hash表概念及代码理解

Hash表(也称为哈希表、散列表)是一种使用哈希函数组织数据,以支持快速插入和搜索的数据结构。它通过把键值(Key)映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数称为哈希函数,存放记录的数组称为哈希表。

基本概念

  • 哈希函数:将任意长度的输入(通常称为键或关键字)通过某种算法转换成固定长度的输出(即哈希值)。理想情况下,不同的输入应产生不同的哈希值,但在实际应用中,哈希冲突(即不同的输入产生相同的哈希值)是不可避免的。
  • 哈希表:用于存储键值对的数组。哈希表的大小通常是固定的,或者有一个上限。通过哈希函数计算出的哈希值用于确定键值对在哈希表中的位置(索引)。
  • 哈希冲突:当两个或多个不同的键通过哈希函数映射到哈希表的同一个位置时,就发生了哈希冲突。解决哈希冲突的方法有多种,如链地址法(使用链表)、开放定址法(线性探测、二次探测等)、再哈希法等。

操作

  1. 插入:计算键的哈希值,并根据哈希表的大小和某种策略(如取模运算)确定该键的存储位置。如果该位置已有元素,则根据解决哈希冲突的方法处理。
  2. 搜索:与插入类似,首先计算键的哈希值,然后定位到哈希表中的相应位置。如果该位置上的元素与搜索的键相同,则搜索成功;如果发生冲突,则根据解决哈希冲突的策略进行查找。
  3. 删除:定位到键值对的位置,将其从哈希表中移除。在链地址法中,可能只是删除链表中的一个节点;在开放定址法中,可能需要将后续的元素向前移动。

优点

  • 查找效率高:在理想情况下,哈希表的查找、插入和删除操作的时间复杂度都是O(1)。
  • 存储空间利用率高:相比于顺序存储,哈希表可以根据需要动态扩展。

缺点

  • 哈希冲突:虽然可以通过不同的方法解决哈希冲突,但冲突的存在仍然会影响哈希表的性能。
  • 对哈希函数的依赖:哈希函数的设计直接影响到哈希表的性能。
  • 不支持顺序遍历:由于哈希表是通过哈希值来确定存储位置的,因此不能直接进行顺序遍历。

c代码实现示例:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
  
#define TABLE_SIZE 10  // 哈希表的大小  
  
// 定义链表节点  
typedef struct Node {  
    char* key;  
    int value;  
    struct Node* next;  
} Node;  
  
// 定义哈希表  
typedef struct HashTable {  
    Node** buckets;  
} HashTable;  
  
// 哈希函数(简单示例,实际使用时应更复杂)  
unsigned int hash(char* key) {  
    unsigned long hash = 5381;  
    int c;  
  
    while ((c = *key++))  
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */  
  
    return hash % TABLE_SIZE;  
}  
  
// 初始化哈希表  
HashTable* create_hash_table() {  
    HashTable* table = (HashTable*)malloc(sizeof(HashTable));  
    table->buckets = (Node**)malloc(TABLE_SIZE * sizeof(Node*));  
    for (int i = 0; i < TABLE_SIZE; i++) {  
        table->buckets[i] = NULL;  
    }  
    return table;  
}  
  
// 插入键值对到哈希表  
void insert(HashTable* table, char* key, int value) {  
    unsigned int index = hash(key);  
    Node* newNode = (Node*)malloc(sizeof(Node));  
    newNode->key = strdup(key);  
    newNode->value = value;  
    newNode->next = table->buckets[index];  
    table->buckets[index] = newNode;  
}  
  
// 从哈希表中查找键对应的值  
int search(HashTable* table, char* key) {  
    unsigned int index = hash(key);  
    Node* current = table->buckets[index];  
    while (current != NULL) {  
        if (strcmp(current->key, key) == 0) {  
            return current->value;  
        }  
        current = current->next;  
    }  
    return -1;  // 未找到  
}  
  
// 销毁哈希表  
void destroy_hash_table(HashTable* table) {  
    for (int i = 0; i < TABLE_SIZE; i++) {  
        Node* current = table->buckets[i];  
        while (current != NULL) {  
            Node* temp = current;  
            current = current->next;  
            free(temp->key);  
            free(temp);  
        }  
    }  
    free(table->buckets);  
    free(table);  
}  
  
int main() {  
    HashTable* table = create_hash_table();  
      
    insert(table, "apple", 100);  
    insert(table, "banana", 200);  
    insert(table, "cherry", 300);  
  
    printf("Value of 'apple': %d\n", search(table, "apple"));  
    printf("Value of 'banana': %d\n", search(table, "banana"));  
    printf("Value of 'grape' (not found): %d\n", search(table, "grape"));  
  
    destroy_hash_table(table);  
  
    return 0;  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值