数据结构的运算之查找(四)

本文介绍了散列表(哈希表)查找的概念,包括散列函数计算非负整数散列值的特点。讨论了两种常见的散列表构造方法,强调使用质数作为表长的重要性。详细阐述了开放地址法处理冲突,特别是线性探测法,并分析了不同冲突解决方法的平均查找长度。最后,给出了散列表的初始化、插入和查找操作的算法实现。总结了散列表适用于数据量小、装载因子小的情况,以及链表处理冲突的灵活性。
摘要由CSDN通过智能技术生成

今天我们来看看数据结构运算之查找的最后一种——散列表查找(也叫哈希表查找,主要是利用hash函数)。

1.散列表的概念:

注意:散列函数计算得到的散列值是一个非负整数;

 2.散列表的构造方法:(方法有很多种,这里就只是列出了比较常用的两种方法)

 

注意质数这一点。p 应为小于等于m,最好是接近m 的最小质数

 3.解决冲突的几种方法:

 其中线性探测法:

 

取余13,就有13种可能,就可以有13个单链表表头。

 4.散列表的查找:

假设采用开放地址法处理冲突,查找过程为:

对于给定的key,计算hash 地址index = f(key)
如果数组 arr[index] 的值为空,则查找不成功
如果数组 arr[index] == key,则查找成功
否则,使用冲突解决方法求下一个地址,直到
arr[index] == key or arr[index] == null

可以看到使用两种解决冲突的方法的平均查找长度是不同的 

最后,说几点关于散列表的结论:

 

 当数据量比较小、装载因子小的时候,适合采用开放寻址法

 基于链表的散列冲突处理方法比较适合存储大对象、大数据量的散列表,而且,比起开放寻址法,它更加灵活,支持更多的优化策略,比如用红黑树代替链表。

文章最后分享以下散列表的查找算法实现:

1. 定义一个散列表的结构以及一些相关常数

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHSIZE 12 // 定义散列表长为数组的长度
#define NULLKEY -32768

typedef struct{
    int *elem;      // 数据元素存储基址,动态分配数组
    int count;      // 当前数据元素个数
}HashTable;
int m = 0;          // 散列表表长,全局变量

注意:HashTable:散列表结构 elem:动态数组

2. 对散列表进行初始化

/* 初始化散列表 */
Status InitHashTable(HashTable *H){
    int i;
    m = HASHSIZE;
    H->count = m;
    H->elem = (int *)malloc(m * sizeof(int));
    for(i = 0; i < m; i++)
        H->elem[i] = NULLKEY;
    return OK;
}

3.定义散列函数,可根据不同情况更改算法

/* 散列函数 */

int Hash(int key)

{ return key % m; //除留余数法 }

4. 对散列表进行插入操作

/* 插入关键字进行散列表 */
void InsertHash(HashTable *H, int key){
    int addr = Hash(key)            // 求散列地址
    while(H->elem[addr] != NULLKEY) // 如果不为空,则冲突
        addr = (addr + 1) % m;      // 开放定址法的线性探索
    H->elem[addr] = key;            // 知道有空位后插入关键字
}

5. 通过散列表查找关键字

/* 散列表查找关键字 */
Status SearchHash(HashTable H, int key, int *addr){
    *addr = Hash(key);          // 求散列地址
    while(H.elem[*addr] != key){// 如果不为空,则冲突
        *addr = (*addr + 1) % m;    // 开方定址法的线性探索
        if(H.elem[*addr] == NULLKEY || *addr = Hash(key)){
            /* 如果循环回到原点 */
            return UNSUCCESS;   // 则说明关键字不存在
        }
    }
    return SUCCESS;
}

好啦,关于散列表(哈希表)的内容就分享到这啦
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值