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插入速度明显比我实现的这个跳表快很多,这点我需要研究一下。看看为啥我这个这么慢