算法导论 开放寻址法

来源:互联网 发布:tv007网络电视手机版 编辑:程序博客网 时间:2024/05/29 18:06

散列表

11.4 开放寻址法

  1. 开放寻址法中,所有的元素都存放在散列表里,每个表项或包含动态集合的一个元素或者NIL。当查找某个元素时,要系统的检查所有表项,直到找到所有的元素或者最终查明元素不在表中。
  2. 为了使用开放寻址法插入一个元素,需要连续的检查散列表,或称为探查(probe),直到找到一个空槽来放置待插入的关键字为止。检查的顺序不一定是0,1,2…m的顺序序列,而是依赖于待插入的关键字。
  3. 将散列函数扩充,使之包含探查号,即 U(0,1,...,m1)(0,1,...,m1),对每一个关键字,使用开放寻址法的探查序列 ( h(k,0),h(k,1),…, h(k,m-1) )
  4. 该散列方法的思想在于:插入一个关键字k,如果k被占用,则往后一个位置插入, 直到没有空间。与链接法相比,不需要指针,所以可以将指针所占用的空间存放更多的槽。
  5. 缺点在于:该方法的删除操作,如果删除了某个关键字后,无法检索到以后的关键字了。如果用一个特定的值代替,查找时间就不依赖于转载因子α了。
  6. 定义一个均匀散列的假设:每个关键字的探查序列等可能的为0,1…,m-1中的m!中排列的一种。
  7. 三种技术用来计算探查序列:
    • 线性探查
      • 线性探查所用的散列函数为:h(k,i)=(h’(k)+i) mod m,i=0,1…,m-1
      • 问题:随着连续被占用的槽不断增加,平均查找时间也随之不断增加。
    • 二次探查
      • 采用如下的散列函数 h(k,i)=(h’(k)+i) mod m,i=0,1,…m-1
      • 问题:如果两个关键字的初始探查位置相同,那么它们的探查序列也是相同的。
    • 双重散列
      • 散列函数: h(k,i)=(h1(k)+ih2(k))%m
      • 这个函数的探查序列以两种不同方式依赖于关键字k。
  8. 定理:给定一个装载因子为α=n/m<1的开放寻址散列表,并假设其是均匀散列的,则对于一次不成功的查找,其期望的探查次数至多为1/(1-α)

练习

11.4-1

代码如下:

```#include<stdio.h> //线性散列int Linear_probing(int m,int key,int i){return (key+i)%m;}//二次散列int quadratic_probing(int m,int key,int i){    return  (key+i+3*i*i)%m;}//多重散列int double_hashing(int m,int key,int i){    return (key+i*(1+key%(m-1)))%m;}//插入过程,其中有个函数指针,传递所需的散列函数void  Insert(int a[],int (*func)(int ,int,int),int m,int key){    int i=0;    int x; do{     x=func(m,key,i);    if(a[x]==-1)     {           a[x]=key;           return;     }        else         i++; }while(i!=m);     printf("no slot to insert \n");}//搜索过程,用函数指针,传递散列函数int Search(int a[],int (*func)(int,int,int) ,int m,int key){    int i=0;    int x=func(m,key,i);    while(key!=a[x]&&i<m)    {        i++;        x=func(m,key,i);    }    if(i==m)    {          return -1;    }    else    {        printf("%d\n",x);          return x;      }}int main(){    int m=11;    int hash_Linear[11];    int hash_Quad[11];    int hash_Doub[11];    int i;    //列表初始化     for(i=0;i<11;i++)        {            hash_Linear[i]=-1;  //-1代表槽中没有元素            hash_Quad[i]=-1;  //C语言初始化真坑,不能{}            hash_Doub[i]=-1;  //挑了我半天bug!!        }    int b[9]={10,22,31,4,15,28,17,88,59};    int j;    for(j=0;j<9;j++)    {        Insert(hash_Linear,Linear_probing,11,b[j]);        Insert(hash_Quad,quadratic_probing,11,b[j]);        Insert(hash_Doub,double_hashing,11,b[j]);    }    for(j=0;j<11;j++)    {        printf("%d\t",hash_Linear[j]);    }    printf("\n");    for(i=0;i<11;i++)    {        printf("%d\t",hash_Quad[i]);    }    printf("\n");    for(i=0;i<11;i++)    {        printf("%d\t",hash_Doub[i]);    }    printf("\n");    return 0;}```

11.4-2

  • 将上述插入代码的条件判断增加一个DELETED,可以用-2赋值为删除。

11.4-3

  • 根据书上公式,可得出

11.4-4

  • 先占坑,证明留待以后完成

11.5 完全散列

  • 当关键字为静态时,散列技术能提供出色的最佳情况性能。所谓静态,就是指一旦给定各关键字存入表中,关键字集合就不在变化了
  • 一种能在最坏情况下用O(1)访存完成的查找,是完全散列
  • 完全散列用两级的散列方法来设计
    • 第一级与带链接的散列表基本上是一样的,利用从某一全域散列函数簇中仔细挑选一个散列函数h,将n个关键字集合散列到m个槽中
    • 采用一个较小的二级散列表,为确保二级上不出现冲突,需要让散列表的大小为散列槽的平方个数
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 老公投的公司倒闭了钱怎么办 小丑鱼老在缸上边游不下去怎么办 海缸养珊瑚又想养蝴蝶鱼怎么办 被几个月的小狗咬了怎么办 木本植物继代长出大量愈伤怎么办 钱兜树叶子发黄掉叶怎么办 手机qq群200人满了怎么办 支票被背书人的章盖浅了怎么办 没病装病的心理病患者怎么办 20多岁被骗40多万怎么办 一个学生上课爱捣乱班级课堂怎么办 军训的时候大姨妈来了怎么办 笔记本连接无线网说链接限制怎么办 12306密码和邮箱都忘了怎么办 烦恼都是自找的新书散页了怎么办 白色衣服被红色衣服染了怎么办 手机微信里面不能拍手功怎么办 肇事逃逸轻伤且对方不私了怎么办 数学差怎么办脑子不好啊数学学不老 手机号丢失微信密码丢失怎么办找回 悦借钱输入五次密码被锁怎么办 生源地助学贷款密码忘了怎么办 生源地助学贷款登录密码忘了怎么办 助学贷款支付宝密码忘了怎么办 微信密码忘记了手机号也换了怎么办 换手机号了微信密码忘记了怎么办 qq密码忘记了手机号也换了怎么办 一年只能修改一次昵称我能怎么办 华为手机的账号和密码丢失怎么办 华为手机的账号和密码丢失了怎么办 手机号被别人注册了微博怎么办 微博账号一天内多次解冻怎么办 露娜注册时邮箱填错了怎么办 苹果4s手机显示已停用怎么办 新买的微博小号太多内容了怎么办 向海关申报价格低于实际价格怎么办 百度云下载内容包含违规信息怎么办 跨境汇款错了不能退款怎么办 公司欠钱没有还被起诉了。怎么办 战网的姓名不是身份证名字怎么办 手机号码被别人注册了微信怎么办