Open
Graph Drawing
Framework

 v.2012.05
 

Array.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
00007  ***************************************************************/
00008  
00044 #ifdef _MSC_VER
00045 #pragma once
00046 #endif
00047 
00048 #ifndef OGDF_ARRAY_H
00049 #define OGDF_ARRAY_H
00050 
00051 
00052 #include <ogdf/basic/basic.h>
00053 
00054 
00055 namespace ogdf {
00056 
00059 const size_t maxSizeInsertionSort = 40;
00060 
00061 
00063 
00088 #define forall_arrayindices(i, A) \
00089    for(i = (A).low(); i<=(A).high(); ++i)
00090 
00092 
00097 #define forall_rev_arrayindices(i, A) \
00098    for(i = (A).high(); i>=(A).low(); --i)
00099 
00100 
00101 
00103 
00110 template<class E, class INDEX = int> class Array {
00111 public:
00113     Array() { construct(0,-1); }
00114 
00116     explicit Array(INDEX s) {
00117         construct(0,s-1); initialize();
00118     }
00119 
00121     Array(INDEX a, INDEX b) {
00122         construct(a,b); initialize();
00123     }
00124 
00126     Array(INDEX a, INDEX b, const E &x) {
00127         construct(a,b); initialize(x);
00128     }
00129 
00131     Array(const Array<E> &A) {
00132         copy(A);
00133     }
00134 
00135     // destruction
00136     ~Array() {
00137         deconstruct();
00138     }
00139 
00141     INDEX low() const { return m_low; }
00142 
00144     INDEX high() const { return m_high; }
00145 
00147     INDEX size() const { return m_high - m_low + 1; }
00148 
00150     E *begin() { return m_pStart; }
00151 
00153     const E *begin() const { return m_pStart; }
00154 
00156     E *end() { return m_pStop; }
00157 
00159     const E *end() const { return m_pStop; }
00160 
00162     E *rbegin() { return m_pStop-1; }
00163 
00165     const E *rbegin() const { return m_pStop-1; }
00166 
00168     E *rend() { return m_pStart-1; }
00169 
00171     const E *rend() const { return m_pStart-1; }
00172 
00174     const E &operator[](INDEX i) const {
00175         OGDF_ASSERT(m_low <= i && i <= m_high)
00176         return m_vpStart[i];
00177     }
00178 
00180     E &operator[](INDEX i) {
00181         OGDF_ASSERT(m_low <= i && i <= m_high)
00182         return m_vpStart[i];
00183     }
00184 
00186     void swap(INDEX i, INDEX j) {
00187         OGDF_ASSERT(m_low <= i && i <= m_high)
00188         OGDF_ASSERT(m_low <= j && j <= m_high)
00189 
00190         std::swap(m_vpStart[i], m_vpStart[j]);
00191     }
00192 
00194     void init() { init(0,-1); }
00195     
00197 
00200     void init(INDEX s) { init(0,s-1); }
00201 
00203 
00206     void init(INDEX a, INDEX b) {
00207         deconstruct();
00208         construct(a,b);
00209         initialize();
00210     }
00211 
00213     void init(INDEX a, INDEX b, const E &x) {
00214         deconstruct();
00215         construct(a,b);
00216         initialize(x);
00217     }
00218 
00220     Array<E,INDEX> &operator=(const Array<E,INDEX> &array2) {
00221         deconstruct();
00222         copy(array2);
00223         return *this;
00224     }
00225 
00227     void fill(const E &x) {
00228         E *pDest = m_pStop;
00229         while(pDest > m_pStart)
00230             *--pDest = x;
00231     }
00232 
00234     void fill(INDEX i, INDEX j, const E &x) {
00235         OGDF_ASSERT(m_low <= i && i <= m_high)
00236         OGDF_ASSERT(m_low <= j && j <= m_high)
00237 
00238         E *pI = m_vpStart + i, *pJ = m_vpStart + j+1;
00239         while(pJ > pI)
00240             *--pJ = x;
00241     }
00242 
00244 
00249     void grow(INDEX add, const E &x);
00250 
00252 
00256     void grow(INDEX add);
00257 
00259     void permute (INDEX l, INDEX r);
00260 
00262     void permute() {
00263         permute(low(), high());
00264     }
00265     
00267 
00271     inline int binarySearch (const E& x) const {
00272         return binarySearch(x, StdComparer<E>());
00273     }
00274 
00276 
00280     template<class COMPARER>
00281     int binarySearch(const E& e, const COMPARER &comp) const {
00282         if(size() < 2) {
00283             if(size() == 1 && comp.equal(e, m_vpStart[low()]))
00284                 return low();
00285             return low()-1;
00286         }
00287         int l = low();
00288         int r = high();
00289         do {
00290             int m = (r + l)/2;
00291             if(comp.greater(e, m_vpStart[m]))
00292                 l = m+1;
00293             else
00294                 r = m;
00295         } while(r>l);
00296         return comp.equal(e, m_vpStart[l]) ? l : low()-1;
00297     }
00298 
00300 
00305     inline int linearSearch (const E& e) const {
00306         int i;
00307         for(i = size(); i-->0;)
00308             if(e == m_pStart[i]) break;
00309         return i+low(); }
00310 
00312 
00317     template<class COMPARER>
00318     int linearSearch(const E& e, const COMPARER &comp) const {
00319         int i;
00320         for(i = size(); i-->0;)
00321             if(comp.equal(e, m_pStart[i])) break;
00322         return i+low();
00323     }
00324 
00326     inline void quicksort() {
00327         quicksort(StdComparer<E>());
00328     }
00329 
00331     inline void quicksort(INDEX l, INDEX r) {
00332         quicksort(l, r, StdComparer<E>());
00333     }
00334 
00336 
00340     template<class COMPARER>
00341     inline void quicksort(const COMPARER &comp) {
00342         if(low() < high())
00343             quicksortInt(m_pStart,m_pStop-1,comp);
00344     }
00345 
00347 
00352     template<class COMPARER>
00353     void quicksort(INDEX l, INDEX r, const COMPARER &comp) {
00354         OGDF_ASSERT(low() <= l && l <= high())
00355         OGDF_ASSERT(low() <= r && r <= high())      
00356         if(l < r)
00357             quicksortInt(m_vpStart+l,m_vpStart+r,comp);
00358     }
00359 
00360     template<class F, class I> friend class ArrayBuffer; // for efficient ArrayBuffer::compact-method
00361 
00362 private:
00363     E *m_vpStart; 
00364     E *m_pStart;  
00365     E *m_pStop;   
00366     INDEX m_low;    
00367     INDEX m_high;   
00368 
00370     void construct(INDEX a, INDEX b);
00371 
00373     void initialize();
00374 
00376     void initialize(const E &x);
00377 
00379     void deconstruct();
00380 
00382     void copy(const Array<E,INDEX> &A);
00383 
00385     template<class COMPARER>
00386     static void quicksortInt(E *pL, E *pR, const COMPARER &comp) {
00387         size_t s = pR-pL;
00388 
00389         // use insertion sort for small instances
00390         if (s < maxSizeInsertionSort) {
00391             for (E *pI = pL+1; pI <= pR; pI++) {
00392                 E v = *pI; 
00393                 E *pJ = pI;
00394                 while (--pJ >= pL && comp.less(v,*pJ)) {
00395                     *(pJ+1) = *pJ;
00396                 }
00397                 *(pJ+1) = v;
00398             }
00399             return;
00400         }
00401 
00402         E *pI = pL, *pJ = pR;
00403         E x = *(pL+(s>>1));
00404 
00405         do {
00406             while (comp.less(*pI,x)) pI++;
00407             while (comp.less(x,*pJ)) pJ--;
00408             if (pI <= pJ) std::swap(*pI++,*pJ--);
00409         } while (pI <= pJ);
00410 
00411         if (pL < pJ) quicksortInt(pL,pJ,comp);
00412         if (pI < pR) quicksortInt(pI,pR,comp);
00413     }
00414 
00415     OGDF_NEW_DELETE
00416 }; // class Array
00417 
00418 
00419 
00420 
00421 // enlarges array by add elements and sets new elements to x
00422 template<class E, class INDEX>
00423 void Array<E,INDEX>::grow(INDEX add, const E &x)
00424 {
00425     INDEX sOld = size(), sNew = sOld + add;
00426 
00427     // expand allocated memory block
00428     if(m_pStart != 0) {
00429         E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
00430         if(p == 0) OGDF_THROW(InsufficientMemoryException);
00431         m_pStart = p;
00432     } else {
00433         m_pStart = (E *)malloc(sNew*sizeof(E));
00434         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00435     }
00436 
00437     m_vpStart = m_pStart-m_low;
00438     m_pStop   = m_pStart+sNew;
00439     m_high   += add;
00440 
00441     // initialize new array entries
00442     for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00443         new (pDest) E(x);
00444 }
00445 
00446 // enlarges array by add elements (initialized with default constructor)
00447 template<class E, class INDEX>
00448 void Array<E,INDEX>::grow(INDEX add)
00449 {
00450     INDEX sOld = size(), sNew = sOld + add;
00451 
00452     // expand allocated memory block
00453     if(m_pStart != 0) {
00454         E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
00455         if(p == 0) OGDF_THROW(InsufficientMemoryException);
00456         m_pStart = p;
00457     } else {
00458         m_pStart = (E *)malloc(sNew*sizeof(E));
00459         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00460     }
00461 
00462     m_vpStart = m_pStart-m_low;
00463     m_pStop   = m_pStart+sNew;
00464     m_high   += add;
00465 
00466     // initialize new array entries
00467     for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00468         new (pDest) E;
00469 }
00470 
00471 template<class E, class INDEX>
00472 void Array<E,INDEX>::construct(INDEX a, INDEX b)
00473 {
00474     m_low = a; m_high = b;
00475     INDEX s = b-a+1;
00476     
00477     if (s < 1) {
00478         m_pStart = m_vpStart = m_pStop = 0;
00479 
00480     } else {
00481         m_pStart = (E *)malloc(s*sizeof(E));
00482         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00483 
00484         m_vpStart = m_pStart - a;
00485         m_pStop = m_pStart + s;
00486     }
00487 }
00488 
00489 
00490 template<class E, class INDEX>
00491 void Array<E,INDEX>::initialize()
00492 {
00493     E *pDest = m_pStart;
00494     try {
00495         for (; pDest < m_pStop; pDest++)
00496             new(pDest) E;
00497     } catch (...) {
00498         while(--pDest >= m_pStart)
00499             pDest->~E();
00500         free(m_pStart);
00501         throw;
00502     }
00503 }
00504 
00505 
00506 template<class E, class INDEX>
00507 void Array<E,INDEX>::initialize(const E &x)
00508 {
00509     E *pDest = m_pStart;
00510     try {
00511         for (; pDest < m_pStop; pDest++)
00512             new(pDest) E(x);
00513     } catch (...) {
00514         while(--pDest >= m_pStart)
00515             pDest->~E();
00516         free(m_pStart);
00517         throw;
00518     }
00519 }
00520 
00521 
00522 template<class E, class INDEX>
00523 void Array<E,INDEX>::deconstruct()
00524 {
00525     if (doDestruction((E*)0)) {
00526         for (E *pDest = m_pStart; pDest < m_pStop; pDest++)
00527             pDest->~E();
00528     }
00529     free(m_pStart);
00530 }
00531 
00532 
00533 template<class E, class INDEX>
00534 void Array<E,INDEX>::copy(const Array<E,INDEX> &array2)
00535 {
00536     construct(array2.m_low, array2.m_high);
00537 
00538     if (m_pStart != 0) {
00539         E *pSrc = array2.m_pStop;
00540         E *pDest = m_pStop;
00541         while(pDest > m_pStart)
00542             //*--pDest = *--pSrc;
00543             new (--pDest) E(*--pSrc);
00544     }
00545 }
00546 
00547 
00548 // permutes array a from a[l] to a[r] randomly
00549 template<class E, class INDEX>
00550 void Array<E,INDEX>::permute (INDEX l, INDEX r)
00551 {
00552     OGDF_ASSERT(low() <= l && l <= high())
00553     OGDF_ASSERT(low() <= r && r <= high())
00554 
00555     E *pI = m_vpStart+l, *pStart = m_vpStart+l, *pStop = m_vpStart+r;
00556     while(pI <= pStop)
00557         std::swap(*pI++,*(pStart+randomNumber(0,r-l)));
00558 }
00559 
00560 
00561 // prints array a to output stream os using delimiter delim
00562 template<class E, class INDEX>
00563 void print(ostream &os, const Array<E,INDEX> &a, char delim = ' ')
00564 {
00565     for (int i = a.low(); i <= a.high(); i++) {
00566         if (i > a.low()) os << delim;
00567         os << a[i];
00568     }
00569 }
00570 
00571 
00572 // output operator
00573 template<class E, class INDEX>
00574 ostream &operator<<(ostream &os, const ogdf::Array<E,INDEX> &a)
00575 {
00576     print(os,a);
00577     return os;
00578 }
00579 
00580 } // end namespace ogdf
00581 
00582 
00583 #endif