`
iwebcode
  • 浏览: 2020916 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

散列表-开放地址法

 
阅读更多

散列表的查找过程和建表过程相似。假设给定的值为K,根据建表时设定的散列函数h,计算出散列地址h(K),若表中该地址单元为空,则查找失败;否则将该地址中的结点与给定值K比较。若相等则查找成功,否则按建表时设定的处理冲突的方法找下一个地址。如此反复下去,直到某个地址单元为空(查找失败)或者关键字比较相等(查找成功)为止。

(1)开放地址法一般形式的函数表示
int Hash(KeyType k,int i)
{ //求在散列表T[0..m-1]中第i次探查的散列地址hi,0≤i≤m-1
//下面的h是散列函数。Increment是求增量序列的函数,它依赖于解决冲突的方法
return(h(K)+Increment(i))%m; //Increment(i)相当于是di
}
若散列函数用除余法构造,并假设使用线性探查的开放定址法处理冲突,则上述函数中的h(K)和Increment(i)可定义为:
int h(KeyType K){ //用除余法求K的散列地址
return K%m;
}

int Increment(int i){//用线性探查法求第i个增量di
return i; //若用二次探查法,则返回i*i
}

(2)通用的开放定址法的散列表查找算法:
int HashSearch(HashTable T,KeyType K,int *pos)
{ //在散列表T[0..m-1]中查找K,成功时返回1。失败有两种情况:找到一个开放地址
//时返回0,表满未找到时返回-1。 *pos记录找到K或找到空结点时表中的位置
int i=0; //记录探查次数
do{
*pos=Hash(K,i); //求探查地址hi
if(T[*pos].key==K) return l; //查找成功返回
if(T[*pos].key==NIL) return 0;//查找到空结点返回
}while(++i<m) //最多做m次探查
return -1; //表满且未找到时,查找失败
} //HashSearch

注意:
 上述算法适用于任何开放定址法,只要给出函数Hash中的散列函数h(K)和增量函数Increment(i)即可。但要提高查找效率时,可将确定的散列函数和求增量的方法直接写入算法HashSearch中,相应的算法【参见习题】。

3、基于开放地址法的插入及建表
 建表时首先要将表中各结点的关键字清空,使其地址为开放的;然后调用插入算法将给定的关键字序列依次插入表中。
 插入算法首先调用查找算法,若在表中找到待插入的关键字或表已满,则插入失败;若在表中找到一个开放地址,则将待插入的结点插入其中,即插入成功。
void Hashlnsert(HashTable T,NodeTypene w)
{ //将新结点new插入散列表T[0..m-1]中
int pos,sign;
sign=HashSearch(T,new.key,&pos); //在表T中查找new的插入位置
if(!sign) //找到一个开放的地址pos
T[pos]=new; //插入新结点new,插入成功
else //插人失败
if(sign>0)
printf("duplicate key!"); //重复的关键字
else //sign<0
Error("hashtableoverflow!"); //表满错误,终止程序执行
} //Hashlnsert

void CreateHashTable(HashTable T,NodeType A[],int n)
{ //根据A[0..n-1]中结点建立散列表T[0..m-1]
int i
if(n>m) //用开放定址法处理冲突时,装填因子α须不大于1
Error("Load factor>1");
for(i=0;i<m;i++)
T[i].key=NIL; //将各关键字清空,使地址i为开放地址
for(i=0;i<n;i++) //依次将A[0..n-1]插入到散列表T[0..m-1]中
Hashlnsert(T,A[i]);
} //CreateHashTable

4、删除
 基于开放定址法的散列表不宜执行散列表的删除操作。若必须在散列表中删除结点,则不能将被删结点的关键字置为NIL,而应该将其置为特定的标记DELETED。
 因此须对查找操作做相应的修改,使之探查到此标记时继续探查下去。同时也要修改插人操作,使其探查到DELETED标记时,将相应的表单元视为一个空单元,将新结点插入其中。这样做无疑增加了时间开销,并且查找时间不再依赖于装填因子。
 因此,当必须对散列表做删除结点的操作时,一般是用拉链法来解决冲突。

5、性能分析
 插入和删除的时间均取决于查找,故下面只分析查找操作的时间性能。
 虽然散列表在关键字和存储位置之间建立了对应关系,理想情况是无须关键字的比较就可找到待查关键字。但是由于冲突的存在,散列表的查找过程仍是一个和关键字比较的过程,不过散列表的平均查找长度比顺序查找、二分查找等完全依赖于关键字比较的查找要小得多。

(1)查找成功的ASL
 散列表上的查找优于顺序查找和二分查找。
  【例】在例9.1和例9.2的散列表中,在结点的查找概率相等的假设下,线性探查法和拉链法查找成功的平均查找长度分别为:
ASL=(1×6+2×2+3×l+9×1)/10=2.2 //线性探查法
ASL=(1×7+2×2+3×1)/10=1.4 //拉链法
  而当n=10时,顺序查找和二分查找的平均查找长度(成功时)分别为:
ASL=(10+1)/2=5.5 //顺序查找
ASL=(1×l+2×2+3×4+4×3)/10=2.9 //二分查找,可由判定树求出该值

(2) 查找不成功的ASL
 对于不成功的查找,顺序查找和二分查找所需进行的关键字比较次数仅取决于表长,而散列查找所需进行的关键字比较次数和待查结点有关。因此,在等概率情况下,也可将散列表在查找不成功时的平均查找长度,定义为查找不成功时对关键字需要执行的平均比较次数。
  【例】例9.1和例9.2的散列表中,在等概率情况下,查找不成功时的线性探查法和拉链法的平均查找长度分别为:
ASLunsucc=(9+8+7+6+5+4+3+2+1+1+2+1+10)/13=59/13≈4.54
ASLunsucc=(1+0+2+1+0+1+1+0+0+0+1+0+3)/13≈10/13≈0.77
注意:
  ①由同一个散列函数、不同的解决冲突方法构造的散列表,其平均查找长度是不相同的。
 ②散列表的平均查找长度不是结点个数n的函数,而是装填因子α的函数。因此在设计散列表时可选择α以控制散列表的平均查找长度。
 ③ α的取值
 α越小,产生冲突的机会就小,但α过小,空间的浪费就过多。只要α选择合适,散列表上的平均查找长度就是一个常数,即散列表上查找的平均时间为O(1)。
 ④ 散列法与其他查找方法的区别
除散列法外,其他查找方法有共同特征为:均是建立在比较关键字的基础上。其中顺序查找是对无序集合的查找,每次关键字的比较结果为"="或"!="两种可能,其平均时间为O(n);其余的查找均是对有序集合的查找,每次关键字的比较有"="、"<"和">"三种可能,且每次比较后均能缩小下次的查找范围,故查找速度更快,其平均时间为O(lgn)。而散列法是根据关键字直接求出地址的查找方法,其查找的期望时间为O(1)。

分享到:
评论

相关推荐

    散列表之开放定址法

    在散列表里面经常发生散列值冲突,为了解决散列冲突问题,开放定址法是一种简单又高效的方法

    散列表C++实现(不同装载因子的开放寻址法和链表法比较)

    2.open_hash-onetime.exe:是使用开放地址法的散列程序,它是在n=80000,m=100000,即在装载因子是0.8的情况下测试的。该程序演示的功能和上类似。 3.chain-hash-different-loading-factors(all_success).exe。它是...

    散列表 (哈希表,线性探测再散列)

    散列表,也称为哈希表。根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置的表。 哈希函数的构造方法:1)...

    散列表的建立和查找.zip

    假设关键字为整型数据,散列函数用除留余数法,采用开放定址法的线性探测法处理冲突。 1.从键盘输入关键字个数n及关键字数据; 2.根据输入的关键字个数及平均查找长度要求,设计散列函数和计算表长; 3.构造散列表;...

    数据结构算法\哈希表开放地址法解决冲突

    数据结构算法\哈希表开放地址法解决冲突

    散列表实验报告(不同装载因子下的链表法和开放寻址法的对比)

    该实验报告主要是通过介绍散列表的各种技术,包括散列函数、解决碰撞的机制等技术,并对两种解决碰撞的机制:链接法和开放寻址法进行分析和证明,并通过实验分析两者在不同的装载因子下的运行时间和空间占用的对比,...

    LAW文件解压缩+散列表

    1.用于散列表的链表;2.开放寻址和链接法的散列表;3.LZW文件压缩和解压

    算法基础-散列表的原理及基础操作

    文章目录前言正文什么是散列表Hash的数据结构存储数据的数组散列函数Hash的负载因子开放寻址法链表法Hash结构的几个操作读操作开放寻址法的读操作链表法的读操作写操作开放寻址法的写操作链表法的写入扩容总结 ...

    散列表与散列冲突

    散列表与散列冲突 解决散列冲突的方法 1.分离链接法(拉链法) 2.开放寻址法 再散列 散列表与散列冲突 HashTable,音译为哈希表,是根据关键字(key)而直接进行访问的数据结构。关键字k,值存放在f(k)的存储位置上...

    哈希表课程设计

    采用开放定址法建立散列表。 (3)显示开放定址散列表最高的寻址次数,若次数过高,则重建散列表; (4)输入手机号码,对该手机号码进行哈希查找,显示散列的次数,若号码存在,则显示号码对应的人名、性别以及...

    数据结构--查找--思维导图.pdf

    链地址法是指把所有同义词存放在一个线性链表中,这个线性链表由地址唯一标识,即散列表中每个单元存放该链表头指针。链地址法适用于经常进行插入和删除的情况。 分块查找 分块查找又称索引顺序查找,它吸取了顺序...

    19丨散列表(中):如何打造一个工业级水平的散列表?1

    1. 开放寻址法 2. 链表法 1. 初始大小 2. 装载因子和动态扩容 3. 散列冲突解决方法

    java算法与数据结构

    (2)散列表解决散列冲突的方法(开放地址法、链地址法) (3)散列表的插入和删除 6.算法分析与设计基础 (1)分治与递归的关系 (2)贪心算法的思想 (3)回溯与分支限界算法的比较 (4)算法时间和空间复杂度的...

    leetcode2-Algorithms:算法导论

    (开放地址法) 完美散列 (针对静态集合) chapter 12 二叉搜索树 chapter 13 红黑树 chapter 14 区间树 顺序统计树 chapter 15 切割钢管问题 最长公共子序列问题 矩阵链乘法问题 最优二叉搜索树问题 chapter 16 活动...

    数据结构和算法动画演示

    开放定址法建立散列表 拉链法创建散列表 朴素串匹配算法过程示意 图的深度优先遍历 邻接表表示的图的广度优先遍历 邻接表表示的图的深度优先遍历 拓扑排序 最短路径 克鲁斯卡尔算法构造最小生成树 B树的删除 B树的...

    Flash动画演示 数据结构和算法

    开放定址法建立散列表.swf 循环队列操作演示.swf 快速排序.swf 拉链法创建散列表.swf 拓扑排序.swf 最短路径.swf 朴素串匹配算法过程示意.swf 构造哈夫曼树的算法模拟.swf 构造哈夫曼树过程.swf 栈与递归.swf 树、...

    数据结构和算法Flash动画演示

    单链表结点的插入,图的深度优先遍历,基数排序,堆排序,头插法建单链表,寻找中序线索化二叉树指定结点的前驱,寻找中序线索化二叉树指定结点的后继,尾插法建表,希儿排序,开放定址法建立散列表,循环队列操作...

    操作系统之哈希表Linux内核应用浅析

    散列表(Hashtable。也叫哈希表)。是依据关键码值(Keyvalue)而直接进行訪问的数据结构。也就是说,它通过把关键码值...常见有冲突处理方法有:(1)开放定址法(2)再散列法(3)链地址法(拉链法)(4)建立一个公共溢出区散列

    数据结构动画演示学习工具SWF.zip

    树的删除.swfB树的生成.swf查找中序线索二叉树后继.swf串的顺序存单链表...开放定址法建立散列表.swf克鲁斯卡尔算法构造最小生成树.swf快速排序.swf拉链法创建散列表.swf邻接表表示的图的广度优先遍历.swf邻接表表示的...

    钢条切割问题leetcode-clrs:python实现的clrs算法

    开放寻址法散列表 theta(1/(1-alpha)) 优秀的查找速度,对删除操作支持不好 完全散列 theta(1) 极好的查找速度,建表慢,一旦建好,不支持对表结构改变 树 普通二叉树 search, minimum, maximum, successor, ...

Global site tag (gtag.js) - Google Analytics