确定性跳跃表,可以实现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
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 }
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 }