HashMap与冲突解决算法

本文介绍了如何使用简单的除留取余法作为hash函数和开散列地址链作为冲突解决算法来实现HashMap。通过定义链表节点类型Node,构建基于地址链的开散列哈希表,并提供了插入、删除和检索操作的基本实现。讨论了如何处理键值类型、特殊键映射以及键比较等问题,展示了更完整的HashMap实现思路。
摘要由CSDN通过智能技术生成

hash_map是经常被使用的一种数据结构,而其实现方式也是多种多样。如果要求我们使用尽可能简单的方式实现hash_map,具体该如何做呢?

我们知道hash_map最重要两个概念是hash函数和冲突解决算法。hash_map-值之间的映射关系,hash函数将键映射为内存地址,冲突解决算法用于解决不同的键映射为相同地址时候的情况。

数据结构和算法导论中介绍了大量的hash函数和冲突解决算法,如果选择实现精简的hash_map,那么可以选择“除留取余法”作为hash函数,选择“开散列地址链”作为冲入解决算法。这样的选择不仅使得hash_map实现简单,而且有很高的查询效率。其设计结构如下:

基于地址链的开散列哈希表实现

如图所示,键347通过除留取余法得到地址链的索引,然后将347对应的元素插入到该地址链的尾端。

为了实现地址链,我们需要定义链表节点类型Node。为了简化问题,我们将键值都定义为int类型。


struct Node // 地址链节点
{
     int key; //
     int value; //
    Node*next; // 链接指针
    Node( int k, int v):key(k),value(v),next(NULL){}
};

value用于记录节点数组,key在检索节点时会被使用,next保存链表关系。

基于此,定义hash_map类型SimHash

 


#define SIZE 100  // 地址链个数,足够大
class SimHash
{
    Node**map; // 地址链数组
    size_t hash( int key) // hash函数,除留取余法
    {
         return key%SIZE;
    }
public:
    SimHash()
    {
        map= new Node*[SIZE];
         for(size_t i= 0;i<SIZE;i++)map[i]=NULL; // 初始化数组为空
    }
    ~SimHash()
    {
         for(size_t i= 0;i<SIZE;i++) // 清除所有节点
        {
            Node*p;
             while(p=map[i])
            {
                map[i]=p->next;
                delete p;
            }
        }
        delete[] map; // 清除数组
    }
     void insert( int key, int value)
    {
        Node*f=find(key); // 插入前查询
         if(f)
        {
            f->value=value; // 存在键则覆盖
             return;
        }
        Node*p=map[hash(key)]; // 确定地址链索引
        Node*q= new Node(key,value);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值