博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
71-哈希表的基本运算
阅读量:2043 次
发布时间:2019-04-28

本文共 3006 字,大约阅读时间需要 10 分钟。

1. 哈希表的基本运算

哈希表的存储结构定义如下:

#define MaxSize 100     //定义最大哈希表长度#define NULLKEY -1  //定义空关键字值#define DELKEY -2       //定义被删关键字值typedef int KeyType;        //关键字类型typedef char * InfoType;    //其他数据类型typedef struct{    KeyType key;        //关键字域    InfoType data;  //其他数据域    int count;      //探查次数域} HashData;typedef HashData HashTable[MaxSize];    //哈希表类型

创建哈希表(除留余数法):

/*创建哈希表(除留余数法)HashTable ha : 哈希表KeyType x[] : 建表的数据int n : 关键字个数int m : 哈希表大小int p : 除留余数法中的p*/void CreateHT(HashTable ha,KeyType x[],int n,int m,int p){    int i,n1=0;    //初始化哈希表    for (i=0; i

插入及建表:

/*插入及建表HashTable ha : 哈希表int n : 哈希表中当前已有关键字个数KeyType k :要插入的关键字int p : 除留余数法中的p*/void InsertHT(HashTable ha,int &n,KeyType k,int p , int m){    int i,adr;    //通过除留余数法计算出当前要插入的关键字的存储地址    adr=k % p;    //然后判断哈希地址是否空闲,是否有哈希冲突    if (ha[adr].key==NULLKEY || ha[adr].key==DELKEY)    {        //没有冲突就可以直接插入        ha[adr].key=k;        ha[adr].count=1;    }    else    {        //哈希地址有冲突,采用线性探查法解决冲突        //i表示探测次数        //如果发生冲突,该循环则会一直探测        i=1;        do        {            adr=(adr+1) % m;            i++;        }        while (ha[adr].key!=NULLKEY && ha[adr].key!=DELKEY);        ha[adr].key=k;        ha[adr].count=i;    }    n++;}

删除某个关键字:

/*HashTable ha : 哈希表int n : 哈希表中已有数据个数KeyType k : 要删除的数据int p : 除留余数法中的p*/int DeleteHT(HashTable ha,int p,int k,int &n , int m){    int adr;    //查找要删除的关键字的存储地址(下标),adr返回-1说明没找到,否则找到了    adr=SearchHT(ha,p,k,m);    if (adr!=-1)    {        //把该关键字标记为删除        ha[adr].key=DELKEY;        n--;        return 1;    }    else    {        return 0;    }}

查找某个关键字:

/*查找某个关键字返回值:返回该关键字的哈希地址*/int SearchHT(HashTable ha,int p,KeyType k , int m){    int i=0 , adr;    adr=k % p;    //按照线性探测法继续往后找    while (ha[adr].key!=NULLKEY && ha[adr].key!=k)    {        i++;        adr=(adr+1) % m;    }    //查找成功    if (ha[adr].key==k)         return adr;    //查找失败    else        return -1;}

2. 哈希表示例

  将关键字序列{7,8,30,11,18,9,14}散列存储到散列表中,散列表的存储空间是一个下标从0开始的一维数组。,散列函数为:H(key)=(key×3) mod 7,处理冲突采用线性探测再散列法,要求装填(载)因子为0.7。构造的散列表如下:n=7,α = 0.7 = n/m,则m = n/0.7 = 10

计算各关键字存储地址的过程如下:

计算关键字7的哈希地址:H(7)=7×3 mod 7=0,存储到哈希表中下标0的位置,只探测了一次。

计算关键字8的哈希地址:H(8)=8×3 mod 7=3,存储到哈希表中下标3的位置,只探测了一次。
计算关键字30的哈希地址:H(30)=30×3 mod 7=6,存储到哈希表中下标6的位置,只探测了一次。
计算关键字11的哈希地址:H(11)=11×3 mod 7=5,存储到哈希表中下标5的位置,只探测了一次。

  在计算关键字为18的哈希地址:H(18)=18×3 mod 7=5,显然关键字18和关键字11的哈希地址起冲突了,那么探测下一个哈希地址,d1=(5+1) mod 10 = 6,发现还是有冲突,继续探测下一个地址d2=(6+1) mod 10 = 7,没有发现冲突,那么把关键字18存储到哈希表中下标为7的位置上。

  其他的关键字同理,最后形成的哈希表结构如下图所示:

这里写图片描述

在等概率情况下:

  对于查找成功的平均查找长度来说,我们把哈希表中每个关键字探测次数全部加起来,再除以关键字个数n(n = 7),就得到了查找成功的平均查找长度为: ASL=(1+2+1+1+1+3+3)/7=12/7=1.71 A S L 成 功 = ( 1 + 2 + 1 + 1 + 1 + 3 + 3 ) / 7 = 12 / 7 = 1.71

  对于查找不成功的平均长度,我们知道由于任一关键字k,H(k)的值只能是0~6之间,不成功的情况,共有7种:

这里写图片描述

  从哈希表结构图来看,当哈希地址为H(k) = 0时,需要比较3次才会出现查找不成功的情况,H(k) = 1时需要比较2次才会出现查找不成功的情况,以此类推…… 当H(k) = 2只需要比较1次,当H(k) = 5时就需要比较5次。

  于是,我们把哈希表中每个关键字的查找不成功情况的比较次数全部加起来,再除以关键字个数n(n = 7),就得到了查找不成功的平均查找长度: ASL=(3+2+1+2+1+5+4)/7=18/7=2.57 A S L 不 成 功 = ( 3 + 2 + 1 + 2 + 1 + 5 + 4 ) / 7 = 18 / 7 = 2.57

你可能感兴趣的文章
(PAT 1141) PAT Ranking of Institutions (排序+unorded_map的使用)
查看>>
(PAT 1118) Birds in Forest (并查集)
查看>>
(PAT 1114) Family Property (并查集)
查看>>
(PAT 1127) ZigZagging on a Tree (二叉树建立+层序遍历)
查看>>
(PAT 1155) Heap Paths (堆+完全二叉树遍历)
查看>>
(PAT 1142) Maximal Clique (图中顶点与顶点之间的关系)
查看>>
(PAT 1126) Eulerian Path (欧拉图/欧拉回路判断)
查看>>
(PAT 1130) (二叉树加括号的表达式)
查看>>
(PAT 1122) Hamiltonian Cycle (哈密顿图)
查看>>
数据结构 拓扑排序
查看>>
(PAT 1146) Topological Order (拓扑排序)
查看>>
(PAT 1108) Finding Average (字符串处理)
查看>>
(PAT 1007) Maximum Subsequence Sum (DP-最大字串)
查看>>
最长不下降子序列自实现
查看>>
(PAT 1045) Favorite Color Stripe (DP-最长公共字串)
查看>>
(PAT 1040) Longest Symmetric String (DP-最长回文子串)
查看>>
(PAT 1145) Hashing - Average Search Time (哈希表冲突处理)
查看>>
(1129) Recommendation System 排序
查看>>
PAT1090 Highest Price in Supply Chain 树DFS
查看>>
(PAT 1096) Consecutive Factors (质因子分解)
查看>>