#ifndef SKIPLIST_H #define SKIPLIST_H //#define DEBUG #ifdef DEBUG #include #endif #ifndef RCITLIST_H #include #endif #ifndef DARRAY_H #include #endif #ifndef __STDLIB_H #include #endif // This implementation of a skip list uses the type Tower as a descendent of // *Link* the node class found in *rcitlist.h*. Tower will create new virtual // functions *insert*, *getNext*, and *removeNext* that will take into account // the multiple links found in a skip list node. SkipIterator will also // be implemented to replace ListIterator in the call to List::insert. const TowerHeight = 4; // Article on skip lists recommends the following randomLevel function // to get a good distribution of values at different levels. // The simple random function seems to do just as well. /*const double PickLevel = 0.75;//also try 0.5 int randomLevel() { int newLevel=0; while ((PickLevel > random(100)/100.0)&& (newLevel < TowerHeight-1)) newLevel++; return newLevel; } */ // **** randomLevel not needed //***** class Tower template class Tower :public Link { public: Tower(int h); Tower(Type val,Link *next, Tower nextOnes,int h = 0); // If all pointers point to list nodes, let list distructor get rid of // the pointers. Link* insert(Type val,Tower nextOnes,int h); Link* getNextOne(int level);//returns pointer to next node at level // virtual Link* removeNext();// removes next node and adjusts next to next->next int getHeight(){return height;} Link* & operator [](int i) {return tower[i];} protected: Array*> tower; int height; }; //***** class SkipList template class SkipIterator; template class SkipList :public List { public: SkipList(int h = TowerHeight); ~SkipList(); virtual ListIterator* genIterator();// generates an iterator for a type of list virtual void add(const Type &value); // add to head of List void printLevels(); protected: int tallest; //tallest tower currently in list int height; // tallest possible tower Tower firstPointers; List::_size; List::ptrToFirstItem; friend SkipIterator; }; //***** class SkipIterator template class SkipIterator :public OrderedIterator { public: SkipIterator (SkipList&); ~SkipIterator(); virtual int init(); //sets up the local tower and calls ListIterator::init() virtual int locate(const Type&);// locate the first occurrence of an item virtual void addBefore(const Type &newValue); // add before current location virtual void removeCurrent();// removes the item current from the list protected: virtual void moveToNext(); //advances one through list // height, tallest, firstPointers, _size and firstItem // are needed to have access to // their counterparts in the list. int &height; int &tallest; int &_size; Tower &firstPointers; List::RCPtr *firstItem; int currentLevel; // current level in traversal Tower history;//list of previous pointers for backfill. Tower nextOnes;// list of next items }; //*********** Code for classes ************** //********** Tower functions ************** template Tower::Tower(int h=TowerHeight):tower(h,0) { height = h; for(int i = 0;i Tower::Tower(Type val,Link *next,Tower nextOnes,int h = 0) :tower(h,0),Link(val,next) { height = h; for(int i = 0;i Link* Tower::insert(Type val,Tower nextOnes,int h) { ptrToNextLink =new Tower(val,ptrToNextLink,nextOnes,h); assert(ptrToNextLink != NULL); return ptrToNextLink; } template Link* Tower::getNextOne(int level) { if ((level >= 0)&& (level < height)) return tower[level]; else if(level == -1) return getNext(); #ifdef DEBUG else { cout<<"The node containning "< SkipList::SkipList(int h = TowerHeight) :List(),firstPointers(h) { randomize(); height = h; tallest = 0; } template SkipList::~SkipList() { } template ListIterator* SkipList::genIterator() { ListIterator* returnVal = new SkipIterator(*this); return returnVal; } template void SkipList::add(const Type &value) // add to head of List { int level = random(height);//randomLevel(); // zero level is always possible if (level > tallest) tallest = level; #ifdef DEBUG cerr<<"In add adding "< *temp = new Tower(value,(Tower*)ptrToFirstItem->data,firstPointers,level); assert(temp != NULL); ptrToFirstItem->data = temp; _size++; // connect this new node up to the level of its tower for (int i = 0; i< level;i++) firstPointers[i] = temp; } template void SkipList::printLevels() { for(int i = tallest-1;i>=0;i--) { cout<<"*********\nlevel "< *now = firstPointers[i]; while (now) { cout<value()<<' '; now = ((Tower*)now)->getNextOne(i); } cout< SkipIterator::SkipIterator(SkipList &l) :OrderedIterator(l),height(l.height),tallest(l.tallest), _size(l._size),history(height),nextOnes(height), firstPointers(l.firstPointers),firstItem(l.ptrToFirstItem) { init(); } template SkipIterator::~SkipIterator() { } template int SkipIterator::init() { ListIterator::init(); currentLevel = tallest-1;//Start at the shallowest list (the top) if (currentLevel >=0) current = firstPointers[currentLevel]; //look as far as possible into list return current != NULL; // otherwise current is data->ptrToFirstItem set in ListIterator::init() } template void SkipIterator::moveToNext() { previous = current; current = ((Tower*)current)->getNextOne(currentLevel); } template int SkipIterator::locate(const Type &val) { init(); //start at the beginning #ifdef DEBUG cout<<"Seaching for "<=-1)//search at each level -1 is link level { #ifdef DEBUG if(current) cout<<"current item "<value()<<" "; else cout<<"current is NULL "; #endif while (current && current->value() < val) { moveToNext(); #ifdef DEBUG if (current) cout<<" Moving to next item of "<value()<<' '; else cout<<" Next item NULL "<=0) // save place for backfilling if insert or delete { history[currentLevel] = previous; nextOnes[currentLevel] = current; } if (--currentLevel >=-1) // go to next level and find next item { if (previous) current = ((Tower*)previous)->getNextOne(currentLevel); else if(currentLevel >= 0) current = firstPointers[currentLevel]; else current = firstItem->data; } #ifdef DEBUG cout<value() == val)) return 1; else return 0; } template void SkipIterator::addBefore(const Type &newValue) // add before current location { if(previous)// insert in the middle of the list { int newLevel = random(height);//randomLevel();// #ifdef DEBUG cout<<"In addBefore adding "<*)previous)->insert(newValue,nextOnes,newLevel); // if new node is taller than all previous nodes it must be connected // to the beginning of the list. if (newLevel > tallest) { for(int i = tallest;i*)history[i]))[i]=previous;//set the next pointer for previous towers _size++; } else //insert at the beginning of the list theList.add(newValue); _pos++; } template void SkipIterator::removeCurrent() { #ifdef DEBUG cout<<"\n********In removeCurrent with current value "<value()<*)current)->getHeight()>0)) { // adjust the first pointers because the first thing in list // has been removed. #ifdef DEBUG cout<<"Must have previous == NULL. Next values are\n"; for(int j =0;j<((Tower*)current)->getHeight();j++) { cout<<"level "<*)current)->getNextOne(j)) cout<<' '<<((Tower*)current)->getNextOne(j)->value()<=0;i--) if (firstPointers[i] == current) { firstPointers[i] = ((Tower*)current)->getNextOne(i); if(firstPointers[i] ==NULL) //tallest is now shorter tallest--; } } else if (current && (((Tower*)current)->getHeight()>0))//used only with current not NULL { //must reconnect history to make sure that list is maintained #ifdef DEBUG cout<<"Next values in removeCurrent\n"; for(int j =0;j<((Tower*)current)->getHeight();j++) { cout<<"level "<*)current)->getNextOne(j)) cout<<' '<<((Tower*)current)->getNextOne(j)->value()<*)current)->getHeight();i++) if(history[i]) //if there is a prior node set next pointer (*((Tower*)history[i]))[i]= ((Tower*)current)->getNextOne(i);//set the next pointer for previous towers else//nothing before current here so readjust { firstPointers[i] =((Tower*)current)->getNextOne(i); if(firstPointers[i] ==NULL) //tallest is now shorter tallest--; } } ListIterator::removeCurrent();//takes care of the list connections } #endif