Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/searchTrees/StairFunc.cpp
Go to the documentation of this file.
00001 
00009 #include "StairFunc.h"
00010 
00011 namespace grafalgo {
00012 
00016 StairFunc::StairFunc(int size) : Adt(size) {
00017         makeSpace(size);
00018 }
00019 
00021 StairFunc::~StairFunc() { freeSpace(); }
00022 
00026 void StairFunc::makeSpace(int size) {
00027         try {
00028                 points = new DkBstSet(2*size+1); free = new List(2*size+1);
00029         } catch (std::bad_alloc e) {
00030                 stringstream ss;
00031                 ss << "makeSpace:: insufficient space for "
00032                    << size << "index values";
00033                 string s = ss.str();
00034                 throw OutOfSpaceException(s);
00035         }
00036         nn = size; clear();
00037 }
00038 
00040 void StairFunc::freeSpace() { delete points; delete free; }
00041 
00046 void StairFunc::clear() {
00047         points->clear(); free->clear();
00048         points->setkey(1,0,0); // initialize function to zero for all x>=0
00049         for (int i = 2; i <= 2*n()+1; i++) free->addLast(i);
00050 }
00051 
00055 void StairFunc::resize(int size) {
00056         freeSpace();
00057         try { makeSpace(size); } catch(OutOfSpaceException e) {
00058                 string s; s = "StairFunc::resize::" + e.toString(s);
00059                 throw OutOfSpaceException(s);
00060         }
00061 }
00062 
00067 void StairFunc::expand(int size) {
00068         if (size <= n()) return;
00069         StairFunc old(this->n()); old.copyFrom(*this);
00070         resize(size); this->copyFrom(old);
00071 }
00072 
00076 void StairFunc::copyFrom(const StairFunc& source) {
00077         if (&source == this) return;
00078         if (source.n() > n()) resize(source.n());
00079         else clear();
00080 
00081         points->copyFrom(*(source.points));
00082         free->copyFrom(*(source.free));
00083 }
00084 
00085 // Return the y value at a specified x coordinate
00086 index StairFunc::value(int x)  {
00087         assert (x >= 0);
00088         index v = points->access(x,points->find(1));
00089         return points->key2(v);
00090 }
00091 
00092 // Return the smallest y value that the function takes on in
00093 // the range [lo,hi]
00094 int StairFunc::findmin(int lo, int hi) {
00095         assert(0 <= lo && lo <= hi);
00096         int min = Util::BIGINT32;
00097         BstSet::BstPair pairA(0,0); BstSet::BstPair pairB(0,0);
00098         
00099         //lowNode is largest node with key1 <= lo
00100         index lowNode = points->access(lo,points->find(1));
00101         //split at lowNode, stuff we want in pairA.t2
00102         pairA = points->split(lowNode, points->find(1));
00103         //if key1(lowNode) == lo, we should include it
00104         if(points->key1(lowNode) >= lo){ min = points->key2(lowNode);}
00105 
00106         //we have 3 trees now, pair.t1, lo, pair.t2     
00107         //within pair.t2, split at the largest node < hi
00108         index hiNode = points->access(hi, points->find(pairA.t2));
00109         pairB = points->split(hiNode, points->find(pairA.t2));
00110         //check if min is at hiNode (hiNode <= hi)
00111         if(points->key2(hiNode) < min){ min = points->key2(hiNode);}
00112         
00113         //last thing to check is min in pairB.t1
00114         if(points->min2(pairB.t1) < min){ min = points->min2(pairB.t1);}
00115         
00116         //reassemble the parts...we have 5 trees now
00117         int hiPortion = points->join(pairB.t1, hiNode, pairB.t2);
00118         points->join(pairA.t1, lowNode, hiPortion);
00119         
00120         return min;
00121 }
00122 
00123 // Add diff to all values in the range lo,hi.
00124 void StairFunc::change(int lo, int hi, int diff) {
00125         assert(0 <= lo && lo <= hi);
00126         // when adding new points to the function, first select unused index
00127         // from free list and insert that point into points
00128         // after removing an index from points, put it back on free
00129         // note - never remove index #1 from the search tree
00130         BstSet::BstPair pairA(0,0); BstSet::BstPair pairB(0,0);
00131         
00132         //lowNode is largest node with key1 <= lo
00133         index lowNode = points->access(lo,points->find(1));
00134         //split at lowNode and hiNode, like findmin func
00135         pairA = points->split(lowNode, points->find(1));
00136         index hiNode = points->access(hi, points->find(pairA.t2));
00137         if(pairA.t2 != 0){
00138                 pairB = points->split(hiNode, points->find(pairA.t2));
00139         }
00140         
00141         //handle edge cases
00142         index insertLo, insertHi;
00143         //if lo == lowNode, add diff to lowNode, don't insert
00144         if (lo == lowNode) {
00145                 points->change2(diff, points->find(lowNode));
00146         } else {
00147                 insertLo = free->first(); free->removeFirst();
00148                 points->setkey(insertLo, lo, diff + points->key2(lowNode));
00149                 if (points->find(pairA.t2) == 0){
00150                         points->insert(insertLo, points->find(lowNode));
00151                 } else {
00152                         points->insert(insertLo, points->find(pairA.t2));
00153                 }
00154         }
00155         //if hi == hiNode, add diff to hiNode, don't insert
00156         if (hi == hiNode) {
00157                 points->change2(diff, points->find(hiNode));
00158         }else{
00159                 insertHi = free->first(); free->removeFirst();
00160                 if(hi>hiNode){//at rightmost of step func
00161                         points->setkey(insertHi, hi+1, 0);
00162                 } else {
00163                         points->setkey(insertHi, hi+1,
00164                                        diff + points->key2(hiNode));
00165                 }
00166                 if (points->find(pairB.t1 != 0)){
00167                         points->insert(insertHi, points->find(pairB.t1));
00168                 } else if (hiNode != 0){
00169                         points->insert(insertHi, points->find(hiNode));
00170                 } else {
00171                         points->insert(insertHi, points->find(lowNode));
00172                 }
00173         }
00174 
00175         //everything in pairB.t1 is within range, add diff to dmin
00176         if(pairB.t1 != 0){
00177                 points->change2(diff, points->find(pairB.t1));
00178         }
00179         
00180         //resemble the parts...we got 5 trees now
00181         int hiPortion = 0;
00182         if(hiNode != 0){
00183                 hiPortion = points->join(pairB.t1, hiNode, pairB.t2);
00184         }
00185         points->join(pairA.t1, lowNode, hiPortion);
00186 }
00187 
00188 string& StairFunc::toString(string& s) const {
00189         stringstream ss;
00190         for (index i = 1; i != 0; i = points->suc(i)) {
00191                 ss << "(" << points->key1(i) << "," << points->key2(i) << ") ";
00192         }
00193         ss << "\n";
00194         s = ss.str();
00195         return s;
00196 }
00197 
00198 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends