HashTable 解决碰撞(冲突)的方法 —— 分离链接法(separate chaining)

本文介绍了一种使用链表作为哈希表桶的数据结构实现方法,包括哈希表初始化、插入元素等核心操作的具体步骤。通过示例代码详细解释了如何构建哈希表并插入新节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. ListNode 及 HashTable 的类型声明

  • 声明

    typedef int ElementType;
    typedef unsigned int Index;
    
    struct ListNode;
    typedef struct ListNode* Position;
    struct HashTbl;
    typedef struct HashTbl* HashTable;
    
    HashTable InitHashTable(int TableSize);
    void DestroyHashTable(HashTable H);
    Position Find(ElementType Element, HashTable H);
    void Insert(ElementType Element, HashTable H);;
    ElementType Retrieve(Position P);
  • 定义

    struct ListNode{
        ElementType Element;
        Position Next;  
    };
    
    typedef Position List;
    
    struct HashTbl {
        int TableSize;
        List* TheLists; 
    };

2. HashTable 的构建

HashTable InitHashTable(int TableSize){
    HashTable H;
    if (TableSize < MinTableSize){
        Error(" ... ");
        return NULL;
    }

    H = (HashTable)malloc(sizeof(struct HashTbl));
    if (!H)
        FatalError("out of space !!!");
    H->TableSize = NextPrime(TableSize);
    H->TheLists = (List*)malloc(sizeof(struct ListNode)*H->TableSize);

    for (int i = 0; i < H->TableSize; ++i){
        H->TheLists[i] = (List)malloc(sizeof(struct ListNode));
        if (!H->TheLists[i])
            FatalError("");
        else
            H->TheLists[i]->Next = NULL;
    }
}

3. 插入新的结点

void Insert(ElementType Key, HashTable H){
    Position Pos, NewCell;
    List L;
    Pos = Find(key, H);
    if (!Pos){
        NewCell = (Position)malloc(sizeof(struct ListNode));
        if (!NewCell)
            FatalError("");
        L = H->TheLists[Hash(Key, H->TableSize)];
        NewCell->Next = L->Next;
                                    // 插入在首部
        NewCell->Element = Key;
        L->Next = NewCell->Next;
    }
}
### 使用拉链解决哈希表中的碰撞冲突 拉链是一种有效的解决方案,用于处理哈希表中的键值对因哈希函数产生的冲突问题。其核心思想是在每个桶(即由哈希函数计算得到的位置)维护一个链表或其他动态数据结构来存储具有相同哈希值的元素。 #### 拉链的工作原理 在实现过程中,如果两个不同的键通过哈希函数映射到了同一位置,则这些键会被存入该位置上的链表中[^1]。具体来说: - 如果插入新键时未发生冲突(即目标位置为空),则直接将此键作为链表的第一个节点。 - 若发生了冲突(即已有其他键位于该位置上),但不存在重复键的情况下,新的键被追加至链表头部或尾部。 - 当尝试更新已有的键时,遍历对应链表找到匹配的键并替换其关联值[^2]。 下面给出基于Python语言的一个简单示例代码展示如何利用拉链构建和操作哈希表: ```python class ListNode: def __init__(self, key=None, value=None, next_node=None): self.key = key self.value = value self.next = next_node class HashTable: def __init__(self, size=10): self.size = size self.buckets = [None] * self.size def hash_function(self, key): return abs(hash(key)) % self.size def put(self, key, value): index = self.hash_function(key) if not self.buckets[index]: self.buckets[index] = ListNode(key=key, value=value) # No collision or existing node. else: current = self.buckets[index] while True: if current.key == key: current.value = value # Update the value of an existing key. break if not current.next: break current = current.next if not current.key == key: new_node = ListNode(key=key, value=value, next_node=current.next) current.next = new_node # Add a new node at head/tail depending on implementation. def get(self, key): index = self.hash_function(key) current = self.buckets[index] while current is not None and current.key != key: current = current.next if current is not None: return current.value else: raise KeyError(f"Key {key} does not exist.") def remove(self, key): index = self.hash_function(key) prev = None curr = self.buckets[index] while curr and curr.key != key: prev = curr curr = curr.next if curr is None: return False # Key was not found; nothing to delete. if prev is None: self.buckets[index] = curr.next # Remove first element in bucket's list. else: prev.next = curr.next # Bypass the target node by linking previous with its successor. del curr return True ``` 上述代码定义了一个基本版本的哈希表类`HashTable`, 它使用拉链管理内部的数据存储方式。其中包含了三个主要功能:`put()`, `get()` 和 `remove()` 方法分别用来向表里添加/获取以及删除指定项[^4]. #### 总结 采用拉链可以有效缓解由于不良分布特性引起的频繁哈希冲突现象,并且允许灵活调整负载因子以优化性能表现。然而需要注意的是,随着链表长度增加可能会影响查找效率,因此合理设置初始容量及适时扩容对于保持良好运行状态至关重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值