00001
00002
00003
00004
00005
00006
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
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;
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
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 };
00417
00418
00419
00420
00421
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
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
00442 for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00443 new (pDest) E(x);
00444 }
00445
00446
00447 template<class E, class INDEX>
00448 void Array<E,INDEX>::grow(INDEX add)
00449 {
00450 INDEX sOld = size(), sNew = sOld + add;
00451
00452
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
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
00543 new (--pDest) E(*--pSrc);
00544 }
00545 }
00546
00547
00548
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
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
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 }
00581
00582
00583 #endif