53
静静静静静 静静静静静 静静静静静 静静静静静 AVL AVL 静静静 (Hash)

静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表 (Hash)

Embed Size (px)

DESCRIPTION

第九章 查找. 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表 (Hash). 查找的基本概念. 备注. 概念. 查找表 查找操作针对的数据集,由同一类型的数据元素组成 关键字 (key) 数据元素中某个数据项的值,可唯一标识该数据元素 关键字和数据元素的类型说明,如. typedef float KeyType; // 实型 typedef int KeyType; // 整型 typedef char *KeyType; // 字符串型. typedef struct { KeyType key ; // 关键字域 - PowerPoint PPT Presentation

Citation preview

Page 1: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

静态查找表 动态查找表

二叉搜索树二叉搜索树 AVLAVL 树树

哈希表 (Hash)

Page 2: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

查找的基本概念

备注

Page 3: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

概念 查找表

查找操作针对的数据集,由同一类型的数据元素组成 关键字 (key)

数据元素中某个数据项的值,可唯一标识该数据元素 关键字和数据元素的类型说明,如

typedef float KeyType; // 实型typedef int KeyType; // 整型typedef char *KeyType; // 字符串型typedef struct { KeyType key; // 关键字域 … // 其它域}ElemType;

Page 4: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

概念 查找

在查找表中根据关键字找出特定的数据元素的操作

查找成功 关键字找到,返回对应数据元素在查询表中的

位置 查找失败

关键字没有找到,返回空记录或空指针

Page 5: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

概念 查找算法

取决于查找表的数据结构 静态查找表

查找表事先已确定 对查询表除了创建和销毁操作外,只有查找或遍历操作

动态查找表 查找表本身在查找过程中动态生成,即若没有找到,则

插入该元素 对查询表除了创建、销毁、查找、遍历操作外,还能进

行插入和删除操作

Page 6: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

对两个关键字的比较约定为如下的宏定义:

对数值型关键字#define EQ(a,b) ((a)==(b))#define LT(a,b) ((a)<(b))#define LQ(a,b) ((a)<=(b))对字符串型关键字#define EQ(a,b) (!strcmp((a),(b)))#define LT(a,b) (strcmp((a),(b))<0)#define LQ(a,b) (strcmp((a),(b))<=0)

Page 7: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.1 静态表查找 顺序表的查找 有序表的查找 索引顺序表的查找

Page 8: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

静态查找表的类型定义:

ADT StaticSearchTable{数据对象 D : D 是具有相同特性的数据元素的集合。各个数据元素均含有类型相同,可唯一标识数据元素的关键字。

数据关系 R :数据元素同属一个集合。

基本操作 P :

Page 9: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

Create(&ST,n); 操作结果:构造一个含 n 个数据元素的静态查找表 ST 。

Destroy(&ST); 初始条件:静态查找表 ST 存在。操作结果:销毁表 ST 。

Search(ST,key); 初始条件:静态查找表 ST 存在, key 为和关键字类型相同的给定值。

操作结果:若 ST 中在在其关键字等于 key 的数据元素,则函数值为该元素的值或在表中的位置,否则为“空”。

Traverse(ST,Visit()); 初始条件:静态查找表 ST 存在, Visit 是对元素操作的应用函数。操作结果:按某种次序对ST 的每个元素调用函数 visit() 一次且仅一次。一旦 visit()失败,则操作失败。

}ADT StaticSearchTable

Page 10: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.1.1 顺序表的查找

顺序查找:从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,则查找成功,找到所查记录;反之,查找不成功。

Page 11: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

静态查找表的顺序存储结构

typedef struct {ElemType *elem;int length;}SSTable;

int Search_Seq(SSTable ST,KeyType key){ST.elme[0].key=key;for(i=ST.length; !EQ(ST.elem[i].key,key); --i);return i;}

查找算法

Page 12: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

查找操作的性能分析:

查找算法中的基本操作是将记录的关键字和给定值进行比较,通常以“其关键字和给定值进行过比较的记录个数的平均值”作为衡量依据。

平均查找长度 Average Search Length :为确定记录在查找表中的位置,需用和给定值进行比较的关键字个数的期望值称为查找算法在查找成功时的平均查找长度。

Page 13: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

           

其中: Pi 为查找表中第 i 个记录的概率,且 ;Ci 为找到表中其关键字与给定值相等的第 i个记录时,和给定值已进行过比较的关键字个数。

             

等概率条件下有:

                

假设查找成功与不成功的概率相同:                        

Page 14: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.1.2 静态查找表(二)有序表的查找

折半查找的查找过程以有序表表示静态查找表时, Search 函数可用折半查找来实现。先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。                                               

Page 15: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.1.2 静态查找表(二)有序表的查找

Page 16: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

折半查找的查找实现int Search_Bin(SSTable ST,KeyType key){low=1;high=ST.length;while(low<=high){mid=(low+high)/2;if EQ(key,ST.elem[mid].key) return mid;else if LT(key,ST.elem[mid].key) high=mid -1;else low=mid +1 ;}return 0;}//Search_Bin;

Page 17: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

折半查找的性能分析

1 折半查找在查找成功时和给定值进行比较的关键字个数至多为

2 折半查找在查找不成功时和给定值进行比较的关键字个数至多为

      

Page 18: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

3 查找成功时折半查找的平均查找长度为:

1)1(log50

1)1(log1

21

2

2

1

1

1

nASLn

nn

n

jn

CPASL

bs

h

j

j

n

iiibs

Page 19: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

比较顺序查找 折半查找

效率平均查找长度

( n+1 ) /2

存储结构 顺序表线性链表

有序表

1)1(log2 n

Page 20: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.1.3 索引顺序表查找 又称分块查找 是顺序查找的改进 除了查找表以外,还需一个索引表

结构

Page 21: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

索引表22 148 7 86 13

块中最大 key

块第一个元素在查找表中的

位置

2212138920334244382444382448605874498653

查找表( 只描述了关键字部分 )

( 块间有序,块内无序 )

( 有序 )

Page 22: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

索引顺序表查找 分块查找算法

首先,根据关键字值在索引表中查找 ( 顺序或折半查找 ) 以确定块的范围

然后,在块中根据关键字值做顺序查找 性能分析

若索引表查找采用顺序查找,则平均查找长度为 (n/s+s)/2 +1 ;若索引表查找采用折半查找,则平均查找长度为 log2(n/s+1)+s/2 ;其中 n 为查找表表长, s 为每一块中记录个数

查找效率高,但需建立索引表

Page 23: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.2 动态查找表

动态查找表的特点 表结构本身是在查找过程中动态生成的,即对

于给定值 key ,若表中存在其关键字等于 key的记录,则查找成功返回,否则插入关键字等于 key 的记录

动态查找表允许的操作 创建表、销毁表、关键字查找、记录插入、记

录删除、记录遍历等

Page 24: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

ADT DymanicSearchTable{数据对象D:D是具有相同特性的数据元素的集合。各个数据元素均含有类型相同,可唯一标识数据元素的关键字。数据关系R:数据元素同属一个集合。基本操作P:InitDSTable(&DT);DestroyDSTable(&DT);SearchDSTable(DT,key);InsertDSTable(&DT,e);DeleteDSTable(&DT,key);TraverseDSTable(DT,Visit());}ADT DynamicSearchTable

动态查找表

Page 25: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

动态查找表 二叉排序树 二叉排序树 (*)(*) 平衡二叉树

Page 26: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

9.2.1 二叉排序树及其查找过程

二叉排序树或者是一棵空树;或者是具有下列性质的二叉树:1、若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;2、若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;3、它的左、右子树了分别为二叉排序树。

Page 27: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

45

12 53

3 37 100

24 61

90

78

CAO

ZHAO

DING

CHEN WANG

MA

DU LI

XIA

二叉排序树示例

Page 28: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

二叉排序树 二叉排序树的存储结构

通常采用二叉链表结构

datalchild rchild

Page 29: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

二叉排序树 二叉排序树的查找算法一

( 不考虑查找失败后插入记录 )

BiTree SearchBST(BiTree T, KeyType key) {// 在根指针 T 所指二叉排序树中递归地查找某关键字等于 key 的数据元素,// 若查找成功则返回指向该数据元素的指针,否则返回空指针 if ((!T) || EQ(key, T->data.key))

return (T); else if (LT(key, T->data.key))

return (SearchBST(T->lchild, key)); else

return (SearchBST(T->rchild, key));}

Page 30: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

假设查找的关键序列为 {45,24,53,45,12,24,90} ,则生成二叉排序树的过程如下图所示:

45 45

24

45

24 53

45

24 53

12

45

24 53

12 90a b c d e

Page 31: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

二叉排序树 二叉排序树的特点

中序遍历二叉排序树可得到一个关键字的有序序列(即:可以通过输入一个无序序列,而通过构造二叉排序树后进行遍历的方法实现排序)

二叉排序树的插入过程不需要移动其他记录 具有相同 n 个结点的二叉排序树会因为构造的时

候关键字插入的顺序不同而不同 ( 下页说明 ) 二叉排序树的查找算法具有折半查找的特性,同

时又采用了链式存储结构,因此是动态查找表的适宜表示

Page 32: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

如:查找的关键序列分别为 {27,32,16,14} 、 {16,14,27,32} 和 {14,16,27, 32}, 生成二叉排序树分别如下:

27

16 32

14

16

14 27

32

14

16

27

32

Page 33: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

比较极端的例子还有

Page 34: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

二叉排序树的查找分析

最差情况 (n+1)/2 最好情况 log2n 平均性能

Page 35: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

在二叉排序树中删除一个节点

Page 36: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

思考:如何找到某子树上最大值结点,如何找到最小值结点?

Page 37: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

在二叉排序树中删除一个节点 x

如何找到 w ?

Page 38: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

平衡二叉树 AVLAVL 树 树 高度平衡的二叉搜索树高度平衡的二叉搜索树

一棵一棵 AVLAVL 树或者是空树,或者是具有下列性质的树或者是空树,或者是具有下列性质的二叉搜索树:二叉搜索树:它的左子树和右子树都是它的左子树和右子树都是 AVLAVL 树,且左子树,且左子树和右子树的高度之差的绝对值不超过树和右子树的高度之差的绝对值不超过 11 。。

高度不平衡的二叉搜索树 高度平衡的二叉搜索树高度不平衡的二叉搜索树 高度平衡的二叉搜索树

Page 39: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

结点的平衡因子结点的平衡因子 balancebalance (balance factor) (balance factor) 每个结点附加一个数字,给出该结点右子树的每个结点附加一个数字,给出该结点右子树的高度减去左子树的高度所得的高度差。这个数高度减去左子树的高度所得的高度差。这个数字即为结点的平衡因子字即为结点的平衡因子 balancebalance 。。

根据根据 AVLAVL 树的定义,任一结点的平衡因子只能树的定义,任一结点的平衡因子只能取 取 -1-1 ,, 00 和 和 11 。。

如果一个结点的平衡因子的绝对值大于如果一个结点的平衡因子的绝对值大于 11 ,则,则这棵二叉搜索树就失去了平衡,不再是这棵二叉搜索树就失去了平衡,不再是 AVLAVL 树。树。

如果一棵二叉搜索树是高度平衡的,它就成为 如果一棵二叉搜索树是高度平衡的,它就成为 AVLAVL 树。如果它有 树。如果它有 n n 个结点,其高度可保持个结点,其高度可保持在在 O(logO(log22nn)) ,平均搜索长度也可保持在,平均搜索长度也可保持在 O(logO(log22nn)) 。。

Page 40: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

AVLAVL 树的高度树的高度 设在新结点插入前设在新结点插入前 AVLAVL 树的高度为 树的高度为 hh ,结点个,结点个数为 数为 nn ,则插入一个新结点的时间是,则插入一个新结点的时间是 O(O(hh)) 。对。对于于 AVLAVL 树来说,树来说, h h 多大?多大?

设 设 NNh h 是高度为 是高度为 h h 的的 AVLAVL 树的最小结点数树的最小结点数。根。根的一棵子树的高度为 的一棵子树的高度为 hh--11 ,另一棵子树的高度,另一棵子树的高度为 为 hh--22 ,这两棵子树也是高度平衡的。因此有,这两棵子树也是高度平衡的。因此有 NN--1 1 = 0= 0 ( ( 空树空树 ))

NN00 = 1 = 1 (( 仅有根结点仅有根结点 ))

NNhh = = NNhh--11 + + NNhh--22 +1 +1 , , hh > 0 > 0

可以证明,对于 可以证明,对于 hh 0 0 ,有 ,有 NNhh = = FFhh+3 +3 -1-1 成立。成立。

Page 41: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

平衡化旋转平衡化旋转 如果在一棵平衡的二叉搜索树中插入一个新结点,造如果在一棵平衡的二叉搜索树中插入一个新结点,造

成了不平衡。此时必须调整树的结构,使之平衡化。成了不平衡。此时必须调整树的结构,使之平衡化。 平衡化旋转有两类:平衡化旋转有两类:

单旋转 单旋转 (( 左旋和右旋左旋和右旋 )) 双旋转 双旋转 (( 左平衡和右平衡左平衡和右平衡 ))

每插入一个新结点时,每插入一个新结点时, AVLAVL 树中相关结点的平衡状态树中相关结点的平衡状态会发生改变。因此,在插入一个新结点后,需要会发生改变。因此,在插入一个新结点后,需要从插从插入位置沿通向根的路径回溯入位置沿通向根的路径回溯,,检查各结点的平衡因子检查各结点的平衡因子(( 左、右子树的高度差左、右子树的高度差 )) 。。

如果在某一结点发现高度不平衡,停止回溯。如果在某一结点发现高度不平衡,停止回溯。

Page 42: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

从发生不平衡的结点起,沿刚才回溯的路径取从发生不平衡的结点起,沿刚才回溯的路径取直接下两层的结点。直接下两层的结点。

如果这三个结点处于一条直线上,则采用单旋如果这三个结点处于一条直线上,则采用单旋转进行平衡化转进行平衡化。单旋转可按其方向分为左单旋。单旋转可按其方向分为左单旋转和右单旋转,其中一个是另一个的镜像,其转和右单旋转,其中一个是另一个的镜像,其方向与不平衡的形状相关。方向与不平衡的形状相关。

如果这三个结点处于一条折线上,则采用双旋如果这三个结点处于一条折线上,则采用双旋转进行平衡化转进行平衡化。双旋转分为先左后右和先右后。双旋转分为先左后右和先右后左两类。左两类。

右单旋转右单旋转 左单旋转左单旋转 左右双旋转左右双旋转 右左双旋转右左双旋转

Page 43: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

左单旋转 左单旋转 (RotateLeft (RotateLeft ))

hh h

AC

EB

D

(a) (b) (c)

hh

h+1

BA

CED

h h

h+1

CEA

B D

如果在子树如果在子树 EE 中插入一个新结点,该子树高度增中插入一个新结点,该子树高度增11 导致结点导致结点 AA 的平衡因子变成的平衡因子变成 +2+2 ,出现不平衡。,出现不平衡。

沿插入路径检查三个结点沿插入路径检查三个结点 AA 、、 CC 和和 EE 。它们处于。它们处于一条方向为“一条方向为“ \”\” 的直线上,需要做左单旋转。的直线上,需要做左单旋转。

以结点以结点 CC 为旋转轴,让结点为旋转轴,让结点 AA 反时针旋转。反时针旋转。

+1+1 +2+2

00 +1+1 00

00

Page 44: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

右单旋转 右单旋转 (RotateRight )(RotateRight )

hh h

AC

EB

D

(a) (b) (c)

hh+1

BA

CED

h h

h+1

CEA

BD

在左子树在左子树 DD 上插入新结点使其高度增上插入新结点使其高度增 11 ,导致,导致结点结点 AA 的平衡因子增到 的平衡因子增到 --22 ,造成了不平衡。,造成了不平衡。

为使树恢复平衡,从为使树恢复平衡,从 AA 沿插入路径连续取沿插入路径连续取 33 个个结点结点 AA 、、 BB 和和 DD ,它们处于一条方向为“,它们处于一条方向为“ //””的直线上,需要做右单旋转。的直线上,需要做右单旋转。

以结点以结点 BB 为旋转轴,将结点为旋转轴,将结点 AA 顺时针旋转。顺时针旋转。

h

00

00

00

--11

--11

--22

Page 45: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

先左后右双旋转 先左后右双旋转 (RotationLeftRigh(RotationLeftRight)t)

在子树在子树 FF 或或 GG 中插入新结点,该子树的高度增中插入新结点,该子树的高度增11 。结点。结点 AA 的平衡因子变为 的平衡因子变为 --22 ,发生了不平衡。,发生了不平衡。

从结点从结点 AA 起沿插入路径选取起沿插入路径选取 33 个结点个结点 AA 、、 BB 和和EE ,它们位于一条形如“,它们位于一条形如“”的折线上,因此需”的折线上,因此需要进行先左后右的双旋转。要进行先左后右的双旋转。

首先以结点首先以结点 EE 为旋转轴,将结点为旋转轴,将结点 BB 反时针旋转,反时针旋转,以以 EE 代替原来代替原来 BB 的位置,做左单旋转。的位置,做左单旋转。

再以结点再以结点 EE 为旋转轴,将结点为旋转轴,将结点 AA 顺时针旋转,顺时针旋转,做右单旋转。使之平衡化。做右单旋转。使之平衡化。

Page 46: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

插入左单左单旋转旋转

右单右单旋转旋转

00

00--11 --22

+1+1

--11

00

00

+1+1

Page 47: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

先右后左双旋转 先右后左双旋转 (RotationRightLeft)(RotationRightLeft)

右左双旋转是左右双旋转的镜像。右左双旋转是左右双旋转的镜像。 在子树在子树 FF 或或 GG 中插入新结点,该子树高度增中插入新结点,该子树高度增 11 。。结点结点 AA 的平衡因子变为的平衡因子变为 22 ,发生了不平衡。 ,发生了不平衡。

从结点从结点 AA 起沿插入路径选取起沿插入路径选取 33 个结点个结点 AA 、、 CC和和 DD ,它们位于一条形如“,它们位于一条形如“”的折线上,需”的折线上,需要进行先右后左的双旋转。要进行先右后左的双旋转。

首先做右单旋转:以结点首先做右单旋转:以结点 DD 为旋转轴,将结点为旋转轴,将结点CC 顺时针旋转,以顺时针旋转,以 DD 代替原来代替原来 CC 的位置。的位置。

再做左单旋转:以结点再做左单旋转:以结点 DD 为旋转轴,将结点为旋转轴,将结点 AA反时针旋转,恢复树的平衡。反时针旋转,恢复树的平衡。

Page 48: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

左单左单旋转旋转

插入插入

右旋右旋

转转

+1+1

00

00

00

00--11

--11

+1+1

+2+2

Page 49: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

Fibonacci 树 p238

Page 50: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

Fibonacci 树

Page 51: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

思考题 二叉排序树的高度与输入数据序列的关系

Page 52: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

作业 1 建立以下单词的二叉排序树(画图)

ZHAO QIAN SUN LI

ZHOU WU ZHENG WANG

FENG CHEN

Page 53: 静态查找表 动态查找表 二叉搜索树 AVL 树 哈希表  (Hash)

作业 2 高度为 4 的平衡二叉树最多有多少个结点,

最少有多少个结点?