Open
Graph Drawing
Framework

 v.2010.10
 

Array.h

Go to the documentation of this file.
00001 /*
00002  * $Revision: 2047 $
00003  * 
00004  * last checkin:
00005  *   $Author: klein $ 
00006  *   $Date: 2010-10-13 17:12:21 +0200 (Wed, 13 Oct 2010) $ 
00007  ***************************************************************/
00008  
00054 #ifdef _MSC_VER
00055 #pragma once
00056 #endif
00057 
00058 #ifndef OGDF_ARRAY_H
00059 #define OGDF_ARRAY_H
00060 
00061 
00062 #include <ogdf/basic/basic.h>
00063 
00064 
00065 namespace ogdf {
00066 
00069 const size_t maxSizeInsertionSort = 40;
00070 
00071 
00073 
00098 #define forall_arrayindices(i, A) \
00099    for(i = (A).low(); i<=(A).high(); ++i)
00100 
00102 
00107 #define forall_rev_arrayindices(i, A) \
00108    for(i = (A).high(); i>=(A).low(); --i)
00109 
00110 
00111 
00113 
00120 template<class E, class INDEX = int> class Array {
00121 public:
00123     Array() { construct(0,-1); }
00124 
00126     explicit Array(INDEX s) {
00127         construct(0,s-1); initialize();
00128     }
00129 
00131     Array(INDEX a, INDEX b) {
00132         construct(a,b); initialize();
00133     }
00134 
00136     Array(INDEX a, INDEX b, const E &x) {
00137         construct(a,b); initialize(x);
00138     }
00139 
00141     Array(const Array<E> &A) {
00142         copy(A);
00143     }
00144 
00145     // destruction
00146     ~Array() {
00147         deconstruct();
00148     }
00149 
00151     INDEX low() const { return m_low; }
00152 
00154     INDEX high() const { return m_high; }
00155 
00157     INDEX size() const { return m_high - m_low + 1; }
00158 
00160     E *begin() { return m_pStart; }
00161 
00163     const E *begin() const { return m_pStart; }
00164 
00166     E *end() { return m_pStop; }
00167 
00169     const E *end() const { return m_pStop; }
00170 
00172     E *rbegin() { return m_pStop-1; }
00173 
00175     const E *rbegin() const { return m_pStop-1; }
00176 
00178     E *rend() { return m_pStart-1; }
00179 
00181     const E *rend() const { return m_pStart-1; }
00182 
00184     const E &operator[](INDEX i) const {
00185         OGDF_ASSERT(m_low <= i && i <= m_high)
00186         return m_vpStart[i];
00187     }
00188 
00190     E &operator[](INDEX i) {
00191         OGDF_ASSERT(m_low <= i && i <= m_high)
00192         return m_vpStart[i];
00193     }
00194 
00196     void swap(INDEX i, INDEX j) {
00197         OGDF_ASSERT(m_low <= i && i <= m_high)
00198         OGDF_ASSERT(m_low <= j && j <= m_high)
00199 
00200         std::swap(m_vpStart[i], m_vpStart[j]);
00201     }
00202 
00204     void init() { init(0,-1); }
00205     
00207 
00210     void init(INDEX s) { init(0,s-1); }
00211 
00213 
00216     void init(INDEX a, INDEX b) {
00217         deconstruct();
00218         construct(a,b);
00219         initialize();
00220     }
00221 
00223     void init(INDEX a, INDEX b, const E &x) {
00224         deconstruct();
00225         construct(a,b);
00226         initialize(x);
00227     }
00228 
00230     Array<E,INDEX> &operator=(const Array<E,INDEX> &array2) {
00231         deconstruct();
00232         copy(array2);
00233         return *this;
00234     }
00235 
00237     void fill(const E &x) {
00238         E *pDest = m_pStop;
00239         while(pDest > m_pStart)
00240             *--pDest = x;
00241     }
00242 
00244     void fill(INDEX i, INDEX j, const E &x) {
00245         OGDF_ASSERT(m_low <= i && i <= m_high)
00246         OGDF_ASSERT(m_low <= j && j <= m_high)
00247 
00248         E *pI = m_vpStart + i, *pJ = m_vpStart + j+1;
00249         while(pJ > pI)
00250             *--pJ = x;
00251     }
00252 
00254 
00259     void grow(INDEX add, const E &x);
00260 
00262 
00266     void grow(INDEX add);
00267 
00269     void permute (INDEX l, INDEX r);
00270 
00272     void permute() {
00273         permute(low(), high());
00274     }
00275     
00277 
00281     inline int binarySearch (const E& x) const {
00282         return binarySearch(x, StdComparer<E>());
00283     }
00284 
00286 
00290     template<class COMPARER>
00291     int binarySearch(const E& e, const COMPARER &comp) const {
00292         if(size() < 2) {
00293             if(size() == 1 && comp.equal(e, m_vpStart[low()]))
00294                 return low();
00295             return low()-1;
00296         }
00297         int l = low();
00298         int r = high();
00299         do {
00300             int m = (r + l)/2;
00301             if(comp.greater(e, m_vpStart[m]))
00302                 l = m+1;
00303             else
00304                 r = m;
00305         } while(r>l);
00306         return comp.equal(e, m_vpStart[l]) ? l : low()-1;
00307     }
00308 
00310 
00315     inline int linearSearch (const E& e) const {
00316         int i;
00317         for(i = size(); i-->0;)
00318             if(e == m_pStart[i]) break;
00319         return i+low(); }
00320 
00322 
00327     template<class COMPARER>
00328     int linearSearch(const E& e, const COMPARER &comp) const {
00329         int i;
00330         for(i = size(); i-->0;)
00331             if(comp.equal(e, m_pStart[i])) break;
00332         return i+low();
00333     }
00334 
00336     inline void quicksort() {
00337         quicksort(StdComparer<E>());
00338     }
00339 
00341     inline void quicksort(INDEX l, INDEX r) {
00342         quicksort(l, r, StdComparer<E>());
00343     }
00344 
00346 
00350     template<class COMPARER>
00351     inline void quicksort(const COMPARER &comp) {
00352         if(low() < high())
00353             quicksortInt(m_pStart,m_pStop-1,comp);
00354     }
00355 
00357 
00362     template<class COMPARER>
00363     void quicksort(INDEX l, INDEX r, const COMPARER &comp) {
00364         OGDF_ASSERT(low() <= l && l <= high())
00365         OGDF_ASSERT(low() <= r && r <= high())      
00366         if(l < r)
00367             quicksortInt(m_vpStart+l,m_vpStart+r,comp);
00368     }
00369 
00370     template<class F, class I> friend class ArrayBuffer; // for efficient ArrayBuffer::compact-method
00371 
00372 private:
00373     E *m_vpStart; 
00374     E *m_pStart;  
00375     E *m_pStop;   
00376     INDEX m_low;    
00377     INDEX m_high;   
00378 
00380     void construct(INDEX a, INDEX b);
00381 
00383     void initialize();
00384 
00386     void initialize(const E &x);
00387 
00389     void deconstruct();
00390 
00392     void copy(const Array<E,INDEX> &A);
00393 
00395     template<class COMPARER>
00396     static void quicksortInt(E *pL, E *pR, const COMPARER &comp) {
00397         size_t s = pR-pL;
00398 
00399         // use insertion sort for small instances
00400         if (s < maxSizeInsertionSort) {
00401             for (E *pI = pL+1; pI <= pR; pI++) {
00402                 E v = *pI; 
00403                 E *pJ = pI;
00404                 while (--pJ >= pL && comp.less(v,*pJ)) {
00405                     *(pJ+1) = *pJ;
00406                 }
00407                 *(pJ+1) = v;
00408             }
00409             return;
00410         }
00411 
00412         E *pI = pL, *pJ = pR;
00413         E x = *(pL+(s>>1));
00414 
00415         do {
00416             while (comp.less(*pI,x)) pI++;
00417             while (comp.less(x,*pJ)) pJ--;
00418             if (pI <= pJ) std::swap(*pI++,*pJ--);
00419         } while (pI <= pJ);
00420 
00421         if (pL < pJ) quicksortInt(pL,pJ,comp);
00422         if (pI < pR) quicksortInt(pI,pR,comp);
00423     }
00424 
00425     OGDF_NEW_DELETE
00426 }; // class Array
00427 
00428 
00429 
00430 
00431 // enlarges array by add elements and sets new elements to x
00432 template<class E, class INDEX>
00433 void Array<E,INDEX>::grow(INDEX add, const E &x)
00434 {
00435     INDEX sOld = size(), sNew = sOld + add;
00436 
00437     // expand allocated memory block
00438     if(m_pStart != 0) {
00439         E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
00440         if(p == 0) OGDF_THROW(InsufficientMemoryException);
00441         m_pStart = p;
00442     } else {
00443         m_pStart = (E *)malloc(sNew*sizeof(E));
00444         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00445     }
00446 
00447     m_vpStart = m_pStart-m_low;
00448     m_pStop   = m_pStart+sNew;
00449     m_high   += add;
00450 
00451     // initialize new array entries
00452     for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00453         new (pDest) E(x);
00454 }
00455 
00456 // enlarges array by add elements (initialized with default constructor)
00457 template<class E, class INDEX>
00458 void Array<E,INDEX>::grow(INDEX add)
00459 {
00460     INDEX sOld = size(), sNew = sOld + add;
00461 
00462     // expand allocated memory block
00463     if(m_pStart != 0) {
00464         E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
00465         if(p == 0) OGDF_THROW(InsufficientMemoryException);
00466         m_pStart = p;
00467     } else {
00468         m_pStart = (E *)malloc(sNew*sizeof(E));
00469         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00470     }
00471 
00472     m_vpStart = m_pStart-m_low;
00473     m_pStop   = m_pStart+sNew;
00474     m_high   += add;
00475 
00476     // initialize new array entries
00477     for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00478         new (pDest) E;
00479 }
00480 
00481 template<class E, class INDEX>
00482 void Array<E,INDEX>::construct(INDEX a, INDEX b)
00483 {
00484     m_low = a; m_high = b;
00485     INDEX s = b-a+1;
00486     
00487     if (s < 1) {
00488         m_pStart = m_vpStart = m_pStop = 0;
00489 
00490     } else {
00491         m_pStart = (E *)malloc(s*sizeof(E));
00492         if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
00493 
00494         m_vpStart = m_pStart - a;
00495         m_pStop = m_pStart + s;
00496     }
00497 }
00498 
00499 
00500 template<class E, class INDEX>
00501 void Array<E,INDEX>::initialize()
00502 {
00503     E *pDest = m_pStart;
00504     try {
00505         for (; pDest < m_pStop; pDest++)
00506             new(pDest) E;
00507     } catch (...) {
00508         while(--pDest >= m_pStart)
00509             pDest->~E();
00510         free(m_pStart);
00511         throw;
00512     }
00513 }
00514 
00515 
00516 template<class E, class INDEX>
00517 void Array<E,INDEX>::initialize(const E &x)
00518 {
00519     E *pDest = m_pStart;
00520     try {
00521         for (; pDest < m_pStop; pDest++)
00522             new(pDest) E(x);
00523     } catch (...) {
00524         while(--pDest >= m_pStart)
00525             pDest->~E();
00526         free(m_pStart);
00527         throw;
00528     }
00529 }
00530 
00531 
00532 template<class E, class INDEX>
00533 void Array<E,INDEX>::deconstruct()
00534 {
00535     if (doDestruction((E*)0)) {
00536         for (E *pDest = m_pStart; pDest < m_pStop; pDest++)
00537             pDest->~E();
00538     }
00539     free(m_pStart);
00540 }
00541 
00542 
00543 template<class E, class INDEX>
00544 void Array<E,INDEX>::copy(const Array<E,INDEX> &array2)
00545 {
00546     construct(array2.m_low, array2.m_high);
00547 
00548     if (m_pStart != 0) {
00549         E *pSrc = array2.m_pStop;
00550         E *pDest = m_pStop;
00551         while(pDest > m_pStart)
00552             //*--pDest = *--pSrc;
00553             new (--pDest) E(*--pSrc);
00554     }
00555 }
00556 
00557 
00558 // permutes array a from a[l] to a[r] randomly
00559 template<class E, class INDEX>
00560 void Array<E,INDEX>::permute (INDEX l, INDEX r)
00561 {
00562     OGDF_ASSERT(low() <= l && l <= high())
00563     OGDF_ASSERT(low() <= r && r <= high())
00564 
00565     E *pI = m_vpStart+l, *pStart = m_vpStart+l, *pStop = m_vpStart+r;
00566     while(pI <= pStop)
00567         std::swap(*pI++,*(pStart+randomNumber(0,r-l)));
00568 }
00569 
00570 
00571 // prints array a to output stream os using delimiter delim
00572 template<class E, class INDEX>
00573 void print(ostream &os, const Array<E,INDEX> &a, char delim = ' ')
00574 {
00575     for (int i = a.low(); i <= a.high(); i++) {
00576         if (i > a.low()) os << delim;
00577         os << a[i];
00578     }
00579 }
00580 
00581 
00582 // output operator
00583 template<class E, class INDEX>
00584 ostream &operator<<(ostream &os, const ogdf::Array<E,INDEX> &a)
00585 {
00586     print(os,a);
00587     return os;
00588 }
00589 
00590 } // end namespace ogdf
00591 
00592 
00593 #endif