数据结构C语言版第八章 查找.docx
《数据结构C语言版第八章 查找.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版第八章 查找.docx(16页珍藏版)》请在冰豆网上搜索。
数据结构C语言版第八章查找
第八章查找
重点难点
要求理解"查找表"的结构特点以及各种表示方法的适用性;熟练掌握顺序查找和折半查找的方法;熟悉描述折半查找过程的判定树的构造方法;熟练掌握二叉排序树的构造和查找方法;理解二叉平衡树的构造过程;理解B-和B+树的特点、基本操作和二者的区别。
熟练掌握哈希表的构造方法,深刻理解哈希表与其它结构的表的实质性的差别;掌握各种不同查找方法之间的区别和各自的适用情况,能按定义计算各种查找方法在等概率情况下查找成功时的平均查找长度。
典型例题
1.若对具有n个元素的有序的顺序表和无序的顺序表分别进行顺序查找,试在下述两种情况下分别讨论两者在等概率时的平均查找长度:
(1)查找不成功,即表中无关键字等于给定值K的记录;
(2)查找成功,即表中有关键字等于给定值K的记录。
【解】 查找不成功时,需进行n+1次比较才能确定查找失败。
因此平均查找长度为n+1,这时有序表和无序表是一样的。
查找成功时,平均查找长度为(n+1)/2,有序表和无序表也是一样的。
因为顺序查找与表的初始序列状态无关。
2.画出对长度为18的有序的顺序表进行二分查找的判定树,并指出在等概率时查找成功的平均查找长度,以及查找失败时所需的最多的关键字比较次数。
【解】
等概率情况下,查找成功的平均查找长度为:
ASL=(1+2*2+3*4+4*8+5*3)/18=3.556
查找失败时,最多的关键字比较次树不超过判定树的深度,此处为5.
3.为什么有序的单链表不能进行折半查找?
【解】 因为链表无法进行随机访问,如果要访问链表的中间结点,就必须先从头结点开始进行依次访问,这就要浪费很多时间,还不如进行顺序查找,而且,用链存储结构将无法判定二分的过程是否结束,因此无法用链表实现二分查找。
4.设二叉排序树中关键字互不相同,则其中最小元必无左孩子,最大元必无右孩子。
此命题是否正确?
最小元和最大元一定是叶子吗?
一个新结点总是插在二叉排序树的某叶子上吗?
【解】此命题正确。
假设最小元有左孩子,则根据二叉排序树性质,此左孩子应比最小元更小,如此一来就产生矛盾了,因此最小元不可能有左孩子,对于最大元也是这个道理。
但最大元和最小元不一定是叶子,它也可以是根、内部结点(分支结点)等,这得根据插入结点时的次序而定。
新结点总是作为叶子插入在二叉排序树中的。
5.在一棵m阶的B-树中,当将一关键字插入某结点而引起该结点的分裂时,此结点原有多少个关键字?
若删去某结点中的一个关键字,而导致结点合并时,该结点中原有几个关键字?
【解】在一棵m阶的B-树中,若由于一关键字的插入某结点而引起该结点的分裂时,则该结点原有m-1个关键字。
若删去某结点中一个关键字而导致结点合并时,该结点中原有┌m/2┐-1个关键字。
6.设散列表长度为11,散列函数h(x)=x%11,给定的关键字序列为:
1,13,13,34,38,33,27,22.试画出分别用拉链法和线性探查法解决冲突时所构造的散列表,并求出在等概率情况下,这两种方法查找成功和失败时的平均查找长度。
请问装填因子的值是什么?
答:
(1)拉链法如下图:
T[0..10]
┌──┐
0│ │→33→22→∧
├──┤
1│ │→1→12→34→∧
├──┤
2│ │→13→∧
├──┤
3│∧│
├──┤
4│∧│
├──┤
5│ │→38→27→∧
├──┤
6│∧│
├──┤
7│∧│
├──┤
8│∧│
├──┤
9│∧│
├──┤
10│∧│
└──┘
(2)线性探查法如下图:
下标 0 1 2 3 4 5 6 7 8 9 10
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
T[0..10]│33│1│13│12│34│38│27│22│ │ │ │
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
探查次数 1 1 1 3 4 1 7 8
用拉链法的查找成功平均查找长度为:
ASLsucc=(1*4+2*3+3*1)/8=1.625
查找失败时平均查找长度为:
ASLunsucc=(2+3+1+0+0+0+2+0+0+0+0)/11=0.73
用线性探查法查找成功时平均查找长度为:
ASLsucc=(1+1+1+3+4+1+7+8)/8=3.25
查找失败时平均查找长度为:
ASLunsucc=(9+8+7+6+5+4+3+2+1+1+1)/11=4.3
装填因子α拉链=4/11=0.36α线性探查=8/11=0.73
7.试写一算法判别给定的二叉树是否为二叉排序树,设此二叉树以二叉链表为存储结构,且树中结点的关键字均不相同。
【解】 由二叉排序树的定义可得:
二叉排序树中左子树的所有结点的值都小于根结点的值,所有右子树中结点的值都大于根结点的值。
那么只要对待判定的二叉树中的结点按层遍历并判断即可。
在该算法中要用到队列保存已遍历的结点指针。
typedefBinTNode*DataType;//循环队列中元素为二叉树结点指针
intBinSortStree(BinTreeT)
{
CirQueueQ;
BinTNode*p;
if(!
T)return1;//空树为二叉排序树
InitQueue(&Q);
EnQueue(&Q,T);
while(!
QueueEmpty(&Q))
{
p=DeQueue(&Q);
if(p->lchild)
if(p->datalchild->data)return-1;//不是二叉排序树
elseEnQueue(&Q,p->lchild);
if(p->rchild)
if(p->data>p->rchild->data)return-1;//不是二叉排序树
elseEnQueue(&Q,p->rchild);
}
return1;//是二叉排序树
}
8.试写一递归算法,从大到小输出二叉排序树中所有其值不小于x的关键字。
要求算法的时间为O(lgn+m),n为树中结点数,m为输出关键字个数(提示:
先遍历右子树,后遍历左子树)。
typedefintKeyType;//假定关键字类型为整数
typedefstructnode{//结点类型
KeyTypekey;//关键字项
InfoTypeotherinfo;//其它数据域,InfoType视应用情况而定,下面不处理它
structnode*lchild,*rchild;//左右孩子指针
}BSTNode;
typedefBSTNode*BSTree;
voidOUTPUTNODE(BSTreeT,KeyTypex)
{//从大到小输出二叉排序树中所有其值不小于x的关键字
if(T)
{
OUTPUTNODE(T->rchild,x);
if(T->key>=x)printf("%d",T->key);
OUTPUTNODE(T->Lchild,x);
}
}
习题精选
1.选择题
(1)对n个元素的表做顺序查找时,若查找每个元素的概率相同,则平均查找长度为()。
A.(n-1)/2B.n/2C.(n+1)/2D.n
(2)适用于折半查找的表的存储方式及元素排列要求为()。
A.链接方式存储,元素无序B.链接方式存储,元素有序
C.顺序方式存储,元素无序D.顺序方式存储,元素有序
(3)当在一个有序的顺序表上查找一个数据时,既可用折半查找,也可用顺序查找,但前者比后者的查找速度()。
A.必定快B.不一定
C.在大部分情况下要快D.取决于表递增还是递减
(4)折半查找有序表(4,6,10,12,20,30,50,70,88,100)。
若查找表中元素58,则它将依次与表中()比较大小,查找结果是失败。
A.20,70,30,50B.30,88,70,50
C.20,50D.30,88,50
(5)对22个记录的有序表作折半查找,当查找失败时,至少需要比较()次关键字。
A.3B.4C.5D.6
(6)折半搜索与二叉排序树的时间性能()。
A.相同B.完全不同
C.有时不相同D.数量级都是O(log2n)
(7)分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是()。
A.(100,80,90,60,120,110,130)
B.(100,120,110,130,80,60,90)
C.(100,60,80,90,120,110,130)
D.(100,80,60,90,120,130,110)
(8)在平衡二叉树中插入一个结点后造成了不平衡,设最低的不平衡结点为A,并已知A的左孩子的平衡因子为0右孩子的平衡因子为1,则应作()型调整以使其平衡。
A.LLB.LRC.RLD.RR
(9)下列关于m阶B-树的说法错误的是()。
A.根结点至多有m棵子树
B.所有叶子都在同一层次上
C.非叶结点至少有m/2(m为偶数)或m/2+1(m为奇数)棵子树
D.根结点中的数据是有序的
(10)下面关于B-和B+树的叙述中,不正确的是()。
A.B-树和B+树都是平衡的多叉树B.B-树和B+树都可用于文件的索引结构
C.B-树和B+树都能有效地支持顺序检索D.B-树和B+树都能有效地支持随机检索
(11)m阶B-树是一棵()。
A.m叉排序树B.m叉平衡排序树
C.m-1叉平衡排序树D.m+1叉平衡排序树
(12)下面关于哈希查找的说法,正确的是()。
A.哈希函数构造的越复杂越好,因为这样随机性好,冲突小
B.除留余数法是所有哈希函数中最好的
C.不存在特别好与坏的哈希函数,要视情况而定
D.哈希表的平均查找长度有时也和记录总数有关
(13)下面关于哈希查找的说法,不正确的是()。
A.采用链地址法处理冲突时,查找一个元素的时间是相同的
B.采用链地址法处理冲突时,若插入规定总是在链首,则插入任一个元素的时间是相同的
C.用链地址法处理冲突,不会引起二次聚集现象
D.用链地址法处理冲突,适合表长不确定的情况
(14)设哈希表长为14,哈希函数是H(key)=key%11,表中已有数据的关键字为15,38,61,84共四个,现要将关键字为49的元素加到表中,用二次探测法解决冲突,则放入的位置是()。
A.8B.3C.5D.9
(15)采用线性探测法处理冲突,可能要探测多个位置,在查找成功的情况下,所探测的这些位置上的关键字()。
A.不一定都是同义词B.一定都是同义词
C.一定都不是同义词D.都相同
2.应用题
(1)假定对有序表:
(3,4,5,7,24,30,42,54,63,72,87,95)进行折半查找,试回答下列问题:
画出描述折半查找过程的判定树;
若查找元素54,需依次与哪些元素比较?
若查找元素90,需依次与哪些元素比较?
假定每个元素的查找概率相等,求查找成功时的平均查找长度。
先画出判定树如下(注:
mid=(1+12)/2=6):
30
563
374287
424547295
查找元素54,需依次与30,63,42,54元素比较;
查找元素90,需依次与30,63,87,95元素比较;
求ASL之前,需要统计每个元素的查找次数。
判定树的前3层共查找1+2×2+4×3=17次;
但最后一层未满,不能用8×4,只能用5×4=20次,
所以ASL=1/12(17+20)=37/12≈3.08
(2)在一棵空的二叉排序树中依次插入关键字序列为12,7,17,11,16,2,13,9,21,4,请画出所得到的二叉排序树。
12
717
2111621
4913
验算方法:
用中序遍历应得到排序结果:
2,4,7,9,11,12,13,16,17,21
(3)已知如下所示长度为12的表:
(Jan,Feb,Mar,Apr,May,June,July,Aug,Sep,Oct,Nov,Dec)
试按表中元素的顺序依次插入一棵初始为空的二叉排序树,画出插入完成之后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
若对表中元素先进行排序构成有序表,求在等概率的情况下对此有序表进行折半查找时查找成功的平均查找长度。
按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
解:
(4)对下面的3阶B-树,依次执行下列操作,画出各步操作的结果。
插入90
插入25
插入45
删除60
(5)设哈希表的地址范围为0~17,哈希函数为:
H(key)=key%16。
用线性探测法处理冲突,输入关键字序列:
(10,24,32,17,31,30,46,47,40,63,49),构造哈希表,试回答下列问题:
画出哈希表的示意图;
若查找关键字63,需要依次与哪些关键字进行比较?
若查找关键字60,需要依次与哪些关键字比较?
假定每个关键字的查找概率相等,求查找成功时的平均查找长度。
画表如下:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
32
17
63
49
24
40
10
30
31
46
47
查找63,首先要与H(63)=63%16=15号单元内容比较,即63vs31,no;
然后顺移,与46,47,32,17,63相比,一共比较了6次!
查找60,首先要与H(60)=60%16=12号单元内容比较,但因为12号单元为空(应当有空标记),所以应当只比较这一次即可。
对于黑色数据元素,各比较1次;共6次;
对红色元素则各不相同,要统计移位的位数。
“63”需要6次,“49”需要3次,“40”需要2次,“46”需要3次,“47”需要3次,
所以ASL=1/11(6+2+3×3+6)=23/11
(6)设有一组关键字(9,01,23,14,55,20,84,27),采用哈希函数:
H(key)=key%7,表长为10,用开放地址法的二次探测法处理冲突。
要求:
对该关键字序列构造哈希表,并计算查找成功的平均查找长度。
散列地址
0
1
2
3
4
5
6
7
8
9
关键字
14
01
9
23
84
27
55
20
比较次数
1
1
1
2
3
4
1
2
平均查找长度:
ASLsucc=(1+1+1+2+3+4+1+2)/8=15/8
以关键字27为例:
H(27)=27%7=6(冲突)H1=(6+1)%10=7(冲突)
H2=(6+22)%10=0(冲突)H3=(6+33)%10=5所以比较了4次。
(7)设哈希函数H(K)=3Kmod11,哈希地址空间为0~10,对关键字序列(32,13,49,24,38,21,4,12),按下述两种解决冲突的方法构造哈希表,并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc和ASLunsucc。
线性探测法;
链地址法。
散列地址
0
1
2
3
4
5
6
7
8
9
10
关键字
4
12
49
38
13
24
32
21
比较次数
1
1
1
2
1
2
1
2
ASLsucc=(1+1+1+2+1+2+1+2)/8=11/8
ASLunsucc=(1+2+1+8+7+6+5+4+3+2+1)/11=40/11
ASLsucc=(1*5+2*3)/8=11/8
ASLunsucc=(1+2+1+2+3+1+3+1+3+1+1)/11=19/11