240 likes | 362 Views
第七章 查找. 基本概念 线性表的查找 树表的查找. 7.1 基本概念. 简单地说,查找就是给定一个值 K ,在含有 n 个结点的表中找出关键字等于给定值 K 的结点。 查找也是计算机中经常遇到的操作。特别是当问题所涉及到的数据量相当大时,查找的效率就显得格外重要。 在研究各种查找算法时,优先必须弄清这些方法所需要的数据结构,特别是存储结构。 和排序类似,查找也有内查找与外查找之分。 查找运算的主要操作是关键字的比较,所以,通常把查找过程中对关键字需要执行的平均比较次数(也称为平均查找长度)作为衡量一个查找算法效率优劣的标准。. 平均查找长度定义为:.
E N D
第七章 查找 • 基本概念 • 线性表的查找 • 树表的查找
7.1 基本概念 • 简单地说,查找就是给定一个值K,在含有n个结点的表中找出关键字等于给定值K的结点。 • 查找也是计算机中经常遇到的操作。特别是当问题所涉及到的数据量相当大时,查找的效率就显得格外重要。 • 在研究各种查找算法时,优先必须弄清这些方法所需要的数据结构,特别是存储结构。 • 和排序类似,查找也有内查找与外查找之分。 • 查找运算的主要操作是关键字的比较,所以,通常把查找过程中对关键字需要执行的平均比较次数(也称为平均查找长度)作为衡量一个查找算法效率优劣的标准。
平均查找长度定义为: 其中,n是结点的个数;pi是查找第i个结点的概率,p1=p2=...=pn=1/n;ci 是找到第i个结点所需要的比较次数
7.2 线性表的查找 7.2.1 线性表的顺序查找 • 顺序查找 • 二分查找 • 分块查找 typedef struct { keytype key; datatype other; } table; table R[n+1]; 线性表的向量存储结构
顺序查找算法: int SEQSEARCH(table R[],keytype K) { int i; R[n].key=K; //设置监视哨 i=0; //从表头开始向后扫描 while (R[i].key!=K) i++; if (i==n) return(-1); //未找到,返回-1 else return i; //找到,返回下标 }
算法中监视哨R[n]的作用仍然是为了在while 循环中省去判定防止下标越界的条件 i<n, 从而节省比较的时间。 • 顺序查找的平均查找长度为: • 有时,表中各结点的查找概率并不相等。因 此若事先知道表中各结点查找概率的分布情 况,则可将表中结点按查找概率从大到小排 列,以便提高顺序查找的效率。 • 顺序查找的特点:算法简单,但查找效率低。
7.2.2 线性表的二分查找 • 二分查找又称为折半查找。 • 二分查找要求线性表是有序的。且表为向量。 • 二分查找的基本思想是:首先将待查的K值与有 序表R[0]到R[n-1]的中间位置mid上的结点的关键 字进行比较,若相等,则查找完成;否则,若 R[mid].key>K,则说明待查找的结点只可能在左 子表R[0]到R[mid-1]中,只需在左子表中继续查 找;否则在右子表中继续查找。这样,经过一次 关键字的比较就缩小了一半的查找区间。如此进 行下去,直到找到为止(也存在最后查找区间为空即找不到的可能)。
二分查找算法(low和high分别表示当前查找区间的下界和上界)二分查找算法(low和high分别表示当前查找区间的下界和上界) int BINSEARCH(table R[],keytype K) { int low,mid,high; low=0; high=n-1; while (low<=high) { mid=(low+high)/2; //整除 if (K==R[mid].key) return mid; if (K<R[mid].key) high=mid-1; else low=mid+1; } return -1; //查找失败 }
[05 13 19 21 37 56 64 75 80 88 92] [05 13 19 21 37] 56 64 75 80 88 92 05 13 19 [21 37] 56 64 75 80 88 92 查找K=21的过程(查找成功)
[05 13 19 21 37 56 64 75 80 88 92] 05 13 19 21 37 56 [64 75 80 88 92] 05 13 19 21 37 56 64 75 80 [88 92] 05 13 19 21 37 56 64 75 80] [88 92 查找K=85的过程(查找失败)
算法分析 如果把当前查找位置上的结点作为根,左子表和右子表的结点分别作为根的左子树和右子树,由此得到的二叉树称为描述二分查找的判定树。 借助于判定树很容易求得二分查找的平均查找长度。设结点总数为: 树中第k层上的结点个数不超过
因此,在等概率假设下,二分查找的平均查找长度为:因此,在等概率假设下,二分查找的平均查找长度为:
可见,二分查找的算法复杂度为: 即在最坏情况下,二分查找方法查找成功的比较次数不超过判定树的深度。 虽然二分查找的效率较高,但它要求被查找序列事先按关键字排好序,而排序本身是一种很费时的运算;另外,二分查找只适用于顺序存储结构,因此,二分查找特别适用于那种一经建立就很少改动、而又需要经常查找的线性表。
7.3 树表的查找 • 二叉排序树 • B-树
输入:45,24,55,12,37,53,60,28,40,70 45 24 55 12 37 53 60 28 70 40 (a)
输入:12,24,28,37,40,45,53,55, 60, 70 12 24 28 37 40 45 53 55 60 (b) 70
45 24 55 12 37 53 60 28 70 40
=(1+2+3+4+5+6+7+ 8+9+10)/10=5.5 12 24 28 37 40 45 53 55 60 70
二叉排序树ASL: 最坏ASL=(n+1)/2 最好ASL=log2n 平均ASL=log2n 就平均性能而言,二叉排序树上的查找和二分查找相差不大,并且二叉排序树上的结点插入和删除十分方便,无须移动大量结点。因此,对于需要经常做插入、删除和查找操作的表,宜采用二叉排序树结构
B-树查找效率: L=1+log m/2 ((n+1)/2) 若n=1,999,999,m=199,则L=4
习题: 1. 请指出在顺序表{2、5、7、10、14、15、18、23、35、41、52}中,用二分法查找关键码12需做多少次关键码比较。( ) A.2 B.3 C.4 D.5 答案是C。第一次和15比较;第二次和7比较;第三次和10比较;第四次和14比较;比较后结束,没找到。
2.对一棵查找树根结点而言,左子树中所有结点与右子树中所有结点的关键字大小关系是()2.对一棵查找树根结点而言,左子树中所有结点与右子树中所有结点的关键字大小关系是() A、小于B、大于C、等于、D、不小于 答案是A
3.在一棵空的二叉查找树中依次插入关键字序列为20、30、8、12、34、5、60、5、1,29,请画出所得到的二叉查找树。3.在一棵空的二叉查找树中依次插入关键字序列为20、30、8、12、34、5、60、5、1,29,请画出所得到的二叉查找树。
4.为什么有序的单链表不能进行折半查找? 答:因为链表无法进行随机访问,如果要访问链表的中间结点,就必须先从头结点开始进行依次访问,这就要浪费很多时间,还不如进行顺序查找,而且,用链存储结构将无法判定二分的过程是否结束,因此无法用链表实现二分查找。 5.将二叉排序树T的先序序列中的关键字依次插入一空树中,所得二叉排序树T'与T是否相同?为什么? 答:这两棵二叉树完全相同。