第10章 查找

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(1)若查找给定值为20的元素,将依次与表中哪 些元素比较?
(2)若查找给定值为26的元素,将依次与哪些元 素比较?
(3)假设查找表中每个元素的概率相同,求查找 成功时的平均查找长度和查找不成功时的平均查 找长度。
二分查 找判定 树
25
1030215 Nhomakorabea28
35
3
20
29
40
(1) 若 查 找 给 定 值为20的元素,依次 与 表 中 25,10,15,20 元素比较,共比较4 次。
索引表的数据类型定义如下:
#define MAXI <索引表的最大长度>
typedef struct
{ KeyType key; /*KeyType为关键字的类型*/
int link;
/*指向对应块的起始下标*/
} IdxType;
typedef IdxType IDX[MAXI]; /*索引表类型*/
while (i<n && R[i].key!=k) i++; /*从表头往后找*/ if (i>=n)
return -1; else
return i; }
从顺序查找过程可以看到(不考虑越界比较 i<n),ci取决于所查记录在表中的位置。如查找表中第 1个记录R[0]时,仅需比较一次;而查找表中最后一 个记录R[n-1]时,需比较n次,即ci=i。因此,成功时的顺 序查找的平均查找长度为:
(2)若查找给定值为26的元素,依次与25,30,28元素比较,共比 较3次。
(3)在查找成功时,会找到图中某个圆形结点,则成功时的平
均查找长度:
AS = 1 L 1 2 s 2 u 4 c 3 c 4 4 = 3 11
在查找不成功时,会找到图中某个方形结点,则不成功时
的平均查找长度:
它的基本思路是:从表的一端开始,顺序扫描线性表, 依次将扫描到的关键字和给定值k相比较,若当前扫描 到的关键字与k相等,则查找成功;若扫描结束后,仍未 找到关键字等于k的记录,则查找失败。
例如,在关键字序列为{3,9,1,5,8,10,6,7,2,4}的线性 表查找关键字为6的元素。
顺序查找过程如下:
if (R[mid].key>k) /*继续在R[low..mid-1]中查找*/ high=mid-1;
else low=mid+1; /*继续在R[mid+1..high]中查找*/
} return -1; }
二分查找过程可用二叉树来描述,我们把当前 查找区间的中间位置上的记录作为根,左子表和右 子表中的记录分别作为根的左子树和右子树,由此 得到的二叉树,称为描述二分查找的判定树或比较 树。
<
5
=
2 < =>
> 8
<= >
0 < =>
-∞~-1 1 < =>
3 <= >
2~3
4
<=>
6 <=>
9 <=>
5~6
7
8~9
10
<=>
< =>
0~1 1~2
3~4 4~5
6~7 7~8
9~10 10~∞
R[0..10]的二分查线的判定树(n=11)
例 10.1 对 于 给 定 11 个 数 据 元 素 的 有 序 表 {2,3,10,15,20,25,28,29,30,35,40},采用二分查找 ,试 问:
在讨论二叉排序树上的运算之前,定义其结点的类 型如下:
typedef struct node
/*记录类型*/
{ KeyType key;
/*关键字项*/
InfoType data;
/*其他数据域*/
struct node *lchild,*rchild;
/*左右孩子指针*/
} BSTNode;
开始: 3 9 1 5 8 10 6 7 2 4
第1次比较: 3 9 1 5 8 10 6 7 2 4 i=0
第2次比较: 3 9 1 5 8 10 6 7 2 4 i=1
第3次比较: 3 9 1 5 8 10 6 7 2 4 i=2
第4次比较: 3 9 1 5 8 10 6 7 2 4 i=3
第5次比较: 3 9 1 5 8 10 6 7 2 4 i=4
若以顺序查找确定块,则分块查找成功时的平 均查找长度为:
A L b l S A kb n A S s L q b S 2 1 L s 2 1 s 2 2 2 s s n
10.3 树表的查找
当表的插入或删除操作频繁时,为维护表的有序 性,需要移动表中很多记录。这种由移动记录引起 的额外时间开销,就会抵消二分查找的优点。也就 是说,二分查找只适用于静态查找表。若要对动态 查找表进行高效率的查找,可采用下面介绍的几种 特殊的二叉树或树作为表的组织形式,在这里将它 们统称为树表。下面将分别讨论在这些树表上进 行查找和修改操作的方法。
ASL= u4 n 3 s8 u4= c3.6 c 7 12
10.2.3 分块查找
分块查找又称索引顺序查找,它是一种性能介于 顺序查找和二分查找之间的查找方法。
它要求按如下的索引方式来存储线性表:将表 R[0..n-1]均分为b块,前b-1块中记录个数为s=n/b,最 后一块即第b块的记录数小于等于s;每一块中的关键 字不一定有序,但前一块中的最大关键字必须小于后 一块中的最小关键字,即要求表是“分块有序”的; 抽取各块中的最大关键字及其起始位置构成一个索引 表 IDX[0..b-1], 即 IDX[i](0≤i≤b-1) 中 存 放 着 第 i 块 的 最 大关键字及该块在表R中的起始位置。由于表R是分 块有序的,所以索引表是一个递增有序表。
第10章 查找
10.1 查找的基本概念 10.2 线性表的查找 10.3 树表的查找 10.4 哈希表查找
本章小结
10.1 查找的基本概念
被查找的对象是由一组记录组成的表或文件,而每个 记录则由若干个数据项组成,并假设每个记录都有一个 能惟一标识该记录的关键字。
在这种条件下,查找的定义是:给定一个值k,在含有 n个记录的表中找出关键字等于k的记录。若找到,则 查找成功,返回该记录的信息或该记录在表中的位置; 否则查找失败,返回相关的指示信息。
#define MAXL <表中最多记录个数>
typedef struct { KeyType key;
InfoType data;
/*KeyType为关键字的数据类型*/ /*其他数据*/
} NodeType; typedef NodeType SeqList[MAXL]; /*顺序表类型*/
10.2.1 顺序查找 顺序查找是一种最简单的查找方法。
时返回记录的位置,失败时返回-1):
int BinSearch(SeqList R,int n,KeyType k) { int low=0,high=n-1,mid;
while (low<=high) { mid=(low+high)/2;
if (R[mid].key==k) /*查找成功返回*/ return mid;
第6次比较: 3 9 1 5 8 10 6 7 2 4 i=5
第7次比较: 3 9 1 5 8 10 6 7 2 4 i=6
查找成功,返回序号6
顺序查找的算法如下(在顺序表R[0..n-1]中查找关键 字为k的记录,成功时返回找到的记录位置,失败时返回1):
int SeqSearch(SeqList R,int n,KeyType k) { int i=0;
常把查找过程中对关键字需要执行的平均比较次数(也
称为平均查找长度)作为衡量一个查找算法效率优劣的
标准。平均查找长度ASL(Average Search Length)定义
为:
n
ASLpici i1
其中,n是查找表中记录的个数。pi是查找第i个记 录的概率,一般地,均认为每个记录的查找概率相等,即
pi=1/n(1≤i≤n),ci是找到第i个记录所需进行的比较次数。
10.2 线性表的查找
在表的组织方式中,线性表是最简单的一种。三种 在线性表上进行查找的方法:
(1) 顺序查找 (2) 二分查找 (3) 分块查找。 因为不考虑在查找的同时对表做修改,故上述三种 查找操作都是在静态查找表上实现的。
查找与数据的存储结构有关,线性表有顺序和链式 两种存储结构。本节只介绍以顺序表作为存储结构时 实现的顺序查找算法。定义被查找的顺序表类型定义 如下:
if (I[mid].key>=k) high=mid-1;
else low=mid+1;
}
if (low<m) /*在块中顺序查找*/ { i=I[low].link;
while (i<=I[low].link+b-1 && R[i].key!=k) i++; if (i<=I[low].link+b-1)
例如,设有一个线性表,其中包含25个记录,其关键字序列 为{8,14,6,9,10,22,34,18,19,31,40,38,54,66, 46,71,78,68,80,85, 100, 94,88,96,87}。假设将25个记录分为5块,每块中有5个记 录,该线性表的索引存储结构如下图所示。
14 34 66 85 100 key 0 5 10 15 20 link
采用何种查找方法?
(1) 使用哪种数据结构来表示“表”,即表中记 录是按何种方式组织的。
(2) 表中关键字的次序。是对无序集合查找还 是对有序集合查找?
若在查找的同时对表做修改运算(如插入和删 除),则相应的表称之为动态查找表,否则称之为静 态查找表。
由于查找运算的主要运算是关键字的比较,所以通
10.3.1 二叉排序树
二叉排序树(简称BST)又称二叉查找(搜索)树, 其定义为:二叉排序树或者是空树,或者是满足如 下性质的二叉树:
(1) 若它的左子树非空,则左子树上所有记录的值 均小于根记录的值;
(2) 若它的右子树非空,则右子树上所有记录的值 均大于根记录的值;
(3) 左、右子树本身又各是一棵二叉排序树。
return i; else
return -1; } return -1; }
若以二分查找来确定块,则分块查找成功时的平 均查找长度为:
s 1
s
A b A lS k b A n L S s q l2 S L ( o h 1 ) 1 L g 2 l2 ( o n / s 1 ) g 2
int IdxSearch(IDX I,int m,SeqList R,int n,KeyType k)
{ int low=0,high=m-1,mid,i;
int b=n/m;
/*b为每块的记录个数*/
while (low<=high) /*在索引中二分查找*/
{ mid=(low+high)/2;
n 1 n 1n ( n 1 )n 1 A s S q i 1 p i c L i n i 1 i n 2 2
查找成功时的平均比较次数约为表长的一半 。
10.2.2 二分查找
二分查找也称为折半查找要求线性表中的结点必须 己按关键字值的递增或递减顺序排列。它首先用要查 找的关键字k与中间位置的结点的关键字相比较,这个 中间结点把线性表分成了两个子表,若比较结果相等则 查找完成;若不相等,再根据k与该中间结点关键字的比 较大小确定下一步查找哪个子表,这样递归进行下去, 直到找到满足条件的结点或者该线性表中没有这样的 结点。
例如,在关键字有序序列{2,4,7,9,10,14,18,26,32,40}中 采用二分查找法查找关键字为7的元素。
二分查找过程如下:
开始: 2 4 7 9 10 14 18 26 32 40
low=0
high=9 mid=(0+9)/2=4
第1次比较: 2 4 7 9 10 14 18 26 32 40
8 14 6 9 10 22 34 18 19 31 40 38 54 66 46 71 78 68 80 85 100 94 88 96 87 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
采用二分查找索引表的分块查找算法如下(索引 表I的长度为m):
low=0 high=3
mid=(0+3)/2=1
第2次比较: 2 4 7 9 10 14 18 26 32 40
low=2 high=3
mid=(2+3)/2=2
第3次比较: 2 4 7 9 10 14 18 26 32 40
R[2].key=7
查找成功,返回序号2
其算法如下(在有序表R[0..n-1]中进行二分查找,成功
相关文档
最新文档