00001
00002
00003
00004
00005
00006
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
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;
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
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 };
00427
00428
00429
00430
00431
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
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
00452 for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
00453 new (pDest) E(x);
00454 }
00455
00456
00457 template<class E, class INDEX>
00458 void Array<E,INDEX>::grow(INDEX add)
00459 {
00460 INDEX sOld = size(), sNew = sOld + add;
00461
00462
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
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
00553 new (--pDest) E(*--pSrc);
00554 }
00555 }
00556
00557
00558
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
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
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 }
00591
00592
00593 #endif