一.代码
#include <stdio.h>
#include <malloc.h>
#define TABLE_SIZE 19
typedef struct Node{
int key;
char value;
}Node, *NodePtr;
typedef struct HashList{
int length;
NodePtr elements;
}HashList, *ListPtr;
ListPtr initList(int* paraKeys, char* paraValues, int paraLength){
int i, tempPosition;
ListPtr resultPtr = (ListPtr)malloc(sizeof(struct HashList));
resultPtr->length = paraLength;
resultPtr->elements = (NodePtr)malloc(TABLE_SIZE * sizeof(struct Node));
for (i = 0; i < TABLE_SIZE; i ++){
resultPtr->elements[i].key = -1;
resultPtr->elements[i].value = 'x';
}
for (i = 0; i < paraLength; i++) {
tempPosition = paraKeys[i] % TABLE_SIZE;
while (resultPtr->elements[tempPosition].key != -1) {
tempPosition = (tempPosition + 1) % TABLE_SIZE;
printf("Collision, move forward for key %d.\r\n", paraKeys[i]);
}
// printf("Inserting %d to %d\r\n", paraKeys[i], tempPosition);
resultPtr->elements[tempPosition].key = paraKeys[i];
resultPtr->elements[tempPosition].value = paraValues[i];
}
return resultPtr;
}
char hashSearch(ListPtr paraPtr, int paraKey) {
int tempPosition = paraKey % TABLE_SIZE;
// printf("For %d\r\n", paraKey);
// printf("Looking at position %d\r\n", tempPosition);
while (paraPtr->elements[tempPosition].key != -1) {
if (paraPtr->elements[tempPosition].key == paraKey) {
// printf("Found\r\n");
return paraPtr->elements[tempPosition].value;
}
// printf("Not this one for %d.\r\n", paraKey);
tempPosition = (tempPosition + 1) % TABLE_SIZE;
// printf("Looking at position %d\r\n", tempPosition);
}
return 'x';
}
void hashSearchTest() {
int tempUnsortedKeys[] = { 16, 33, 38, 69, 57, 95, 86 };
char tempContents[] = { 'h', 'e', 'l', 'o', 'w', 'r', 'd' };
ListPtr tempPtr = initList(tempUnsortedKeys, tempContents, 7);
printf("Search result of 95 is: %c\r\n", hashSearch(tempPtr, 95));
printf("Search result of 38 is: %c\r\n", hashSearch(tempPtr, 38));
printf("Search result of 57 is: %c\r\n", hashSearch(tempPtr, 57));
printf("Search result of 4 is: %c\r\n", hashSearch(tempPtr, 4));
}
int main() {
hashSearchTest();
return 1;
}
二.运行结果
三.图示
四.心得体会
哈希表通常表示为一个数组,其中每个位置(或称为“槽”)存储一个键值对。但由于哈希冲突(即不同的键可能计算出相同的哈希值)的存在,每个槽通常可以进一步链接到一个链表或其他数据结构来存储具有相同哈希值的多个键值对。
- 性能优势:哈希表提供了接近常数时间复杂度的查找、插入和删除操作,这使得它们在处理大规模数据集时非常高效。
- 哈希函数的重要性:一个好的哈希函数是哈希表性能的关键。它应该能够将键均匀地分布到哈希表的各个槽中,以减少哈希冲突并提高性能。
- 处理哈希冲突:哈希冲突是不可避免的,但我们可以使用不同的策略(如链地址法、开放地址法等)来有效地处理它们。选择哪种策略取决于具体的应用场景和性能要求。
- 动态调整大小:当哈希表中的数据量增长或减少时,可能需要动态地调整其大小以保持性能。这通常涉及重新哈希所有键并将它们放入新的表中。虽然这个过程可能很耗时,但它是保持哈希表高效的关键。
- 应用场景广泛:哈希表在许多编程任务中都有广泛的应用,包括数据库索引、缓存系统、编译器符号表等。掌握哈希表的使用可以大大提高我们的编程效率。
- 与其他数据结构的比较:虽然哈希表在查找和插入操作方面非常高效,但它们并不是所有场景下的最佳选择。例如,在需要保持数据顺序的场合下,链表或数组可能更合适;而在需要频繁进行范围查询的场合下,树形结构(如平衡二叉搜索树)可能更合适。因此,在选择数据结构时需要根据具体需求进行权衡。