第七章 哈希表

上章回顾

常见的排序算法有哪些

其中那种算法的效率最高

对大量的数据进行排序的化最好使用那种排

序算法

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

第七章

第七章

哈希表 哈希表

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

预习检查

哈希表的定义

处理冲突的方法有那些

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

本章结构

哈希表 哈希表

哈希函数的构造方法

哈希函数的构造方法

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

什么是哈希表

什么是哈希表

处理冲突的方法

处理冲突的方法

课程目标

了解什么是哈希表

掌握如何构造哈希函数

处理冲突的方式

哈希表的查找及分析

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1 哈希表 哈希表又称散列表。

哈希表存储的基本思想是:以数据表中的每个记录的关 键字 k为自变量,通过一种函数H(k)计算出函数值。把这个 值解释为一块连续存储空间(即数组空间)的单元地址(即下 标),将该记录存储到这个单元中。在此称该函数H为哈希函 数或散列函数。按这种方法建立的表称为哈希表或散列表。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 6

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1 哈希表

例如,要将关键字值序列(3,15,22,24),存储到编号为0到4的表 长为5的哈希表中。

计算存储地址的哈希函数可取除5的取余数算法H(k)=k % 5。则构造好的 哈希表如图所示。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 7

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1 哈希表

理想情况下,哈希函数在关键字和地址之间建立了一个一一对应关系, 从而使得查找只需一次计算即可完成。由于关键字值的某种随机性,使 得这种一一对应关系难以发现或构造。因而可能会出现不同的关键字对 应一个存储地址。即k1≠k2,但H(k1)=H(k2),这种现象称为冲突。

把这种具有不同关键字值而具有相同哈希地址的对象称同义词。 在大多数情况下,冲突是不能完全避免的。这是因为所有可能的关键字

的集合可能比较大,而对应的地址数则可能比较少。 对于哈希技术,主要研究两个问题:

(1)如何设计哈希函数以使冲突尽可能少地发生。 (2)发生冲突后如何解决。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 8

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

构造好的哈希函数的方法,应能使冲突尽可能地少,因而 应具有较好的随机性。这样可使一组关键字的散列地址均匀地 分布在整个地址空间。根据关键字的结构和分布的不同,可构 造出许多不同的哈希函数。

1.直接定址法 直接定址法是以关键字k本身或关键字加上某个数值常量c

作为哈希地址的方法。该哈希函数H(k)为:

H(k)=k+c (c≥0)

这种哈希函数计算简单,并且不可能有冲突发生。当关键

字的分布基本连续时,可使用直接定址法的哈希函数。否则,

若关键字分布不连续将造成内存单元的大量浪费。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 9

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

例:统计某地区从1949年到1995年每年出生的人数,列在一张表中。 年份为关键字,因共有47年,所以表中位置范围是1~47。

设置H(k)=k-1948即可,其中k为年份数。 这样的哈希表示意如下:

年份 人数

1 1949

2 ... 47 1950 1995

...

... ... ...

若要查1970年的出生人数,则根据(1970- 1948=22)计算,在表的第22个位置即可找到。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 10

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

2.除留余数法 取关键字k除以哈希表长度m所得余数作为哈希函数地址的

方法。即:

H(k)=k%m

这是一种较简单、也是较常见的构造方法。这种方法的关 键是选择好哈希表的长度m。使得数据集合中的每一个关键字 通过该函数转化后映射到哈希表的任意地址上的概率相等。理 论研究表明,在m取值为素数(质数)时,冲突可能性相对较 少。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 11

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

3.平方取中法 取关键字平方后的中间几位作为哈希函数地址(若超出

范围时,可再取模)。

设有一组关键字ABC,BCD,CDE,DEF,......其对应的机 内码如表所示。假定地址空间的大小为1000,编号为0- 999。现按平方取中法构造哈希函数,则可取关键字机内码 平方后的中间三位作为存储位置。计算过程如下表所示:

2011-11-13

12

关键字 机内码

机内码的平方数

哈希地址

ABC 010203

0104101209 101

BCD 020304

0412252416 252

CDE 030405

0924464025 464

DEF 040506

1640739036 739

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git... ... ...

...

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

4.折叠法 这种方法适合在关键字的位数较多,而地址区间较

小的情况。

将关键字分隔成位数相同的几部分。然后将这几部 分的叠加和作为哈希地址(若超出范围,可再取模)。

例如,假设关键字为某人身份证号码 430104681015355,则可以用4位为一组进行叠加。即有 5355+8101+1046+430=14932,舍去高位。

则有H(430104681015355)=4932 为该身份证关键字的哈希函数地址。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 13

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

5.数值分析法

若事先知道所有可能的关键字的取值时,可通过

对这些关键字进行分析,发现其变化规律,构造出相

应的哈希函数。

例:对如下一组关键字通过分析可知:每个关键字从 左到右的第l,2,3位和第6位取值较集中,不宜作哈 希地址。

剩余的第4,5,7和8位取值较分散,可根据实际需 要取其中的若干位作为哈希地址。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 14 [email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.1 哈希函数的构造方法

若取最后两位作为哈希地址,则哈希地址的集

合为下表所示:

关键字

哈希函数地址

92317602 2 92326875 75 92739628 28 92343634 34 92706816 16 92774638 38 92381262 62

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 15

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

假设哈希表的地址范围为0~m-l,当对给定的关键 字k,由哈希函数H(k)算出的哈希地址为i(0≤i≤m-1) 的位置上已存有记录,这种情况就是冲突现象。

处理冲突就是为该关键字的记录找到另一个的哈

希地址。即通过一个新的哈希函数得到一个新的哈希地 址。如果仍然发生冲突,则再求下一个,依次类推。直至 新的哈希地址不再发生冲突为止。

常用的处理冲突的方法有开放地址法、链地址法两大 类

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 16

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

1.开放定址法

用开放定址法处理冲突就是当冲突发生时,形成一个地址 序列。沿着这个序列逐个探测,直到找出一个的开放地

址。将发生冲突的关键字值存放到该地址中去。

如 Hi=(H(k)+d(i)) % m, i=1,2,...k (k<m-1)

其中H(k)为哈希函数,m为哈希表长,d为增量函数, d(i)=dl,d2...dn-l。

增量序列的取法不同,可得到不同的开放地址处理冲突探

测方法。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 17

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

(1)线性探测法

线性探测法是从发生冲突的地址(设为d)开始,依次探 查d+l,d+2,...m-1(当达到表尾m-1时,又从0开始探查)

等地址,直到找到一个空闲位置来存放冲突处的关键字。

若整个地址都找遍仍无空地址,则产生溢出。

线性探查法的数学递推描述公式为:

d0=H(k)

di=(di-1+1)% m (1≤i≤m-1)

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 18

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

【例】已知哈希表地址区间为0~10,给定关键字序列(20,30,70,15, 8,12,18,63,19)。哈希函数为H(k)=k%ll,采用线性探测法处理冲 突,则将以上关键字依次存储到哈希表中。试构造出该哈希表,并求出等 概率情况下的平均查找长度。

假设数组为A, 本题中各元素的存放过程如下: H(20)=9,可直接存放到A[9]中去。 H(30)=8,可直接存放到A[8]中去。 H(70)=4,可直接存放到A[4]中去。 H(15)=4,冲突;

d0=4

d1=(4+1)%11=5,将15放入到A[5]中。 H(8)=8,冲突;

d0=8

d1=(8+1)%11=9,仍冲突; d2=(8+2)%11=10,将8放入到A[10]中。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 19

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

H(12)=l,可直接存放到A[1]中去。 H(18)=7,可直接存放到A[7]中去。 H(63)=8,冲突;

d0=8

d1=(8+1)%11=9,仍冲突; d2=(8+2)%11=10,仍冲突; d3=(8+3)%11=0,将63放入到A[0]中。

H(19)=8,冲突; d0=8

d1=(8+1)%11=9,仍冲突; d2=(8+2)%11=10,仍冲突; d3=(8+3)%11=0,仍冲突; d4=(8+4)%11=1,仍冲突; d5=(8+5)%11=2,将19放入到A[2]中。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 20

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

由此得哈希表如图所示

0 1 2 3 4 5 6 7 8 9 10 A 63 12 19 70 15 18 30 20 8

探查次数4 1 6 1 2 1 1 1 3

在等概率情况下成功的平均查找长度为: (1*5+2+3+4+6)/9 =20/9

利用线性探查法处理冲突容易造成关键字的堆积问题。这是因为 当连续n个单元被占用后,再散列到这些单元上的关键字和直接散列到

后面一个空闲单元上的关键字都要占用这个空闲单元,致使该空闲单元 很容易被占用,从而发生非同义冲突。造成平均查找长度的增加。

为了克服堆积现象的发生,可以用下面的方法替代线性探查法。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 21

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

(2)平方探查法

设发生冲突的地址为d,则平方探查法的探查序列为: d+12,d+22,...直到找到一个空闲位置为止。

平方探查法的数学描述公式为:

d0=H(k)

di=(d0+i2) % m (1≤i≤m-1)

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 22

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

【例】已知哈希表地址区间为0~10,给定关键字序列(20, 30,70,15,8,12,18,63,19)。哈希函数为H(k)=k%ll,采 用平方探查法处理冲突。

【解】 H(20)=9,可直接存放到A[9]中去。 H(30)=8,可直接存放到A[8]中去。 H(70)=4,可直接存放到A[4]中去。 H(15)=4,冲突;

d0=4

d1=(4+12) % 11=5,放到A[5]中。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 23

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

H(8)=8,冲突;

d0=8

d1=(8+12) % 11=9,仍冲突 d2=(8+22) % 11=1 放到A[1]中。

H(12)=l,冲突;

d0=1

d1=(1+12) % 11=2,放到A[2]中。 H(18)=7,可直接存放到A[7]中去。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 24

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

H(63)=8,冲突;

d0=8

d1=(8+12) % 11=9,仍冲突 d2=(8+22) % 11=1,仍冲突 d3=(8+32) % 11=6,放到A[6]中。

H(19)=8,冲突;

d0=8

d1=(8+12) % 11=9,仍冲突

d2=(8+22) % 11=1,仍冲突

d3=(8+32) % 11=6,仍冲突

d4=(8+42)% 11= 2,仍冲突

d5=(8+52) % 11=0,放到A[0]中

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 25

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

建立的哈希表如图所示:

0 1 2 3 4 5 6 7 8 9 10

A 19 8 12 70 15 63 18 30 20 探查次数6 3 2 1 2 4 1 1 1

在等概率情况下成功的平均查找长度为: (1*4+2*2+3+4+6)/9 =21/9

平方探查法是一种较好的处理冲突的方法,可以避免出现堆积问 题。它的缺点是不能探查到哈希表上的所有单元,但至少能探查到 一半单元。

例如,若表长m=13,假设在第3个位置发生冲突,则后面探查的 位置依次为4712620,即可以探查到一半单元。

若解决冲突时,探查到一半单元仍找不到一个空闲单元。则表明 此哈希表太满,需重新建立哈希表。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 26

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.2 冲突的解决方法

2.链地址法

2011-11-13

27

用链地址法解决冲突的方法是:把所有关键字为同义

词的记录存储在一个线性链表中,这个链表称为同义词链 表。并将这些链表的表头指针放在数组中(下标从0m- 1)。这类似于图中的邻接表和树中孩子链表的结构。

0

^

^

1

12

2

^ ^

3

4

70 15

^

5

^ ^

6

7

18

^

8 30 8 63 19

^

9

20

^

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

10

^

7.1.2 冲突的解决方法

链地址法查找分析

由于在各链表中的第一个元素的查找长度为l,第二个元素的查找长度 为2,依此类推。因此,在等概率情况下成功的平均查找长度为:

(1*5+2*2+3*l+4*1)/9=16/9 虽然链地址法要多费一些存储空间,但是彻底解决了堆积问题,

大大提高了查找效率。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 28

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.3 哈希表的查找及性能分析

哈希法是利用关键字进行计算后直接求出存储地址的。当哈希函数能 得到均匀的地址分布时,不需要进行任何比较就可以直接找到所要查的 记录。但实际上不可能完全避免冲突,因此查找时还需要进行探测比 较。

在哈希表中,虽然冲突很难避免,但发生冲突的可能性却有大有小。这 主要与三个因素有关。

第一:与装填因子有关

所谓装填因子是指哈希表中己存入的元素个数n与哈希表的大小m的比 值,即 =n/m。

当 越小时,发生冲突的可能性越小,越大(最大为1)时,发生冲突 的可能性就越大。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 29

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

7.1.3 哈希表的查找及性能分析

第二:与所构造的哈希函数有关

若哈希函数选择得当,就可使哈希地址尽可能均匀地

分布在哈希地址空间上,从而减少冲突的发生。否则,若

哈希函数选择不当,就可能使哈希地址集中于某些区域,

从而加大冲突的发生。

第三:与解决冲突的哈希冲突函数有关

哈希冲突函数选择的好坏也将减少或增加发生冲突的

可能性。

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 30

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

有关哈希表的算法

1.基于开放地址法的哈希表的建立

#define NIL -1

#define M 997

typedef int KeyType;

typedef struct node{

KeyType key;

//表长度 //哈希表结点类型

//其他数据域 }HashType;

用除余法求K的哈希地址的函数h

int h(KeyType K)

{ return K%M; }

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 31

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

Increment是求增量序列的函数,它依赖于解决冲突的方法

int Increment(int i) //用线性探查法求第i个增量di { return i; }

求在哈希表T[0..M-1]中第i次探查的哈希地址hi,0≤i≤M-1

int Hash(KeyType k,int i)

{ return (h(k)+Increment(i))%M; }

在哈希表T[0..M-1]中查找K,成功时返回1。失败有两种情况:找到一个开放址时返回0;表满未找到时返 回-1

int HashSearch(HashType T[],KeyType K,int *pos) { int i=0; //记录探查次数

do{ *pos=Hash(K,i); //求探查地址hi

}while(++i<M);

return -1; }

//最多做M次探查 //表满且未找到时,查找失败

if(T[*pos].key==K) return 1; if(T[*pos].key==NIL) return 0; //查找到空结点返回

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

32

2011-11-13

将新结点newnode插入哈希表T[0..M-1]中

void Hashlnsert(HashType T[],HashType newnode) { int pos,sign;

}

sign=HashSearch(T,newnode.key,&pos); if(!sign) //找到一个开放的地址pos

T[pos]=newnode; //插入新结点newnode,插入成功 else //插人失败

if(sign>0) printf("重复的关键字!");

else { printf(表满错误,终止程序执行!); exit(0);}

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 33

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

根据A[0..n-1]中结点建立哈希表T[0..M-1]

void CreateHashTable(HashType T[],HashType A[],int n) { if(n>M){ //用开放定址法处理冲突时,装填因子α须不大于1

printf("装填因子α须不大于1");

     exit(0); }

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]);

}

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 34

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2.基于链地址法的哈希表的建立

#define M 997

  typedef int KeyType;

  typedef struct chain{

KeyType key;

  struct chain *next;

}ChainType;

int h(KeyType K)

  { return K%M; }

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 35

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

在链地址表示的哈希表中某条链中查找关键字K,找到返回该记录地址;否则返回空值;

ChainType *HashSearch(ChainType *Ti,

KeyType K,ChainType **end)

{ ChainType *pre,*cur;

pre=NULL; cur=Ti;

while(cur!=NULL && cur->key!=K){ //查找

pre=cur; cur=cur->next; }

*end=pre;

if(cur==NULL) return NULL; //查找不到时,返回空值 else return cur; //查找到时,返回该记录地址 }

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 36

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

在链地址的哈希表T中若找不到关键字为K的记录,则插入该记录

int HashInsert(ChainType *T[],KeyType K)

{ ChainType *pre,*cur;

i=h(K); cur=HashSearch(T[i],K,&pre); if(cur==NULL){ //未找到时,在链表尾插入该记录

cur=(ChainType *)malloc(sizeof(ChainType));

cur->key=K; cur->next=NULL; if(pre==NULL) //在该链插入第一条记录

T[i]=cur;

else //在该链插入后续记录

   pre->next=cur; return l; }

return 0;}

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 37

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

根据A[0..n-1]中结点建立哈希表T[0..m-1]

void CreateHashTable(ChainType *T[],ChainType A[],int n)

{ int i;

  for(i=0;i<n;i++)

   HashInsert(T,A[i]);

}

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

2011-11-13 38

[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

阶段小节

哈希算法的基本思想是什么

哈希算法的存储效率主要取决于什么   哈希算法解决冲突的方式有哪些

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

本章总结

哈希表 哈希表

哈希函数的构造方法

哈希函数的构造方法

讲解哈希函数的几种构造方式

什么是哈希表

什么是哈希表

处理冲突的方法

处理冲突的方法

如何处理哈希表的冲突

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

了解哈希表的定义

实验1 实验内容

题目:创建一个哈希表用于存放随机数。

实验目的

掌握哈希函数的构造方法

掌握哈表表处理冲突的方法

实验分析

创建一个哈希表 随即生成1000个随机数字存入哈希表中

[email protected]:Kevin-Dfg/[email protected]:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

时间: 2024-10-07 20:25:28

第七章 哈希表的相关文章

MIT算法导论——第七讲.哈希表

从作用上来讲,构建哈希表的目的是把搜索的时间复杂度降低到O(1),考虑到一个长度为n的序列,如果依次去比较进行搜索的话,时间复杂度是θ(n),或者对其先进行排序然后再搜索会更快一些,但这两种方法都不是最快的方法. 哈希表也叫散列表,他通过一个哈希函数H,把要存储的内容取一个键值,经过H的运算,把键值映射到一个有m个槽的表中去,最简单的例子就是手机里存储别人的电话号码,键值就是名字,内容就是电话号码等个人信息.这样的表有一个最大的好处就是一旦要查找某个值,比如说"张三"的电话号码,我们把

《Java数据结构和算法》- 哈希表

Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计算机内存都可以满足. 为了尽可能地存取每个员工的记录,使用工号从1(公司创业者)到1000(最近雇佣的工人).将工号作为关键字(事实上,用其他作为关键字完全没有必要).即使员工离职不在公司,他们的记录也是要保存在数据库中以供参考,在这种情况下需要使用什么数据结构呢? A: 一种可能使用数组,每个员工

perl5 第九章 关联数组/哈希表

第九章 关联数组/哈希表 by flamephoenix 一.数组变量的限制二.定义三.访问关联数组的元素四.增加元素五.创建关联数组六.从数组变量复制到关联数组七.元素的增删八.列出数组的索引和值九.用关联数组循环十.用关联数组创建数据结构  1.(单)链表  2.结构  3.树 一.数组变量的限制    在前面讲的数组变量中,可以通过下标访问其中的元素.例如,下列语句访问数组@array的第三个元素:    $scalar = $array[2];    虽然数组很有用,但它们有一个显著缺陷

SDUT 3379 数据结构实验之查找七:线性之哈希表

数据结构实验之查找七:线性之哈希表 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 根据给定的一系列整数关键字和素数p,用除留余数法定义hash函数H(Key)=Key%p,将关键字映射到长度为p的哈希表中,用线性探测法解决冲突.重复关键字放在hash表中的同一位置. Input 连续输入多组数据,每组输入数据第一行为两个正整数N(N <= 1000)和p(p >= N的最小素数),N是

Python算法教程第二章知识点:计时模块、字典与散哈希表、图与树的实现、成员查询、插入对象

本文目录:一.计时模块:二.字典与散哈希表:三.图与树的实现:四.成员查询:五.插入对象</br>一.计时模块(timeit.cProfile) import timeit timeit.timeit('x = 1 + 2') 既然学习算法,那么来计算程序所耗费的时间是重要的,但是需要注意:timeit()计时函数会多次运行相关的代码段并求得平均值,以提高计时的精准度,所以,我们需要预防早先的执行操作影响之后代码的执行.举个栗子:若我们执行排序算法,则只有第一次执行代码时是在随机的情况下计时,

48 容器(七)——HashMap底层:哈希表结构与哈希算法

哈希表结构 哈希表是由数组+链表组成的,首先有一个数组,数组的每一个位置都用来存储一个链表,链表的基本节点为:[hash值,key值,value值,next],当存入一个键值对时,首先调用hashcode()方法获得key的hashcode,然后通过算法计算出hash值,当不同的key取到相同的hash值时,后面的key作为一个节点连接到前一个相同hash值的key的节点. hash值的算法 最差的算法:hashcode/hashcode 会将所有的元素存储在数组的下标1位,实际上已经退化为一个

第七章 F# 库(三)

序列(Microsoft.FSharp.Collections.Seq)模块 Microsoft.FSharp.Collections.Seq 模块包含所有处理集合的模块,只要它支持 IEnumerable 接口, .NET 框架的 BCL 中的大多数集合都是的.这个模块之所以称为序列(Seq),是因为序列是IEnumerable 接口的别名,是对其简称,为了读.写更方便.给定类型定义时使用这个别名. 注意 FSLib 包含几个模块,用于处理不同类型的集合,包括Array(数组).Array2(

《Python核心编程》 第七章 映射和集合类型 - 习题

课后习题 7–1. 字典方法.哪个字典方法可以用来把两个字典合并到一起? 答: dict1 = {'1' :' python' } dict2 = {'2' :"hello" } dict1.update(dict2) dictAll = dict1 print dictAll Result: {'1': ' python', '2': 'hello'} 7–2. 字典的键.我们知道字典的值可以是任意的 Python 对象,那字典的键又如何呢?请试 着将除数字和字符串以外的其他不同类型

第七章学习小结

第七章主要学习了很多种查找方式,从最简单的线性表查找到树表的查找到散列表查找,不同的查找方式有不同的优点,下面根据练习来实际应用这些知识. 这个问题的任务很简单:将一个不同的正整数序列插入哈希表,并输出输入数字的位置.散列函数定义为h(key)=key%tsize,其中tsize是散列表的最大大小.二次探测(只有正增量)用于解决碰撞.请注意,表的大小最好是素数.如果用户给定的最大大小不是质数,则必须将表大小重新定义为大于用户给定大小的最小质数.输入规格:每个输入文件包含一个测试用例.对于每种情况