1-2-3 skip list 确定性跳跃表的实现

/Files/rocketfan/determinsticList_readme.pdf
确定性跳跃表,可以实现o(log(n))级别的插入删除和查找,复杂度与二叉搜索树相同,但是实现起来简单许多
这里给出一个实现,不允许重复的key。关于确定性跳跃表的定义及详细介绍,可参展数据结构与算法分析 c语言描述 中文第二版的p357.

//123 skip list 的实现文件
  1  /*
  2   *  \file determin_skip_list.h
  3   *  \author pku_goldenlock
  4   *  \date  2009-8-7
  5    */
  6 
  7  #ifndef _DETERMIN_SKIP_LIST_H
  8  #define  _DETERMIN_SKIP_LIST_H
  9 
 10  #define  DISALLOW_COPY_AND_ASSIGN(TypeName) \
 11      TypeName( const  TypeName & ); \
 12       void   operator = ( const  TypeName & )
 13 
 14  #include  < iostream >
 15//  #include  " skip_list.h "
 16  namespace  skip_list {
 17 
 18  /* *
 19   * class SkipNode. 
 20   * the node type for DeterminSkipList to operate.
 21    */
 22  template  < typename ElemType >
 23  class  SkipNode {
 24       public :
 25          template  < typename T >   friend  class  DeterminSkipList;
 26          SkipNode();
 27          SkipNode( const  ElemType  & key_input, SkipNode  * right_input  =  NULL, 
 28                   SkipNode  * down_input  =  NULL);
 29       private :
 30          DISALLOW_COPY_AND_ASSIGN(SkipNode);  /* * Do not all copy and assign */
 31          ElemType key;        /* *< The key is what we use for comparing during Search,Insert,Remove. */
 32          SkipNode  * right;     /* *< Point to the right skip node ont the same level */
 33          SkipNode  * down;      /* *< Point to the lower level skip node where we will go down from current node  */
 34  };
 35 
 36  template  < typename ElemType >
 37  SkipNode < ElemType > ::SkipNode() : right(NULL), down(NULL) {}
 38 
 39  template  < typename ElemType >
 40  SkipNode < ElemType > ::SkipNode( const  ElemType &  key_input, SkipNode  * right_input, 
 41                               SkipNode  * down_input)
 42      : key(key_input), right(right_input), down(down_input) {}
 43 
 44  /*  *
 45   * DeterminSkipList
 46   * An implementaion of skip list using 1-2-3 skip list
 47    */
 48  template  < typename ElemType >
 49  class  DeterminSkipList {
 50       public :
 51           /* * Client should determin Max and Max + 1 value */
 52          DeterminSkipList( const  ElemType  & max, const  ElemType  & max_1);
 53           ~ DeterminSkipList();
 54           /* * Clear the whoe skip list free all allocated resouces on heap */
 55           void  Clear();
 56           bool  Search( const  ElemType  & value)  const
 57           /* *
 58           * If the list already has one node whose key == value
 59           * return false and do not do insert otherwise insert a new node with
 60           * its key == value and return true
 61            */
 62           bool  Insert( const  ElemType  & value);
 63           /* *
 64           * If the list already has one node whose key == value
 65           * remove it and return true otherwise return false
 66            */
 67           bool  Remove( const  ElemType  & value);
 68           /* * For debug */
 69           /* * Show the internal structure of the skip list */
 70           void  Print()  const
 71           /* * Return false if current structure of the skip list is wrong */
 72           bool  IsValid()  const ;
 73          
 74       private :
 75           /* * For simplicty here do not allow copy and assign */
 76          DISALLOW_COPY_AND_ASSIGN(DeterminSkipList);
 77           void  Init();
 78           void  ClearHelp(SkipNode < ElemType >   * current);
 79           /* *
 80           * Helper function for Search
 81           * If could not find one node with key value == item return bottom
 82           * otherwise return postion of node containing the key
 83           *  */
 84          SkipNode < ElemType >   *  SearchHelp( const  ElemType  & value)  const
 85           /* * Helper function for Remove, find all the nodes with key == value and modify it to other_value */
 86           void  FindAndModifyRemoveHelp( const  ElemType  & value,  const  ElemType  & other_value);
 87           /* * lower the head if possible during Remove help to keep skip list structure consistent */
 88           void  LowerHeadRemoveHelp();
 89     
 90       private :
 91           // actual data skip list store
 92          SkipNode < ElemType >   * head;    /* *< where we start */
 93          SkipNode < ElemType >   * bottom;  /* *< mark if we have down to the lowerest level */
 94          SkipNode < ElemType >   * tail;    /* *< mark the end of each level */
 95 
 96           const  ElemType Max;          /* *< Max > any client input key value */
 97           const  ElemType Max_1;        /* *< Max_1 > Max */
 98  };
 99 
100  template  < typename ElemType >
101  DeterminSkipList < ElemType > ::DeterminSkipList( const  ElemType  & max,  const  ElemType  & max_1)
102      : head(NULL), bottom(NULL), tail(NULL), Max(max), Max_1(max_1)
103  {
104      Init();
105  }
106 
107  template  < typename ElemType >
108  DeterminSkipList < ElemType > :: ~ DeterminSkipList()
109  {
110       if  (head) {
111          Clear();
112      }
113  }
114 
115  template  < typename ElemType >
116  void  DeterminSkipList < ElemType > ::Init()
117  {
118       // init head bottom and tail see paper p372 figure 6
119      bottom  =   new  SkipNode < ElemType > ;
120      bottom -> right  =  bottom -> down  =  bottom;
121     
122      tail  =   new  SkipNode < ElemType > (Max_1);
123      tail -> right  =  tail;
124 
125      head  =   new  SkipNode < ElemType > (Max, tail, bottom);
126  }
127 
128  template  < typename ElemType >
129  void  DeterminSkipList < ElemType > ::Clear()
130  {
131      ClearHelp(head -> down);
132      delete head;
133      delete bottom;
134      delete tail;
135      head  =  NULL;
136      bottom  =  NULL;
137      tail  =  NULL;
138  }
139 
140  template  < typename ElemType >
141  void  DeterminSkipList < ElemType > ::ClearHelp(SkipNode < ElemType >   * current)
142  {
143      SkipNode < ElemType >   * temp;
144       if  (current  ==  bottom)
145           return ;
146      ClearHelp(current -> down);
147       while  (current  !=  tail) {
148          temp  =  current;
149          current  =  current -> right;
150          delete temp;
151      }
152  }
153 
154  template  < typename ElemType >
155  inline  bool  DeterminSkipList < ElemType > ::Search( const  ElemType  & value)  const
156  {
157       return  ((SearchHelp(value)  ==  bottom)  ?   false  :  true  ); 
158  }
159 
160  template  < typename ElemType >
161  SkipNode < ElemType >   *  DeterminSkipList < ElemType > ::
162          SearchHelp( const  ElemType  & value)  const
163  {
164      SkipNode < ElemType >   * current;
165 
166      current  =  head;
167       while  (current  !=  bottom) {
168           while  (value  >  current -> key)
169              current  =  current -> right;
170           if  (current -> down  ==  bottom)
171               return  ((value  ==  current -> key)  ?  current : bottom);
172          current  =  current -> down;
173      }
174       return  NULL;
175  }
176 
177  /*
178   * Insert a key value to the skip list.
179   * if that the key value has already existed. 
180   * return false and will not insert.  
181   * else insert and return true.
182    */
183  template  < typename ElemType >
184  bool  DeterminSkipList < ElemType > ::Insert( const  ElemType  & value)
185  {
186      SkipNode < ElemType >   * current,  * new_node;
187      
188      current  =  head;
189      bottom -> key  =  value;
190       bool  can_insert  =   true ;
191       while  (current  !=  bottom) {
192           while  (value  >  current -> key) 
193              current  =  current -> right;
194           // if exists one elem whose key == value return false do not need insert
195           if  ((current -> down  ==  bottom)  &&  (value  ==  current -> key)) {
196              can_insert  =   false // can not insert but should check if need to adjust head before return
197               break ;
198          }
199           // if gap size is 3 or at bottom level and must insert 
200           // then promote the middle element
201           if  ((current -> down  ==  bottom)
202                ||  (current -> key  >  current -> down -> right -> right -> key)) {
203              new_node  =   new  SkipNode < ElemType > ;
204              new_node -> right  =  current -> right; 
205              new_node -> down  =  current -> down -> right -> right;
206              current -> right  =  new_node;
207              new_node -> key  =  current -> key;
208              current -> key  =  current -> down -> right -> key;
209          }
210          current  =  current -> down;
211      }
212       // if need to raise the height of the skip list,raise it
213       if  (head -> right  !=  tail) {
214          new_node  =   new  SkipNode < ElemType > ;
215          new_node -> down  =  head;
216          new_node -> right  =  tail;
217          new_node -> key  =  Max;
218          head  =  new_node;
219      }
220 
221       return  can_insert;
222  }
223  template  < typename ElemType >
224  void  DeterminSkipList < ElemType > ::FindAndModifyRemoveHelp( const  ElemType  & value,  const  ElemType  & other_value)
225  {
226      SkipNode < ElemType >   * current;
227 
228      current  =  head;
229       while  (current  !=  bottom) {
230           while  (value  >  current -> key)
231              current  =  current -> right;
232           if  (value  ==  current -> key)
233              current -> key  =  other_value;
234          current  =  current -> down;
235      }
236 
237  }
238  template  < typename ElemType >
239  void  DeterminSkipList < ElemType > ::LowerHeadRemoveHelp()
240  {
241      SkipNode < ElemType >   * temp;
242       if  (head -> down -> right  ==  tail) {
243          temp  =  head -> down;
244          head -> down  =  temp -> down;
245          delete temp;
246      }
247  }
248  template  < typename ElemType >
249  bool  DeterminSkipList < ElemType > ::Remove( const  ElemType  & value)
250  {
251       // empty list can not remove
252       if  (head -> down  ==  bottom)
253           return   false ;
254       // current node, previous node of current, start mark the begining of each level when the node goes down
255       // if previous finally equal to start means have not advanced toward right on this level
256       // next save the start position of the next level for current node
257      SkipNode < ElemType >   * current,  * previous,  * temp,  * next;
258 
259      current  =  head -> down;
260       int  visit_num  =   0 ;
261       bool  can_remove  =   true
262       for (;;) {   // loop and will return when curent->down == bottom
263          previous  =  NULL;
264           while  (value  >  current -> key) {    // try advance toward right as far as possible
265              previous  =  current;
266              current  =  current -> right;
267          }
268           // visit num will mark if a node is a height 1 node 
269           if  (value  ==  current -> key)   
270              visit_num ++ ;
271 
272           // if on level 1 try to remove if possible and return
273           if  (current -> down  ==  bottom) {
274               if  (visit_num  ==   0 ) {        // can not find do not  need to remove
275                  LowerHeadRemoveHelp();  /// might need to lower the head
276                  can_remove  =   false ;
277                   return   false ;
278              }
279               else  {  // need to remove 
280                   if (visit_num  ==   1 ) {   // if node height == 1 just remove it
281                       // delete need to consider down fild of the upper level
282                       // so swap current and current->right
283                      temp  =  current -> right;  // to be deleted
284                      current -> key  =  current -> right -> key;
285                      current -> right  =  temp -> right;
286                      delete temp;
287                      LowerHeadRemoveHelp();  /// might need to lower the head
288                  }  else  {    
289                       // if current node height > 1, swap the key with neighbour than delete the neighbour
290                       // here swap with left neigbour,notice we must have advaced right on 
291                       // this level otherwise it must be a height 1 node.
292                       // we will find all the node with key value current->key and modify it 
293                       // to previous->key
294                      LowerHeadRemoveHelp();  // need to make sure the sturcture correct first
295                      FindAndModifyRemoveHelp(current -> key, previous -> key); 
296                      previous -> right  =  current -> right; 
297                      delete current;
298                  }
299                   return   true ;
300              }
301          } 
302           // on other levels ,not level 1
303           // save the postion to go down on the lower level
304          next  =  current -> down;   // the next level will be unchaged when dealing the current level
305           // current->key == current->down->right->key means the gap we want to down 
306           // is of size only 1
307           if  (current -> key  ==  current -> down -> right -> key) {
308               // the first gap case, consider current gap and the next
309               if  (previous  ==  NULL) {   // have not advanced on this level
310                   // if the next gap has 2 or more one level lower element 
311                   // one element need to lower down,the other one need to raise one level, 
312                   // just swap do not need to delte space
313                   if  (current -> right -> key  >  current -> right -> down -> right -> key) {
314                      current -> key  =  current -> right -> down -> key;
315                      current -> right -> down  =  current -> right -> down -> right;
316                  }  else  {
317                       // one element need to lower down,need to delete space
318                      temp  =  current -> right;
319                      current -> key  =  temp -> key;
320                      current -> right  =  temp -> right;
321                      delete temp; 
322                  }
323              }  else  {     // not the first so consider the privious gap and the current
324                   if  (previous -> key  >  previous -> down -> right -> key) { 
325                      temp  =  previous -> down -> right;
326                       if  (temp -> right -> key  !=  previous -> key)
327                          temp  =  temp -> right;
328                      previous -> key  =  temp -> key;
329                      current -> down  =  temp -> right;
330                  }  else  {                       
331                      previous -> key  =  current -> key;
332                      previous -> right  =  current -> right;
333                      delete current;
334                  }
335              }
336          } 
337          current  =  next;  // go to the next level (one level lower)
338      }
339  }
340 
341  template  < typename ElemType >
342  bool  DeterminSkipList < ElemType > ::IsValid()  const
343  {
344      SkipNode < ElemType >   * current,  * temp,  * temp2;
345       int  gap_size;
346 
347      current  =  head;
348       while  (current -> down  !=  bottom) {
349          temp  =  current;
350           while  (temp  !=  tail) {
351              temp2  =  temp -> down;
352              gap_size  =   0 ;
353               while (temp2 -> key  !=  temp -> key) {
354                  gap_size ++ ;
355                  temp2  =  temp2 -> right;
356              }
357               if  (gap_size  <   1   ||  gap_size  >   3 )
358                   return   false ;
359              temp  =  temp -> right;
360          }
361          current  =  current -> down;
362      }
363       return   true ;
364  }
365 
366 
367  template  < typename ElemType >
368  void  DeterminSkipList < ElemType > ::Print()  const  
369  {
370       using   namespace  std;
371      SkipNode < ElemType >   * current,  * temp;
372 
373      current  =  head;
374       while  (current  !=  bottom) {
375          temp  =  current;
376           while  (temp  !=  NULL) {
377               if  (temp  !=  tail) {
378                  cout  <<  temp -> key  <<   " ( "  
379                        <<  temp -> down -> key  <<   " " ;
380                  temp  =  temp  ->  right;
381              }  else  {
382                  cout  <<  temp -> key  <<   " [ "  
383                        <<   " tail "   <<   " " ;
384                  temp  =  NULL;
385              }
386          }
387          cout  <<  endl;
388          current  =  current -> down;
389      }
390      cout  <<  endl;
391  }
392 
393 
394  // end fo namespace skip_list
395 
396  #endif   // end of _DETERMIN_SKIP_LIST_H

//123 skip list 的测试文件
 1  #include  < iostream >
 2  #include  < string >
 3  #include  < fstream >
 4 
 5  #include  " determin_skip_list.h "
 6 
 7  using   namespace  std;
 8  using   namespace  skip_list;
 9 
10  /* *
11   * TestSkipList is the kernal test fuction of Insert,Search and Remove of a
12   * determinstic skip list.
13   * @param skip_list is the user created empty skip list for test
14   * @param in is the ifstream relating to the opened file
15   * @param out is the ofstream relating to the file to write result
16    */
17  template  < typename T >
18  void  TestSkipList(DeterminSkipList < T >   & skip_list, ifstream  & in , ofstream  & out
19  {
20       string  op;
21       string  value;
22       /// loop to get input and to corresponding operation on skip_list
23       /// and write the result to the out put file
24       while ( in   >>  op  >>  value) {
25           if  (op  ==   " INS " ) {
26               if  (skip_list.Insert(value))
27                   out   <<  op  <<   "   "   <<  value  <<  endl;
28               else
29                   out   <<   " DUP "   <<   "   "   <<  value  <<  endl;
30          }  else   if  (op  ==   " FIND " ) {
31               if  (skip_list.Search(value))
32                   out   <<  op  <<   "   "   <<  value  <<  endl;
33               else
34                   out   <<   " NONE "   <<   "   "   <<  value  <<  endl;
35          }  else   if  (op  ==   " REM " ) {
36               if  (skip_list.Remove(value))
37                   out   <<  op  <<   "   "   <<  value  <<  endl;
38               else
39                   out   <<   " NONE "   <<   "   "   <<  value  <<  endl;
40          }
41           if  ( ! skip_list.IsValid())
42              cout  <<   " not valid for  "   <<  op  <<   "   "   <<  value  <<  endl; 
43      }
44  }
45 
46  int  main( int  argc,  char   * argv[])
47  {
48       if  (argc  !=   3 ) {
49          cout  <<   " Usage is :  "  
50                <<   " test_determin_skip_list <input_file> <output_file> "  
51                <<  endl;
52           return   - 1 ;
53      }
54       /// argv[1] the name of the file to open
55       /// argv[2] the name of the file to wirte
56      ifstream  in (argv[ 1 ]);
57       if  ( ! in ) {
58          cout  <<   " Could not find the file named  "
59                <<  argv[ 1 <<   "  to open! " <<  endl;
60           return   - 1 ;
61      }
62      ofstream  out (argv[ 2 ]);
63       /// create a empty skip list key type is string,
64       /// assumming for any input key value
65       /// key value  < Max < Max_1
66      char a[2];
67      a[ 0 =   char ( 254 ); a[ 1 =   ' \0 ' ;
68       const   string  Max(a);
69      a[ 0 =   char ( 255 );
70       const   string  Max_1(a);
71      DeterminSkipList < string >  skip_list(Max, Max_1); 
72 
73       try  {
74          TestSkipList(skip_list,  in out );  /// The main test process
75      }  catch (std::bad_alloc & ) {  /// will exit if can not allocate more space
76          cout  <<   " no more available memory "   <<  endl;
77           in .close();
78           out .close();
79           return   - 1 ;
80      }
81 
82       in .close();
83       out .close();
84       return   0 ;
85  }

你可能感兴趣的:(list)