1、第9章 查找,第 2 页,第9章 查 找,查找表:由同一类型的数据元素(或记录)构成的集合。 查找表的基本操作 1) 查询某个“特定的”数据元素是否在表中2) 检索某个“特定的”数据元素的各种属性3) 插入一个数据元素4) 删去某个数据元素 静态查找表:只作查询和检索操作的查找表。 动态查找表:在查找过程中同时作插入或删除操作的查找表。,第 3 页,第9章 查 找,关键字:能标识一个数据元素(或记录)的数据项。 主关键字:能唯一地标识一个记录的关键字。 次关键字:用以识别若干记录的关键字。,学号 姓名 专业 年龄 20090001 王洪 自动化 1720090002 李文 自动化 182009
2、0003 谢军 自动化 1820090004 张辉 信息工程 2020090005 李文 信息工程 19,第 4 页,第9章 查 找,查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录或数据元素,若表中存在这样的记录,则称查找成功,查找结果为该记录在查找表中的位置;否则称为查找不成功,查找结果为0或NULL。,学号 姓名 专业 年龄 20090001 王洪 自动化 1720090002 李文 自动化 1820090003 谢军 自动化 1820090004 张辉 信息工程 2020090005 李文 信息工程 19,第 5 页,第9章 查 找,查找方法评价 查找算法的基本操作:
3、比较 平均查找长度ASL ( Average Search Length):为确定记录在表中的位置,需和给定值进行比较的关键字个数的期望值。 平均查找长度: ASL = PiCi Pi:查找第 i 个记录的概率,且Pi=1 ;Ci:查找第 i 个记录所需的比较次数。,第 6 页,第9章 查 找,关键字类型定义typedef float KeyType; 实型typedef int KeyType; 整型typedef char* KeyType; 字符串型 数据元素类型定义typedef struct KeyType key; 关键字域 其他域 ElemType;,第 7 页,第9章 查 找,
4、对数值型关键字#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),第 8 页,第9章 查 找,静态查找在指定的表中查找某一个“特定”的数据元素是否存在,检索某一个“特定”数据元素的各种属性。 动态查找在查找的过程中同时插入表中不存在的数据元素,或者从查找表中删除已存在的某个数据元素。
5、,第 9 页,第9章 查 找,9.1 静态查找表9.2 动态查找表9.3 哈希表,第 10 页,静态查找表无序表的查找:顺序查找有序表的查找:折半查找索引顺序表的查找:分块查找,9.1 静态查找表,第 11 页,查找表用线性表表示 L1=(45,61,12,3,37,24,90,53,98,78)用顺序表表示静态查找表用线性链表表示静态查找表查找方法:顺序查找,9.1 静态查找表,第 12 页,顺序表类型定义typedef struct ElemType *elem; / 0号单元留空int length; SSTable;,9.1 静态查找表-顺序表查找,与线性表顺序 存储结构比较一下,SS
6、Table ST;,第 13 页,int Search_Seq ( SSTable ST, KeyType key ) ST.elem0.key = key; / “哨兵”for ( i=ST.length; !EQ(key, ST.elemi.Key; -i );return i; / 若表中不存在待查元素, i=0 ,9.1 静态查找表,key,免去查找过程中每一步都要检测整个表是否查找完毕,第 14 页,例1:在下表中查找 key = 8 的结点。,9.1 静态查找表,8,查找不成功,i = 0,8,查找成功,i = n-2,第 15 页,顺序查找的特点:无排序要求;存储结构:顺序、链式
7、;平均查找长度ASLSS=(n+1)/2;,9.1 静态查找表,第 16 页,查找表:用有序表表示 查找方法:折半查找(二分查找) 查找过程:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。例:有原始查找表 45, 61, 12, 3, 37, 24, 90, 53, 98, 78为进行折半查找,需要先进行排序:L=(3, 12, 24, 37, 45, 53, 61, 78, 90, 98),9.1 静态查找表-有序表查找,第 17 页,例:查找 Key=24 的记录。,9.1 静态查找表-有序表查找,1 2 3 4 5 6 7 8 9 103 12 24 37
8、 45 53 61 78 90 98,1 2 3 4 5 6 7 8 9 103 12 24 37 45 53 61 78 90 98,2445,2412,1 2 3 4 5 6 7 8 9 103 12 24 37 45 53 61 78 90 98,第 18 页,int Search_Bin ( SSTable ST, KeyType key ) low=1; high=ST.length;return 0; /表中不存在待查元素 /Search_Bin,9.1 静态查找表-有序表查找,while ( low=high ) mid=(low+high)/2;if EQ ( key, ST.
9、elemmid.key ) return mid; elseif LT ( key, ST.elemmid.key ) high=mid-1; else low=mid+1; ,第 19 页,该查找过程可用一个二叉树来描述,9.1 静态查找表-有序表查找,1 2 3 4 5 6 7 8 9 10 3,12,24,37,45,53,61,78,90,98,5,2,1,3,6,9,4,7,10,8,描述查找过程的树中每个结点表示表中一个记录,结点中的值为该记录在表中的位置,称为判定树。,第 20 页,例1:在下表中查找 key = 9 的结点。,9.1 静态查找表-有序表查找,9,第 21 页,例
10、2:在下表中查找 key = 5 的结点。,9.1 静态查找表-有序表查找,low high,查找不成功!,5,第 22 页,折半查找的特点:要求元素按关键字有序。存储结构:顺序。平均查找长度 ASLbs= log2(n+1)-1,9.1 静态查找表-有序表查找,第 23 页,查找表的组织:分块索引,除表本身以外,尚需建立一个“索引表”。 查找方法:查找索引表;在数据块内顺序查找,9.1 静态查找表-索引顺序表的查找,第 24 页,查找方法比较,9.1 静态查找表,ASL,最大,最小,两者之间,表结构,有序表、无序表,有序表,分块有序表,存储结构,顺序存储结构 线性链表,顺序存储结构,顺序存储
11、结构 线性链表,顺序查找,折半查找,分块查找,第 25 页,二叉排序树:或者是一棵空树;或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于根结点的值;(2)若右子树不空,则右子树上所有结点的值均大于根结点的值;(3)根结点的左、右子树也分别为二叉排序树。,9.2 动态查找表,第 26 页,例:在二叉排序树中查找关键字为24的记录。,9.2 动态查找表,第 27 页,例:在二叉排序树中查找关键字为60的记录。,9.2 动态查找表,第 28 页,二叉排序树的存储 typedef struct BiTNode TElemType data;struct BiTNode *
12、lchild, * rchild; BiTNode,*BTree; typedef struct KeyType key; TElemType;,9.2 动态查找表,第 29 页,例:二叉排序树中插入结点 40。,9.2 动态查找表,第 30 页,二叉排序树的特点:是一种动态树表,树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入。,9.2 动态查找表,新插入结点的特点:一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。,插入新结点的时机:当查找不成功时。,第 31 页,插入算法:(1)执行查找算法,找出被
13、插入结点的双亲结点;(2)判断被插入结点是其双亲结点的左孩子结点还是右孩子结点,将被插入结点作为叶子结点插入;(3)若二叉树为空,则首先单独生成根结点。,9.2 动态查找表,第 32 页,例1:插入值为280的结点。,9.2 动态查找表,第 33 页,例2:在一棵空树中,查找如下的关键字序列,9.2 动态查找表,45, 45,24,53,45,12,24,90 ,依次生成的二叉排序树如下:,对二叉排序树进行中序遍历可以得到有序序列,第 34 页,思考题1:二叉排序树删除50,60。,第9章 查找,第 35 页,思考题2:二叉排序树删除10,5。,第9章 查找,第 36 页,二叉树排序删除操作删
14、除原则:保持二叉排序树的特性。设:二叉排序树上指向被删结点的指针为p,指向其双亲结点的指针为 f,且 p 为 f 的左孩子结点。,9.2 动态查找表,第 37 页,二叉排序树的删除操作 要删除二叉排序树中的p结点,分三种情况:p为叶子结点,只需修改 p 双亲 f 的指针:f-lchild=NULL f-rchild=NULLp只有左子树或右子树p左、右子树均非空,9.2 动态查找表,第 38 页,二叉排序树的删除操作(一) p为叶子结点:,9.2 动态查找表,只需修改 p 双亲 f 的指针: f-lchild=NULL f-rchild=NULL,第 39 页,二叉排序树的删除操作(二)p只有
15、左子树:用p的左孩子代替p (1)(2),9.2 动态查找表,第 40 页,二叉排序树的删除操作(二)p只有右子树:用p的右孩子代替p (3)(4),9.2 动态查找表,第 41 页,二叉排序树的删除操作(三):p左、右子树均非空 沿 p 左子树的根 C 的右子树分支找到 S,S的右子树为空,将 S 的左子树成为 S 的双亲Q 的右子树,用 S 取代 p (5),9.2 动态查找表,中序遍历:CL C QL Q SL S P PR F,中序遍历:CL C QL Q SL S PR F,(5),第 42 页,二叉排序树的删除操作(三):p左、右子树均非空若p 左子树的根 C 无右子树,用 C 取
16、代 p (6),9.2 动态查找表,中序遍历:CL C P PR F,中序遍历:CL C PR F,(6),第 43 页,二叉排序树的删除操作,分三种情况:p为叶子结点,只需修改 p 双亲 f 的指针: f-lchild=NULL f-rchild=NULLp只有左子树或右子树p只有左子树,用p的左孩子代替p (1)(2)p只有右子树,用p的右孩子代替p (3)(4)p左、右子树均非空沿 p 左子树的根 C 的右子树分支找到 S,S的右子树为空,将 S 的左子树成为 S 的双亲Q 的右子树,用 S 取代 p (5)若 C 无右子树,用 C 取代 p (6),9.2 动态查找表,第 44 页,二
17、叉排序树的删除操作,9.2 动态查找表,第 45 页,性能分析 查找表:3,12,24,37,45,53,61,78,90,98,9.2 动态查找表,ASL=(1+2+3+4+5+6+7+8+9+10)/10=5.5,ASL=(1+22+34+43)/10=2.9,第 46 页,二叉排序树的特点之一(缺陷):没有对树的深度进行控制。 在构造二叉排序树的过程中进行“平衡化”处理,成为平衡二叉树(AVL树)。 平衡二叉树:左子树和右子树的深度之差的绝对值不超过计划。,9.2 动态查找表,第 47 页,二叉排序树的特点含有n个结点的二叉排序树不唯一,与结点插入的顺序有直接关系。当查找失败后,在叶结点
18、插入。删除某个结点后,二叉排序树要重组。没有对树的深度进行控制。 二叉排序树的适用范围用于组织规模较小的、内存中可以容纳的数据。对于数据量较大必须存放在外存中的数据,则无法快速处理。,9.2 动态查找表,第 48 页,散列法(哈希法)在记录的存储地址和它的关键字之间建立一个确定的对应关系,一次存取就能得到所查元素的查找方法。即:通过简单计算直接得到数据的地址。1) 哈希(Hash)函数是一个映象,即:将关键字的集合映射到某个地址集合上,映象原则:地址集合的大小不超出允许范围。哈希函数:addr(ai)=H(ki) ai是表中的一个元素 addr(ai)是ai的存储地址 ki是ai的关键字。,9
19、.3 哈希表,第 49 页,散列法(哈希法)2) 由于哈希函数是一个压缩映象,因此,在一般情况下,很容易产生“冲突”现象,即:key1 key2,而 f(key1) = f(key2)。3) 很难找到一个不产生冲突的哈希函数。一般情况下,只能选择恰当的哈希函数,使冲突尽可能少地产生。,9.3 哈希表,第 50 页,散列法(哈希法),9.3 哈希表,以编号作关键字, 构造哈希函数:H(key)=key H(1)=1 H(2)=2,以地区作关键字,取地区 名称第一个拼音字母的序号 作哈希函数:H(Beijing)=2H(Shanghai)=19H(Shenyang)=19,第 51 页,散列法(哈
20、希法)哈希表应用哈希函数,由记录的关键字确定记录在表中的地址,并将记录放入此地址,这样构成的表叫哈希表。哈希查找又叫散列查找,利用哈希函数进行查找的过程。,9.3 哈希表,第 52 页,构造哈希函数,9.3 哈希表,1、直接定址法:取关键字或关键字的某个线性函数值为哈希地址。 2、数字分析法:取关键字的若干数位组成哈希地址。 3、平方取中法:取关键字平方后的中间几位为哈希地址。 4、折叠法:将关键字分割成位数相同的几部分,然后取这几部分的叠加和作为哈希地址。,第 53 页,构造哈希函数,9.3 哈希表,5、除留余数法:取关键字被某个不大于哈希表长m的数p除后所得余数为哈希地址。 H(key)=
21、 key%p,p=m 6、随机数法:选择一个随机函数,取关键字的随机函数值为它的哈希地址。 H(key) = random(key),第 54 页,散列法(哈希法)在构造这种特殊的“查找表” 时,除了需要选择一个“好”(尽可能少产生冲突)的哈希函数之外,还需要找到一种“处理冲突” 的方法。“处理冲突” 的实际含义是:为产生冲突的地址寻找下一个哈希地址。常用的解决冲突的方法:开放地址法,链地址法,再哈希法,建立一个公共溢出区。,9.3 哈希表,第 55 页,解决冲突的方法开放地址法,9.3 哈希表,Hi(key)=(H(key)+di) MOD m (i=1,2,3 ) 为发生冲突的记录再求一存储位置。H(key)为哈希函数;m为哈希表表长;di为增量序列,有三种取法:* di=1,2,3; 称为线性探测再散列* di=12,-12,22,-22,32,-32,+k2,( k = m/2 ) 称为二次探测再散列* di=伪随机数序列,称为伪随机数探测再散列,第 56 页,解决冲突的方法链地址法,9.3 哈希表,19,13,33,02,16,29,24,5H(key)=key mod 11,第 57 页,哈希表的查找的性能分析与哈希函数、处理冲突方法和装载因子有关。假设哈希函数是“均匀的”,处理冲突方法相同,则哈希表平均查找长度依赖于装载因子 。,9.3 哈希表,