解决散列表冲突问题-开放定址法

来源:互联网 发布:数据录入员待遇好么 编辑:程序博客网 时间:2024/06/07 19:03

指针是我们学习C语言的一大瓶颈,用分离链接散列算法的一大缺点也是因为他用到了指针,涉及到了内存分配。开放定址散列法是另一种解决冲突而不需要用到指针的算法。

开放地址散列法的基本思想是,遇到了冲突,我们就用另一套法则,将此关键字放在其他的空缺位置上。显而易见,他的缺点是散列表的创建必须足够大,才能够容许我们进行相关的操作,比起分离链接法来讲,虽然算法速度上有所提升,但是内存浪费比较大。因为他的装填因子λ应该低于0.5

装填因子:散列表的装填因子(load factor)λ为散列表中的元素个数与散列表大小的比值。

1.线性探测法

在原来的散列表基础之上添加增量序列,(1,2……,TableSize-1)循环试探下一个存储地址。

这里写图片描述

只要表足够大,我们就能根据这个方法找到相应的位置,但是这样花费的时间更多,且浪费了很多空间,这样占据的单元也会开始形成一些区块,这样的结果称为一次聚集

2.平方探测 – 二次探测

平方探测法:以增量序列1²,-1²,2²,-2²,……,q²,-q² 且 q≤|TableSize/2|玄幻试探下一个存储地址

伪代码描述

类型声明

struct HashEntry{    ElementType Element;    enum KindOfEntry Info;};typedef struct HashEntry Cell;struct HashTbl{    int TableSize;    Cell *TheCells;}

初始化开放定址散列表

HashTableInitializeTable(int TableSize){    HashTable H;    int i;    if(TableSize < MinTableSize)    {        Error("Table size too small");        return NULL;    }    /*Allocate table*/    H = malloc( sizeof(struct HashTbl));    if(H == NULL)        FatalError("Out of space!!");    H->TableSize = NextPrime(TableSize);    /*Allocate array of cells*/    H->TheCells = malloc( sizeof(cell) * H->TableSize);    if(H->TheCells == NULL)        FatalError(" Out of space !!");    for(i = 0; i < H->TableSize; i++)        H->TheCells[i].Info = Empty;    return H;}

看得出来开放定址的初始化和分离链接的初始化大致相同。

Find例程

PositionFind(ElementType key, HashTable H){    Position CurrentPos;    int CollisionNum;    CollisionNum = 0;    CurrentPos = Hash(key, H->TableSize);    while(H->TheCells[ CurrentPos].Info !=Empty &&            H->TheCells[ CurrentPos].Element != key)            /*Probably need strcmp*/    {        CurrentPos += 2 * ++CollisionNum -1;        if(CurrentPos >= H->TableSize)            CurrentPos -= H->TableSize;    }    return CurrentPos;     //return the position

虽然说平方探测派出了一次聚集,但是散列到同一位置上的那些元素将探测相同的备选单元。形成了二次聚集。

原创粉丝点击