源码:
1 /********************************************************************* 2 * 哈希表算法实现 3 * (c)copyright 2013,jdh 4 * All Right Reserved 5 *文件名:main.c 6 *程序员:jdh 7 **********************************************************************/ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 12 /********************************************************************* 13 * 宏定义 14 **********************************************************************/ 15 16 /********************************************************************* 17 * 数据类型重定义 18 **********************************************************************/ 19 20 #define uint8_t unsigned char 21 #define uint16_t unsigned short 22 #define uint32_t unsigned long 23 24 /********************************************************************* 25 * 哈希表长度 26 **********************************************************************/ 27 28 #define HASH_TABLE_LEN 100 29 30 /********************************************************************* 31 * 数据结构 32 **********************************************************************/ 33 //链表节点 34 typedef struct _Link_Node 35 { 36 uint16_t id; 37 uint16_t data; 38 struct _Link_Node *next; 39 }Link_Node,*Link_Node_Ptr; 40 41 //哈希表头 42 typedef struct _Hash_Header 43 { 44 struct _Link_Node *next; 45 }Hash_Header,*Hash_Header_Ptr; 46 47 /********************************************************************* 48 * 全局变量 49 **********************************************************************/ 50 51 //哈希表 52 Hash_Header_Ptr Hash_Table[HASH_TABLE_LEN]; 53 54 /********************************************************************* 55 * 函数 56 **********************************************************************/ 57 58 /********************************************************************* 59 * 哈希表函数 60 *说明: 61 *1.用哈希函数生成id对应的哈希表中的位置 62 输入:id 63 返回:位置 64 **********************************************************************/ 65 66 uint8_t hash_func(uint16_t id) 67 { 68 uint8_t pos = 0; 69 70 pos = id % HASH_TABLE_LEN; 71 72 return pos; 73 } 74 75 /********************************************************************* 76 * 初始化节点 77 *返回:结点指针 78 **********************************************************************/ 79 80 Link_Node_Ptr init_link_node(void) 81 { 82 Link_Node_Ptr node; 83 84 //申请节点 85 node = (Link_Node_Ptr) malloc(sizeof(Link_Node)); 86 //初始化长度为0 87 node->next = NULL; 88 89 return node; 90 } 91 92 /********************************************************************* 93 * 初始化哈希表头结点 94 *返回哈希表头结点指针 95 **********************************************************************/ 96 97 Hash_Header_Ptr init_hash_header_node(void) 98 { 99 Hash_Header_Ptr node; 100 101 //申请节点 102 node = (Hash_Header_Ptr) malloc(sizeof(Hash_Header)); 103 //初始化长度为0 104 node->next = NULL; 105 106 return node; 107 } 108 109 110 /********************************************************************* 111 * 哈希表初始化 112 *说明: 113 *1.初始化哈希表Hash_Table 114 *2.哈希表长度最大不能超过256 115 **********************************************************************/ 116 117 void init_hash_table(void) 118 { 119 uint8_t i = 0; 120 121 for (i = 0;i < HASH_TABLE_LEN;i++) 122 { 123 Hash_Table[i] = init_hash_header_node(); 124 Hash_Table[i]->next = NULL; 125 } 126 } 127 128 /********************************************************************* 129 * 在哈希表增加节点 130 *说明: 131 *1.在哈希表的某个链表末增加数据 132 输入:new_node:新节点 133 **********************************************************************/ 134 135 void append_link_node(Link_Node_Ptr new_node) 136 { 137 Link_Node_Ptr node; 138 uint8_t pos = 0; 139 140 //新节点下一个指向为空 141 new_node->next = NULL; 142 143 //用哈希函数获得位置 144 pos = hash_func(new_node->id); 145 146 //判断是否为空链表 147 if (Hash_Table[pos]->next == NULL) 148 { 149 //空链表 150 Hash_Table[pos]->next = new_node; 151 } 152 else 153 { 154 //不是空链表 155 //获取根节点 156 node = Hash_Table[pos]->next; 157 158 //遍历 159 while (node->next != NULL) 160 { 161 node = node->next; 162 } 163 164 //插入 165 node->next = new_node; 166 } 167 } 168 169 /********************************************************************* 170 * 在哈希表查询节点 171 *说明: 172 *1.知道在哈希表某处的单链表中,并开始遍历. 173 *2.返回的是查询节点的前一个节点指针.这么做是为了做删除操作. 174 输入:pos:哈希表数组位置,从0开始计数 175 id:所需要查询节点的id 176 root:如果是根节点,则*root = 1,否则为0 177 返回:所需查询的节点的前一个节点指针,如果是根节点则返回根节点,失败返回0 178 **********************************************************************/ 179 180 Link_Node_Ptr search_link_node(uint16_t id,uint8_t *root) 181 { 182 Link_Node_Ptr node; 183 uint8_t pos = 0; 184 185 //用哈希函数获得位置 186 pos = hash_func(id); 187 188 //获取根节点 189 node = Hash_Table[pos]->next; 190 191 //判断单链表是否存在 192 if (node == NULL) 193 { 194 return 0; 195 } 196 197 //判断是否是根节点 198 if (node->id == id) 199 { 200 //是根节点 201 *root = 1; 202 return node; 203 } 204 else 205 { 206 //不是根节点 207 *root = 0; 208 //遍历 209 while (node->next != NULL) 210 { 211 if (node->next->id == id) 212 { 213 return node; 214 } 215 else 216 { 217 node = node->next; 218 } 219 } 220 221 return 0; 222 } 223 } 224 225 /********************************************************************* 226 * 在哈希表删除节点 227 *说明: 228 *1.删除的不是当前节点,而是当前节点后的一个节点 229 输入:node:删除此节点后面的一个节点 230 new_node:新节点 231 **********************************************************************/ 232 233 void delete_link_node(Link_Node_Ptr node) 234 { 235 Link_Node_Ptr delete_node; 236 237 //重定向需要删除的前一个节点 238 delete_node = node->next; 239 node->next = delete_node->next; 240 241 //删除节点 242 free(delete_node); 243 delete_node = NULL; 244 } 245 246 /********************************************************************* 247 * 在哈希表删除根节点 248 输入:node:根节点 249 **********************************************************************/ 250 251 void delete_link_root_node(Link_Node_Ptr node) 252 { 253 uint8_t pos = 0; 254 255 //用哈希函数获得位置 256 pos = hash_func(node->id); 257 258 //哈希表头清空 259 if (node != NULL) 260 { 261 Hash_Table[pos]->next = node->next; 262 //删除节点 263 free(node); 264 node = NULL; 265 } 266 } 267 268 /********************************************************************* 269 * 获得哈希表中所有节点数 270 输入:node:根节点 271 **********************************************************************/ 272 273 uint16_t get_node_num(void) 274 { 275 Link_Node_Ptr node; 276 uint16_t i = 0; 277 uint16_t num = 0; 278 279 //遍历 280 for (i = 0;i < HASH_TABLE_LEN;i++) 281 { 282 //获取根节点 283 node = Hash_Table[i]->next; 284 //遍历 285 while (node != NULL) 286 { 287 num++; 288 node = node->next; 289 } 290 } 291 292 return num; 293 } 294 295 /********************************************************************* 296 * 从哈希表中获得对应序号的节点 297 *参数:index:序号.从1开始,最大值为节点总数值 298 * root:如果是根节点,则*root = 1,否则为0 299 返回:所需查询的节点的前一个节点指针,如果是根节点则返回根节点,失败返回0 300 **********************************************************************/ 301 302 Link_Node_Ptr get_node_from_index(uint16_t index,uint8_t *root) 303 { 304 Link_Node_Ptr node; 305 uint16_t i = 0; 306 uint16_t num = 0; 307 308 //遍历 309 for (i = 0;i < HASH_TABLE_LEN;i++) 310 { 311 //获取根节点 312 node = Hash_Table[i]->next; 313 //判断单链表是否存在 314 if (node == NULL) 315 { 316 continue; 317 } 318 319 //根节点 320 num++; 321 if (num == index) 322 { 323 //是根节点 324 *root = 1; 325 return node; 326 } 327 328 //遍历 329 while (node->next != NULL) 330 { 331 num++; 332 if (num == index) 333 { 334 //不是根节点 335 *root = 0; 336 return node; 337 } 338 node = node->next; 339 } 340 } 341 342 return 0; 343 } 344 345 /********************************************************************* 346 * 删除hash表中所有节点 347 **********************************************************************/ 348 349 void drop_hash() 350 { 351 Link_Node_Ptr node; 352 uint16_t i = 0; 353 Link_Node_Ptr node_next; 354 355 //遍历 356 for (i = 0;i < HASH_TABLE_LEN;i++) 357 { 358 //获取根节点 359 node = Hash_Table[i]->next; 360 361 while (1) 362 { 363 //判断单链表是否存在 364 if (node == NULL) 365 { 366 //不存在 367 Hash_Table[i]->next = NULL; 368 break; 369 } 370 371 //根节点下一个节点 372 node_next = node->next; 373 //删除根节点 374 free(node); 375 //重指定根节点 376 node = node_next; 377 } 378 } 379 } 380 381 /********************************************************************* 382 * 输出所有节点 383 **********************************************************************/ 384 385 void printf_hash() 386 { 387 Link_Node_Ptr node; 388 uint8_t root = 0; 389 uint8_t i = 0; 390 uint8_t num = 0; 391 392 printf("-------------打印hash表-------------\n"); 393 394 num = get_node_num(); 395 for (i = 1;i <= num;i++) 396 { 397 node = get_node_from_index(i,&root); 398 if (node != 0) 399 { 400 if (root) 401 { 402 printf("根节点:节点号%d,id为%d\n",i,node->id); 403 } 404 else 405 { 406 printf("普通节点:节点号%d,id为%d\n",i,node->next->id); 407 } 408 } 409 } 410 } 411 412 /********************************************************************* 413 * 主函数 414 *说明:实现对哈希表的新建,建立节点,查询及增加,删除节点的操作 415 **********************************************************************/ 416 417 int main() 418 { 419 Link_Node_Ptr node; 420 uint8_t temp = 0; 421 uint8_t root = 0; 422 uint8_t i = 0; 423 424 init_hash_table(); 425 426 //插入数据id = 1,data = 2; 427 node = init_link_node(); 428 node->id = 1; 429 node->data = 2; 430 append_link_node(node); 431 432 //查询节点数 433 printf("1节点数为%d\n",get_node_num()); 434 435 node = init_link_node(); 436 node->id = 100; 437 node->data = 101; 438 append_link_node(node); 439 440 node = init_link_node(); 441 node->id = 1002; 442 node->data = 1001; 443 append_link_node(node); 444 445 node = init_link_node(); 446 node->id = 10000; 447 node->data = 10001; 448 append_link_node(node); 449 450 node = init_link_node(); 451 node->id = 1000; 452 node->data = 10001; 453 append_link_node(node); 454 455 node = init_link_node(); 456 node->id = 2; 457 node->data = 10001; 458 append_link_node(node); 459 460 //查询节点数 461 printf("2节点数为%d\n",get_node_num()); 462 463 //查询id = 1000; 464 node = search_link_node(100,&temp); 465 if (node != 0) 466 { 467 if (temp == 0) 468 { 469 printf("删除普通节点:所需查询id的值为%d,数据为%d\n",node->next->id,node->next->data); 470 471 //删除 472 delete_link_node(node); 473 } 474 else 475 { 476 //根节点 477 printf("删除根节点所需查询id的值为%d,数据为%d\n",node->id,node->data); 478 479 //删除 480 delete_link_root_node(node); 481 } 482 } 483 else 484 { 485 printf("查询失败\n"); 486 } 487 488 //查询id = 1000; 489 node = search_link_node(1001,&temp); 490 if (node != 0) 491 { 492 if (temp == 0) 493 { 494 printf("所需查询id的值为%d\n",node->next->data); 495 } 496 else 497 { 498 //根节点 499 printf("所需查询id的值为%d\n",node->data); 500 } 501 } 502 else 503 { 504 printf("查询失败\n"); 505 } 506 507 //查询节点数 508 printf("节点数为%d\n",get_node_num()); 509 510 printf_hash(); 511 512 513 getchar(); 514 return 0; 515 }
时间: 2024-10-09 22:13:19