C语言实现整数哈希表打印顺序异常问题求助
哈希表打印顺序异常的问题排查与解决
兄弟,我一眼就瞅出来你这问题大概率出在哈希函数的元素分配 + printlist的遍历顺序上!咱们来拆解一下:
你期望打印1-10,但输出是10,1,2,3,4,5,6,7,8,9,这个顺序太有规律了——10跑最前面,后面跟着1到9。结合C语言入门哈希表的常见实现,十有八九是这回事:
问题根源:哈希函数把10分到了第一个桶,而你按桶索引顺序遍历
假设你写的哈希函数是最基础的index = value % 10(毕竟是入门哈希表),那:
- 数字1-9会分别被分配到索引1-9的桶里
- 数字10取模10等于0,会被放到索引0的桶里
而你的printlist函数应该是从索引0开始,依次遍历每个桶的元素,先打印索引0里的10,再按顺序打印索引1到9里的1-9,自然就出现了你看到的颠倒顺序。
怎么解决?看你的需求来选方案
需求1:按插入顺序打印所有元素
哈希表本身是按哈希值分桶存储的,不天然保留插入顺序。如果要按插入顺序输出,得额外维护一个全局顺序链表,每次插入节点时,除了放到对应桶里,还要把节点加到这个顺序链表的尾部。
举个修改后的代码例子:
// 先修改节点结构,增加一个记录插入顺序的指针 typedef struct node { struct node* next; // 桶内链表的指针 struct node* order_next; // 记录插入顺序的指针 int data; } node; // 再给哈希表加个结构,维护顺序链表的头尾 typedef struct hashtable { node* buckets[10]; // 假设桶的数量是10 node* order_head; node* order_tail; } hashtable; // 插入函数同时维护顺序链表 void insert_node(hashtable* ht, int value) { int index = value % 10; node* new_node = malloc(sizeof(node)); new_node->data = value; new_node->next = ht->buckets[index]; ht->buckets[index] = new_node; // 把新节点加到顺序链表的尾部 new_node->order_next = NULL; if (ht->order_tail == NULL) { ht->order_head = new_node; ht->order_tail = new_node; } else { ht->order_tail->order_next = new_node; ht->order_tail = new_node; } } // 打印时遍历顺序链表就行 void print_ordered_list(hashtable* ht) { node* curr = ht->order_head; while (curr != NULL) { printf("%d", curr->data); if (curr->order_next != NULL) printf(","); curr = curr->order_next; } printf("\n"); }
需求2:按数值大小顺序打印
如果是想按1-10的数值顺序输出,可以先把所有桶里的元素收集到一个数组,排序后再打印:
void print_sorted_list(node* ht[], int bucket_num) { int arr[10], count = 0; // 先把所有元素捞出来 for (int i = 0; i < bucket_num; i++) { node* curr = ht[i]; while (curr != NULL) { arr[count++] = curr->data; curr = curr->next; } } // 简单冒泡排序(入门用足够了) for (int i = 0; i < count-1; i++) { for (int j = 0; j < count-i-1; j++) { if (arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } // 打印排序后的数组 for (int i = 0; i < count; i++) { printf("%d", arr[i]); if (i != count-1) printf(","); } printf("\n"); }
需求3:临时凑合用(只针对当前1-10的场景)
如果只是想快速让当前的输出变成1-10,你可以直接修改printlist的遍历顺序:先遍历索引1-9的桶,最后遍历索引0的桶,这样就能先打印1-9,再打印10:
void printlist(node *ht[]) { // 先打印1-9对应的桶 for (int i = 1; i < 10; i++) { node* curr = ht[i]; while (curr != NULL) { printf("%d,", curr->data); curr = curr->next; } } // 最后打印10所在的桶0 node* curr = ht[0]; while (curr != NULL) { printf("%d", curr->data); curr = curr->next; } printf("\n"); }
不过这个方法通用性很差,换个数值范围就失效了,只适合临时测试用。
最后再确认下
你可以先检查下自己的哈希函数是不是value%10,再看看printlist是不是从索引0开始遍历所有桶——肯定是这俩组合导致的问题!
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

