123 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, inout); ///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 }
原文地址:https://www.cnblogs.com/rocketfan/p/1556797.html