• 基数树 radix_tree


    Makefile:
    1
    mytest: radix-tree.o test.o 2 gcc -Wall -fno-builtin $^ -o $@ 3 radix-tree.o: radix-tree.c 4 gcc -c $^ -o $@ 5 test.c: test.o 6 gcc -c $^ -o $@ 7 8 clean: 9 rm radix-tree.o test.o mytest
    用户头文件:radix_tree.h
    1
    #ifndef __JERRY_RADIX 2 #define __JERRY_RADIX 3 4 #include <stdio.h> 5 6 struct radix_tree_head; 7 typedef struct radix_tree_head radix_tree_head; 8 typedef radix_tree_head * Pradix_tree_head; 9 10 #ifdef __cplus_cplus 11 extern "c" { 12 #endif 13 14 extern Pradix_tree_head radix_tree_head_new(void); 15 extern void radix_tree_initial(Pradix_tree_head thiz); 16 extern int radix_tree_destroy(Pradix_tree_head thiz); 17 extern int radix_tree_insert(Pradix_tree_head thiz, unsigned int index, void *item); 18 extern void * radix_tree_lookup(Pradix_tree_head thiz, unsigned index); 19 extern void * radix_tree_delete(Pradix_tree_head thiz, unsigned index); 20 extern unsigned int radix_tree_gang_lookup(Pradix_tree_head thiz, 21 void ** results, 22 unsigned int firs_index, 23 unsigned int max_items); 24 25 #ifdef __cplus_cplus 26 } 27 #endif
    库头文件radix-tree.h
    1
    #ifndef __JERRY_RADIX_TREE__ 2 #define __JERRY_RADIX_TREE__ 3 4 5 #include "radix_tree.h" 6 #include <malloc.h> 7 8 9 #define ARRARY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0]))) 10 11 /** 12 * Radix_tree node definiton 13 */ 14 #if 0 15 #define RADIX_TREE_MAP_SHIFT 8 16 #define RADIX_TREE_MAP_SIZE (1 << RADIX_TREE_MAP_SHIFT) 17 #define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE - 1) 18 #define RADIX_TREE_INDEX_BITS (8 * sizeof(unsigned int)) 19 #define RADIX_TREE_MAX_PATH ( RADIX_TREE_INDEX_BITS / RADIX_TREE_MAP_SHIFT + 1) 20 #endif 21 #define RADIX_TREE_MAP_SHIFT 3 22 #define RADIX_TREE_MAP_SIZE (1 << RADIX_TREE_MAP_SHIFT) 23 #define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE - 1) 24 #define RADIX_TREE_INDEX_BITS (8 * sizeof(unsigned int)) 25 #define RADIX_TREE_MAX_PATH ( 4 ) 26 27 typedef struct radix_tree_node 28 { 29 unsigned int count; 30 void *slots[RADIX_TREE_MAP_SIZE]; 31 }radix_tree_node; 32 33 typedef radix_tree_node * Pradix_tree_node; 34 typedef Pradix_tree_node * PPradix_tree_node; 35 36 struct radix_tree_head 37 { 38 unsigned int height; 39 Pradix_tree_node rnode; 40 unsigned int height_to_maxindex[RADIX_TREE_MAX_PATH]; 41 }; 42 43 struct radix_tree_path 44 { 45 Pradix_tree_node node; 46 PPradix_tree_node slot; 47 }; 48 typedef struct radix_tree_path radix_tree_path; 49 typedef radix_tree_path * Pradix_tree_path; 50 51 #endif /* __JERRY_RADIX_TREE__ */



    radix-tree函数功能实现 
    1
    #include "radix-tree.h" 2 3 /** 4 * calloc radix_tree_node 5 * 6 * return Pointer 7 */ 8 9 static Pradix_tree_node radix_tree_node_alloc() 10 { 11 Pradix_tree_node ret; 12 ret = (Pradix_tree_node)calloc(1, sizeof(radix_tree_node)); 13 if(!ret) 14 { 15 printf("calloc radix_tree_node failed\n"); 16 } 17 return ret; 18 } 19 20 static void radix_tree_node_free(Pradix_tree_node node) 21 { 22 free(node); 23 } 24 25 /** 26 * Return the maximum key which can store a radix tree with height HEIGHT 27 */ 28 static unsigned int radix_tree_maxindex(Pradix_tree_head head) 29 { 30 return head->height_to_maxindex[head->height]; 31 } 32 33 static unsigned int __maxindex(unsigned int height) 34 { 35 unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; 36 /* following strange? one day, you'll konw it, learn more..... 37 * ~0U not ~0, that's different 38 */ 39 unsigned int index = (~0U >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; 40 41 if(tmp >= RADIX_TREE_INDEX_BITS) 42 { 43 index = ~0; 44 } 45 return index; 46 } 47 48 static void radix_tree_init_maxindex(Pradix_tree_head head) 49 { 50 unsigned int i; 51 for(i = 0; i < RADIX_TREE_MAX_PATH ; i++) 52 { 53 head->height_to_maxindex[i] = __maxindex(i); 54 } 55 } 56 static int radix_tree_extend(Pradix_tree_head head, unsigned int index) 57 { 58 Pradix_tree_node node; 59 unsigned int height; 60 61 /* Figure out what the height should be */ 62 height = head->height + 1; 63 //bug: while(index > radix_tree_maxindex(head)) 64 while(index > head->height_to_maxindex[height]) 65 { 66 height++; 67 if(height > RADIX_TREE_MAX_PATH) 68 { 69 printf("index are out of the capacity of radix tree\n"); 70 } 71 } 72 73 if(head->rnode) 74 { 75 do 76 { 77 if(!(node = radix_tree_node_alloc())) 78 { 79 return 1; 80 //return -ENOMEM; 81 } 82 node->slots[0] = head->rnode; 83 /* boys, what is count? how many slots have been occupied */ 84 node->count = 1; 85 head->rnode = node; 86 head->height++; 87 }while(height > head->height); 88 } 89 else 90 { 91 head->height = height; 92 } 93 return 0; 94 } 95 96 /** 97 * insert into a radix tree 98 * @head: radix tree head 99 * @index: index key 100 * @item: item to insert 101 * 102 * Insert an item into the radix tree at position @index 103 */ 104 int radix_tree_insert(Pradix_tree_head head, unsigned int index, void *item) 105 { 106 Pradix_tree_node node = NULL, tmp; 107 PPradix_tree_node slot; 108 unsigned int height, shift; 109 int error; 110 111 /* Make sure tree is high enough */ 112 if((index > radix_tree_maxindex(head)) || (!radix_tree_maxindex(head))) 113 { 114 error = radix_tree_extend(head, index); 115 if(error) 116 { 117 return error; 118 } 119 } 120 slot = &head->rnode; 121 height = head->height; 122 shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 123 124 while(height > 0) 125 { 126 if(*slot == NULL) 127 { 128 /* Have to add a child node */ 129 if(!(tmp = radix_tree_node_alloc())) 130 { 131 return 1; 132 // return -ENOMEM; 133 } 134 *slot = tmp; 135 if(node) 136 { 137 node->count++; 138 } 139 } 140 141 /* Go a level down */ 142 node = *slot; 143 slot = (PPradix_tree_node)(node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK)); 144 shift -= RADIX_TREE_MAP_SHIFT; 145 height--; 146 } 147 if(*slot != NULL) 148 { 149 printf("slot have been occupied\n"); 150 return 1; 151 //return -EEXIST; 152 } 153 if(node) 154 { 155 node->count++; 156 } 157 158 insert_succeed: 159 *slot = item; 160 return 0; 161 } 162 163 /** Perform lookup operation on a radix tree 164 * @head: radix tree head 165 * @index: index key 166 * 167 * lookup the item at the position @index in the radix tree @head 168 */ 169 170 void *radix_tree_lookup(Pradix_tree_head head, unsigned int index) 171 { 172 unsigned int height, shift; 173 PPradix_tree_node slot; 174 175 height = head->height; 176 /* Make sure tree is high enough */ 177 if(index > radix_tree_maxindex(head)) 178 { 179 printf("index are out of range\n"); 180 return NULL; 181 } 182 shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 183 slot = &head->rnode; 184 185 while(height > 0) 186 { 187 if(*slot == NULL) 188 { 189 printf("index does not exist, it's empty\n"); 190 return NULL; 191 } 192 slot = (PPradix_tree_node)((*slot)->slots +((index >> shift) & RADIX_TREE_MAP_MASK)); 193 shift -= RADIX_TREE_MAP_SHIFT; 194 height--; 195 } 196 return (void*)(*slot); 197 } 198 199 static unsigned int __lookup(Pradix_tree_head head, void **results, unsigned int first_index, 200 unsigned int max_items, unsigned int *next_index) 201 { 202 unsigned int nr_found = 0, index = first_index; 203 unsigned int shift; 204 unsigned int height = head->height; 205 Pradix_tree_node slot; 206 207 shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 208 slot = head->rnode; 209 210 while(height > 0) 211 { 212 unsigned int i = (index >> shift) & RADIX_TREE_MAP_MASK; 213 height--; 214 if(height && !slot->slots[i]) 215 { 216 printf("bug, please check!!!\n"); 217 //abort(); 218 } 219 if(height == 0) 220 { 221 unsigned int j = index & RADIX_TREE_MAP_MASK; 222 for(; j < RADIX_TREE_MAP_SIZE; j++) 223 { 224 index++; 225 if(slot->slots[j]) 226 { 227 results[nr_found++] = slot->slots[j]; 228 if(nr_found == max_items) 229 { 230 index = 0; 231 goto out; 232 } 233 } 234 } 235 } 236 shift -= RADIX_TREE_MAP_SHIFT; 237 slot = slot->slots[i]; 238 } 239 out: 240 *next_index = index; 241 return nr_found; 242 } 243 244 /** 245 * Perform multiple lookup on a radix tree 246 * @head: radix tree head 247 * @results: where the results of the lookup are placed 248 * @first_index: start the lookup from this key 249 * @max_items: palce up to this many items at *results 250 * 251 * Performs an index-ascending scan of the tree for present items. Places 252 * them at *@results and returns the number of items which were placed at 253 * *@results 254 * 255 * The implementation is naive 256 */ 257 unsigned int radix_tree_gang_lookup(Pradix_tree_head head, void **results, 258 unsigned int first_index, unsigned int max_items) 259 { 260 const unsigned int max_index = radix_tree_maxindex(head); 261 unsigned int cur_index = first_index; 262 unsigned int ret = 0; 263 264 if((head->rnode == NULL) || (max_index == 0)) 265 { 266 goto out; 267 } 268 while(ret < max_items) 269 { 270 unsigned int nr_found, next_index; 271 if(cur_index > max_index) 272 { 273 break; 274 } 275 nr_found = __lookup(head, results + ret, cur_index, max_items - ret, &next_index); 276 ret += nr_found; 277 if(next_index == 0) 278 { 279 break; 280 } 281 cur_index = next_index; 282 } 283 out: 284 return ret; 285 } 286 287 /** 288 * radix_tree_delete delete an item from a radix tree 289 * @head: radix tree head 290 * @index: index key 291 * 292 * Remove the item at @index from the radix tree @head 293 * 294 * Return the address of the deleted item, or NULL if it was not present 295 */ 296 void *radix_tree_delete(Pradix_tree_head head, unsigned int index) 297 { 298 radix_tree_path path[RADIX_TREE_MAX_PATH]; 299 Pradix_tree_path pathp = path; 300 unsigned int height, shift; 301 void *ret = NULL; 302 303 height = head->height; 304 /* Make sure tree is high enough */ 305 if(index > radix_tree_maxindex(head)) 306 { 307 goto out; 308 } 309 shift = (height - 1) * RADIX_TREE_MAP_SHIFT; 310 pathp->node = NULL; 311 pathp->slot = &head->rnode; 312 313 while(height) 314 { 315 if(*pathp->slot == NULL) 316 { 317 printf("bug, please check your input\n"); 318 goto out; 319 } 320 pathp[1].node = *pathp[0].slot; 321 pathp[1].slot = (PPradix_tree_node) (pathp[1].node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK)); 322 323 pathp++; 324 shift -= RADIX_TREE_MAP_SHIFT; 325 height--; 326 } 327 328 ret = *pathp[0].slot; 329 if(ret == NULL) 330 { 331 printf("bug, please check your input\n"); 332 goto out; 333 } 334 335 *pathp[0].slot = NULL; 336 while((pathp[0].node) && (--(pathp[0].node->count) == 0)) 337 { 338 pathp--; 339 *pathp[0].slot = NULL; 340 radix_tree_node_free(pathp[1].node); 341 } 342 if(head->rnode == NULL) 343 { 344 printf("radix tree emtpy now\n"); 345 head->height = 0; 346 } 347 out: 348 return ret; 349 } 350 351 Pradix_tree_head radix_tree_head_new(void) 352 { 353 Pradix_tree_head head = (Pradix_tree_head)calloc(1, sizeof(radix_tree_head)); 354 if(!head) 355 { 356 printf("calloc radix_tree_node failed\n"); 357 } 358 return head; 359 } 360 361 void radix_tree_initial(Pradix_tree_head head) 362 { 363 radix_tree_init_maxindex(head); 364 } 365 366 int radix_tree_destroy(Pradix_tree_head head) 367 { 368 printf("why I should write this function?\n, is it useful?!!!!\n"); 369 return 0; 370 }
    测试文件test.c
    1
    #include "radix_tree.h" 2 3 int main(void) 4 { 5 char *test[] = {"abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz0", 6 "123", "456", "789", "zyx", "wvu", "tsr", "qpo", "nml", "kji"}; 7 int i = 0; 8 int num = sizeof(test)/sizeof(*test); 9 printf("num : %d\n", num); 10 Pradix_tree_head head = radix_tree_head_new(); 11 radix_tree_initial(head); 12 if(!head) 13 { 14 printf("alloc head failed\n"); 15 } 16 17 for(i = 0; i < num; i++) 18 { 19 radix_tree_insert(head, i, test[i]); 20 } 21 22 for(i = 0; i < num; i++) 23 { 24 printf("%s\n",(char*) radix_tree_lookup(head, i)); 25 } 26 for(i = 0; i < num; i++) 27 { 28 radix_tree_delete(head, i); 29 } 30 31 return 0; 32 }
  • 相关阅读:
    event 事件 键盘控制div移动
    event 事件 div鼠标跟随
    获取坐标封装 getPos
    event 事件 clientX 和clientY 配合scrollTop使用, div跟着鼠标走
    event 事件 冒泡
    event 事件 坐标兼容
    event事件基础 document
    DOM 多字符搜索
    DOM search table 模糊搜索
    Reverse a sentence
  • 原文地址:https://www.cnblogs.com/openix/p/2889929.html
Copyright © 2020-2023  润新知