2021/06/07 散列表之除留余数法以及平方探测法

  • 给出一个序列:
    47 7 29 11 9 84 54 20 30  

    如何才能对它们进行排序并且要查找它的位置的时候特别方便?

散列表就是找出每一个数据的关键字并且按照关键字存放在特定的位置;

核心思想就是弄一个映射函数H(key),使得key的位置ret=H(key)

除留余数法是找出某个数字p,让位置ret=key%p;

当然很有可能在存放了几个之后就会有重叠位置的情况发生,也就是冲突。

这里解决冲突的方法是平方探测法:让这个重叠的初始位置ret去加Di;

Di是一段序列:1^2,-1^2,2^2,-2^2....  其中i是发生冲突的次数

例如说p=11.存放数字7的时候没问题(ret=7%11=7),然而存放29的时候(ret=29%11=7)

发生了冲突,那么第一次冲突就加1,也就是前进一格.8这个位置没有别的数据,不会冲突,所以存放在8;冲突解决

如果8这个位置也存放了其他的数字,那就是第二次冲突,这次要加D2也就是ret=(-1)=6;倒退一格

如果6这个位置也冲突那么就加D3也就是加4,前进四格...

循环下去直到找到空位置为止. 

这里关键是找到这里的“某个数字p”。除留余数法中的p指的其实是散列表的最大储存空间。一般是比原序列大的素数。取素数是为了减少冲突。

这里的p用T

测量散列表的平均查找长度需要实现以下几个步骤: 1. 实现哈希函数:散列表的查找是通过哈希函数计算出键值对应的散列表索引位置,所以需要先实现一个哈希函数。常见的哈希函数有除留余数法、乘法哈希法、平方取中法等,可以根据实际情况选择合适的哈希函数。 2. 实现散列表:使用数组实现散列表,将每个键值对应的索引位置存储在数组中。 3. 插入数据:将待查找的数据插入散列表中,需要先计算出键值对应的索引位置,然后将数据存储在该位置。 4. 查找数据:使用哈希函数计算出待查找数据的索引位置,然后在该位置查找数据。如果该位置存储的数据不是待查找数据,则使用开放寻址法或链表法解决冲突,找到对应的数据。 5. 测量平均查找长度:对于散列表,平均查找长度是指查找成功和查找失败的平均查找长度。查找成功的平均查找长度为每个键值对应的索引位置上的查找次数之和除以总的键值对数;查找失败的平均查找长度为散列表大小除以键值对数。 下面是一个用C语言实现的测量不同规模散列表的平均查找长度的代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> #define TABLE_SIZE 10000 //散列表大小 #define MAX_KEY 100000 //键的最大值 typedef struct { int key; int value; } Entry; int hash(int key) { //使用除留余数法作为哈希函数 return key % TABLE_SIZE; } void insert(Entry *table, int key, int value) { int index = hash(key); while (table[index].key != -1) { //使用线性探测法解决冲突 index = (index + 1) % TABLE_SIZE; } table[index].key = key; table[index].value = value; } int search(Entry *table, int key) { int index = hash(key); int count = 0; while (table[index].key != -1) { if (table[index].key == key) { return count + 1; } index = (index + 1) % TABLE_SIZE; count++; } return count + 1; //查找失败 } int main() { srand(time(NULL)); Entry *table = malloc(TABLE_SIZE * sizeof(Entry)); for (int i = 0; i < TABLE_SIZE; i++) { table[i].key = -1; table[i].value = 0; } int n; printf("请输入键值对数量:"); scanf("%d", &n); for (int i = 0; i < n; i++) { int key = rand() % MAX_KEY; int value = rand(); insert(table, key, value); } int sum = 0; for (int i = 0; i < TABLE_SIZE; i++) { if (table[i].key != -1) { sum += search(table, table[i].key); } } printf("查找成功的平均查找长度为:%f\n", (float)sum / n); printf("查找失败的平均查找长度为:%f\n", (float)TABLE_SIZE / n); free(table); return 0; } ``` 该程序首先定义了一个包含键和值的Entry结构体,然后实现了哈希函数和插入、查找操作。在主函数中,程序通过随机生成n个键值对来填充散列表,然后计算出平均查找长度并输出结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值