实现跳表

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #define CASE_NUM 20000
  4 #define LEVEL 10
  5 
  6 struct Node 
  7 {
  8     int value;
  9     int level;
 10     struct Node* down_p;
 11     struct Node* next;
 12 };
 13 
 14 struct Node* init_skip_list(int level)
 15 {
 16     int i;
 17 
 18     struct Node* NodeList[level];
 19     for(i=0; i<level; ++i)
 20     {
 21         NodeList[i] = (struct Node*)malloc(sizeof(struct Node));
 22         NodeList[i]->next = NULL;
 23         NodeList[i]->value = 0;
 24         NodeList[i]->level = i+1;
 25         if(i>0)
 26         {
 27             NodeList[i]->down_p = NodeList[i-1];
 28             printf("build down forward, level=%d
", i+1);
 29         } 
 30         else 
 31         {
 32             NodeList[i]->down_p = NULL;
 33         }
 34     }
 35     return NodeList[level-1];
 36 }
 37 
 38 int get_rand_level(int level)
 39 {
 40     int value_level = 1;
 41     while(rand()%2) value_level ++;
 42     if(value_level > level) value_level = level;
 43     return value_level;
 44 }
 45 
 46 int insert_number(int value, struct Node* node, int level)
 47 {
 48     int value_level;
 49     int i;
 50     int cost_step = 0;
 51     value_level = get_rand_level(level);
 52 
 53     struct Node* NodeList[level];
 54     int level_run[level];
 55 
 56     for(i=0; i<level; ++i) level_run[i] = 0;
 57 
 58     struct Node* tmp; // temp storage node
 59     tmp = NULL;
 60     int insert = 0;
 61     while(node != NULL)
 62     {
 63         insert = node->level <= value_level ? 1 : 0;
 64 
 65         struct Node* new_node;
 66         new_node = (struct Node*)malloc(sizeof(struct Node));
 67         new_node->value = value;
 68         new_node->level = node->level;
 69         new_node->down_p = NULL;
 70 
 71         while(1)
 72         {
 73             if(node->next && node->next->value < value)
 74             {
 75                 node = node->next;
 76                 cost_step ++;
 77                 level_run[node->level-1] ++;
 78             } 
 79             else
 80             {
 81                 if(insert)
 82                 {
 83                     new_node->next = node->next;
 84                     node->next = new_node;
 85                     if(tmp != NULL)
 86                     {
 87                         tmp->down_p = new_node;
 88                     }
 89                     tmp = new_node;
 90                 }
 91                 /*
 92                 else
 93                 {
 94                     printf("Now level is %d, need create under %d level
",
 95                             node->level, value_level);
 96                 }
 97                 */
 98                 //printf("Success insert new node, value=%d, level=%d
",
 99                 //        value, i+1);
100                 break;
101             }
102         }
103         node = node->down_p;
104     }
105     /* DEBUG PIRNT
106     printf("---- value %d cost step ----
", value);
107     for(i=0; i<level; ++i)
108     {
109         printf("level %d cost step %d
", i+1, level_run[i]);
110     }
111     */
112     return cost_step;
113 }
114 
115 int find_number(int value, struct Node* node)
116 {
117     int i;
118     int find = 0;
119     int cost_step = 0;
120     while(node != NULL)
121     {
122         //printf("node->value=%d, node->level=%d, node->down_p=%p, node->next=%p
", 
123         //        node->value, node->level, node->down_p, node->next);
124         while(node->next && node->next->value<=value)
125         {
126             //printf("step forward one step
");
127             node = node->next;
128             cost_step ++;
129         }
130         if(node->value == value)
131         {
132             find = 1;
133             break;
134         }
135         //printf("node->down_p->value=%d, node->down_p->level=%d, node->down_p->down_p=%p
",
136         //        node->down_p->value, node->down_p->level, node->down_p->down_p);
137         node = node->down_p;
138         cost_step ++;
139     }
140     //printf("find %d cost step %d
", value, cost_step);
141     if(find!=1)
142     {
143         printf("Warning, error occured, value=%d
", value);
144     }
145     return cost_step;
146 }
147 
148 void show_skip_list(struct Node* node, int level)
149 {
150     int i;
151     struct Node* NodeList[level];
152     struct Node* p;
153     int NodeCnt[level];
154     for(i=0; i<level; ++i)
155     {
156         NodeList[level-i-1] = node;
157         node = node->down_p;
158         NodeCnt[i] = 0;
159     }
160 
161     for(i=level-1; i>=0; --i)
162     {
163         int sign = 0;
164         p = NodeList[i];
165         while(p)
166         {
167             /*
168             if(sign)
169             {
170                 printf(" -> %d", p->value);
171             }
172             else
173             {
174                 printf("%d", p->value);
175             }
176             */
177             sign = 1;
178             NodeCnt[i] ++;
179             p = p->next;
180         }
181         //printf("
");
182     }
183     for(i=0; i<level; ++i) printf("level %d cnt %d
", i+1, NodeCnt[i]);
184     return;
185 }
186 
187 int main()
188 {
189     int level = LEVEL;
190     int res;
191     int i;
192     int tmp;
193     struct Node* p;
194     p = init_skip_list(level);
195 
196     int test_data[CASE_NUM];
197     long long total_insert_cost_step = 0;
198     int one_time;
199     
200     for(i=0; i<CASE_NUM; i++)
201     {
202         tmp = rand()%1000000;
203         test_data[i] = tmp;
204         one_time = insert_number(tmp, p, level);
205         total_insert_cost_step += one_time;
206         //printf("inserting %d cost %d step
", tmp, one_time);
207     }
208     printf("insert average cost %lld step
", total_insert_cost_step/CASE_NUM);
209     printf("Begin show_skip_list
");
210     show_skip_list(p, level);
211     int total_cost_step = 0;
212     for(i=0;i<CASE_NUM;i++)
213     {
214         tmp = test_data[i];
215         res = find_number(tmp, p);
216         total_cost_step += res;
217     }
218     printf("Average cost %d step
", total_cost_step/CASE_NUM);
219     return 0;
220 }

自己手写了一下跳表,加深了对跳表的理解,贴一下代码

输出

insert average cost 21 step
Begin show_skip_list
level 1 cnt 20001
level 2 cnt 10031
level 3 cnt 5087
level 4 cnt 2567
level 5 cnt 1333
level 6 cnt 704
level 7 cnt 367
level 8 cnt 191
level 9 cnt 95
level 10 cnt 51
Average cost 40 step

相比较之下,python的heapq插入速度明显比我实现的这个跳表快很多,这点我需要研究一下。看看为啥我这个这么慢

原文地址:https://www.cnblogs.com/symons1992/p/8719418.html