算法与数据结构答案第9章查找.docx
《算法与数据结构答案第9章查找.docx》由会员分享,可在线阅读,更多相关《算法与数据结构答案第9章查找.docx(27页珍藏版)》请在冰点文库上搜索。
算法与数据结构答案第9章查找
第9章集合
一、基础知识题
假设对长度均为n的有序的顺序表和无序的顺序表别离进行顺序查找,试在以下三种情形下别离讨论二者在等概率情形下平均查找长度是不是相同?
(1)查找不成功,即表中没有和关键字K相等的记录;
(2)查找成功,且表中只有一个和关键字K相等的记录;
(3)查找成功,且表中有多个和关键字K相等的记录,要求计算有多少个和关键字K相等的记录。
【解答】
(1)平均查找长度不相同。
前者在n+1个位置都可能失败,后者失败时的查找长度都是n+1。
(2)平均查找长度相同。
在n个位置上都可能成功。
(3)平均查找长度不相同。
前者在某个位置上(1<=i<=n)查找成功时,和关键字K相等的记录是持续的,而后者要查找完顺序表的全数记录。
在查找和排序算法中,监视哨的作用是什么?
【解答】监视哨的作用是免去查找进程中每次都要检测整个表是不是查找完毕,提高了查找效率。
用分块查找法,有2000项的表分成多少块最理想?
每块的理想长度是多少?
假设每块长度为25,平均查找长度是多少?
【解答】分成45块,每块的理想长度为45(最后一块长20)。
假设每块长25,那么平均查找长度为ASL=(80+1)/2+(25+1)/2=(顺序查找确信块),或ASL=19(折半查找确信块)。
用不同的输入顺序输入n个关键字,可能构造出的二叉排序树具有多少种不同形态?
【解答】
证明假设二叉排序树中的一个结点存在两个小孩,那么它的中序后继结点没有左小孩,中序前驱结点没有右小孩。
【证明】依照中序遍历的概念,该结点的中序后继是其右子树上按中序遍历的第一个结点,即右子树上值最小的结点:
叶子结点或仅有右子树的结点,没有左小孩;而其中序前驱是其左子树上按中序遍历的最后个结点,即左子树上值最大的结点:
叶子结点或仅有左子树的结点,没有右小孩。
命题得证。
关于一个高度为h的AVL树,其最少结点数是多少?
反之,关于一个有n个结点的AVL树,其最大高度是多少?
最小高度是多少?
【解答】设以Nh表示深度为h的AVL树中含有的最少结点数。
显然,N0=0,N1=1,N2=2,且Nh=Nh-1+Nh-2+1(h≥2)。
那个关系与斐波那契序列类似,用归纳法能够证明:
当h≥0时,Nh=Fh+2-1,而Fh约等于Фh/
。
其中Ф=(1+
)/2,那么Nh约等于Фh+2/(
-1)(即深度为h的AVL树具有的最少结点数)。
有n个结点的平稳二叉树的最大高度是logФ(
(n+1))-2,最小高度是⎣log2n⎦。
试推导含有12个结点的平稳二叉树的最大深度,并画出一棵如此的树。
【解答】依照的结论可知,深度为n的AVL树中的最少结点数为
因此12=
,有
=13,求得n+2=7(Fibonacci数列第一项的值假设为1,对应于二叉树表
示有一个结点的二叉树的深度为1),因此n=5。
可表示为如以下图所示的AVL树:
假定有n个关键字,它们具有相同的哈希函数值,用线性探测方式把这n个关键字存入到哈希表中要做多少次探测?
【解答】n个关键字都是同义词,因此用线性探测法第一个关键字存入时可不能发生冲突,因此探测的次数应为
次。
成立一棵具有13个结点的判定树,并求其成功和不成功的平均查找长度值各为多少。
【解答】
3
10
1
5
12
4
2
6
8
11
9
13
7
查找成功时的平均查找长度为:
查找不成功时的平均查找长度为:
二叉排序树中关键字互不相同,那么其中关键字最小值结点无左小孩,关键字最大值结点无右小孩,此命题是不是正确?
最小值结点和最大值结点必然是叶子吗?
一个新结点老是插在二叉排序树的某叶子上吗?
【解答】
(1)此命题正确。
(2)最小值结点和最大值结点不必然是叶子结点。
(3)一个新结点不必然老是插在二叉排序树的某叶子上。
回答下列问题并填空:
(1)散列表存储的大体思想是什么?
(2)散列表存储中解决碰撞的大体方式有哪些?
其大体思想是什么?
(3)用线性探查法解决碰撞时,如何处置被删除的结点?
什么缘故?
【解答】
(1)散列表存储的大体思想是用关键字的值决定数据元素的存储地址
(2)散列表存储中解决碰撞的大体方式:
①开放定址法形成地址序列的公式是:
Hi=(H(key)+di)%m,其中m是表长,di是增量。
依照di取法不同,又分为三种:
a.di=1,2,…,m-1称为线性探测再散列,其特点是逐个探测表空间,只要散列表中有空闲空间,就可解决碰撞,缺点是容易造成“聚集”,即不是同义词的关键字争夺同一散列地址。
b.di=12,-12,22,-22,…,±k2(k≤m/2)称为二次探测再散列,它减少了聚集,但不容易探测到全数表空间,只有当表长为形如4j+3(j为整数)的素数时才有可能。
c.di=伪随机数序列,称为随机探测再散列。
②再散列法Hi=RHi(key)i=1,2,…,k,是不同的散列函数,即在同义词产生碰撞时,用另一散列函数计算散列地址,直到解决碰撞。
该方式不易产生“聚集”,但增加了计算时刻。
③链地址法将关键字为同义词的记录存储在同一链表中,散列表地址区间用H[0..m-1]表示,分量初始值为空指针。
凡散列地址为i(0≤i≤m-1)的记录均插在以H[i]为头指针的链表中。
这种解决方式中数据元素个数不受表长限制,插入和删除操作方便,但增加了指针的空间开销。
这种散列表常称为开散列表,而①中的散列表称闭散列表,含义是元素个数受表长限制。
④成立公共溢出区设H[0..m-1]为大体表,凡关键字为同义词的记录,都填入溢出区O[0..m-1]。
(3)要在被删除结点的散列地址处作标记,不能物理的删除。
不然,中断了查找通路。
如何衡量哈希函数的好坏?
简要表达哈希表技术中的冲突概念,并指出三种解决冲突的方式。
【解答】评判哈希函数好坏的因素有:
可否将关键字均匀影射到哈希空间上,有无好的解决冲突的方式,计算哈希函数是不是简单高效。
由于哈希函数是紧缩映像,冲突难以幸免。
解决冲突的方式见上面题。
设有一组关键字{9,01,23,14,55,20,84,27},采纳哈希函数:
H(key)=key%7,表长为10,用开放地址法的二次探测再散列方式Hi=(H(key)+di)%10(di=12,22,32,…,)解决冲突。
要求:
对该关键字序列构造哈希表,并计算查找成功的平均查找长度。
【解答】
散列地址
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次。
对下面的关键字集合{30,15,21,40,25,26,36,37},假设查找表的装填因子为,采纳线性探测再散列方式解决冲突。
要求:
(1)设计哈希函数;
(2)画出哈希表;
(3)计算查找成功和查找失败的平均查找长度。
【解答】由于装填因子为,关键字有8个,因此表长为8/=10。
(1)用除留余数法,哈希函数为H(key)=key%7
(2)
散列地址
0
1
2
3
4
5
6
7
8
9
关键字
21
15
30
36
25
40
26
37
比较次数
1
1
1
3
1
1
2
6
(3)计算查找失败时的平均查找长度,必需计算不在表中的关键字,当其哈希地址为i(0≤i≤m-1)时的查找次数。
本例中m=10。
故查找失败和查找成功时的平均查找长度别离为:
ASLunsucc=(9+8+7+6+5+4+3+2+1+1)/10=ASLsucc=16/8=2
设哈希函数H(k)=3k%11,散列地址空间为0~10,对关键字序列(32,13,49,24,38,21,4,12)按下述两种解决冲突的方式构造哈希表:
(1)线性探测再散列
(2)链地址法,并别离求出等概率下查找成功时和查找失败时的平均查找长度。
【解答】
(1)
散列地址
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
查找成功时的平均查找长度为
查找不成功时的平均查找长度为
0
1
2
3
4
5
6
7
8
9
10
∧
(2)
4
∧
∧
∧
12
38
∧
49
∧
∧
24
13
∧
∧
21
32
∧
∧
查找成功时的平均查找长度为
查找不成功时的平均查找长度为
已知长度为l2的表{Jan,Feb,Mar,Apr,May,June,July,Aug,Sep,Oct,Nov,Dec}
(1)试按表中元素的顺序依次插入一棵初始为空的二叉排序树,并求在等概率情形下查找成功的平均查找长度。
(2)用表中元素构造一棵最正确二叉排序树,求在等概率的情形下查找成功的平均查找长度。
(3)按表中元素顺序构造一棵AVL树,并求其在等概率情形下查找成功的平均查找长度。
Jan
July
Aug
Feb
Apr
May
Mar
June
Nov
Sep
Dec
Oct
【解答】
(1)
ASLsuss=(1*1+2*2+3*3+4*3+5*2+6*1)/12=42/12=
(2)最正确二叉排序树的形状和12个结点的折半查找判定树相同,见题目。
ASLsuss=(1*1+2*2+4*3+5*4)/12=37/12
Mar
(3)
Oct
Jan
Sep
May
June
Aug
Nov
Feb
Apr
July
Dec
ASLsuss=(1*1+2*2+3*4+4*4+5*1)/12=38/12
假定对有序表:
(3,4,5,7,24,30,42,54,63,72,87,95)进行折半查找,试回答以下问题:
(1)画出描述折半查找进程的判定树;
(2)假设查找元素54,需依次与哪些元素比较?
(3)假设查找元素90,需依次与哪些元素比较?
(4)假定每一个元素的查找概率相等,求查找成功时的平均查找长度。
【解答】
(1)
6
判定树:
(注:
结点内的数字为数据元素,隔壁的数字是该元素在有序表中的位置)
30
9
3
63
5
11
7
1
4
87
42
7
3
95
72
54
24
4
12
10
2
5
8
(2)假设查找元素54,需依次与元素30、63、42、54比较,查找成功。
(3)假设查找元素90,需依次与元素30、63、87、95比较,查找失败。
(4)等概率下,查找成功时的平均查找长度:
ASL=(1*1+2*2+4*3+5*4)/12=37/12
直接在二叉排序树中查找关键字K与在中序遍历输出的有序序列中查找关键字K,其效率是不是相同?
输入关键字有序序列来构造一棵二叉排序树,然后对此树进行查找,其效率如何?
什么缘故?
【解答】在二叉排序树上查找关键字K,走了一条从根结点最多到叶子的途径,时刻复杂度是O(logn),而在中序遍历输出的序列中查找关键字K,时刻复杂度是O(n)。
按序输入成立的二叉排序树,蜕变成单枝树,其平均查找长度是(n+1)/2,时刻复杂度也是O(n)。
设二叉排序树中关键字由1到1000的整数组成,现要查找关键字为363的结点,下述关键字序列哪个不可能是在二叉排序树中查到的序列?
说明缘故。
(1)51,250,501,390,320,340,382,363
(2)24,877,125,342,501,623,421,363
【解答】序列
(2)不可能是二叉排序树中查到363的序列。
查到501后,因363<501,后面应显现小于501的数,但序列中显现了623,故不可能。
用关键字1,2,3,4的四个结点
(1)能构造出几种不同的二叉排序树?
其中
(2)最优查找树有几种?
(3)AVL树有几种?
(4)完全二叉树有几种?
试画出这些二叉排序树。
【解答】
(1)此题的本质是给定中序序列一、二、3、4,有几种不同的二叉排序树,即该中序序列相当多少不同的前序序列,这是树的计数问题。
设中序序列中元素数为n,那么二叉数的数量为1/(n+1)C2nn,那个地址n=4,故有14种。
图示如下:
4
3
2
1
(14)
(6)
2
1
3
4
(9)
3
2
4
1
(11)
4
1
3
2
(4)
1
2
4
3
(8)
3
1
4
2
(7)
2
1
4
3
(12)
4
2
3
1
(3)
1
2
3
4
(5)
1
3
4
2
(10)
4
1
2
3
(2)
1
2
4
3
(13)
4
3
2
1
(1)
1
2
3
4
(2)最优查找树有4种,图中(6)(7)(8)(9)。
(3)AVL树也有4种,图中(6)(7)(8)(9)。
(4)完全二叉树有1种,图中(9)。
简要表达B-树与B+树的区别?
【解答】m阶的B+树和B-树要紧区别有三:
(1)有n棵子树的结点中含有n(B-树中n-1)个关键字;
(2)B+树叶子结点包括了全数关键字信息,及指向含关键字记录的指针,且叶子结点本身依关键字大小自小到大顺序链接;
(3)B+树的非终端结点能够看成是索引部份,结点中只含其子树(根结点)中最大(或最小)关键字。
B+树的查找既能够顺序查找,也能够随机查找,B-只能随机查找。
包括n个关键码的m阶B-树在一次检索中最多涉及多少个结点?
(要求写出推导进程。
)
【解答】此题等价于“含有n个关键字的m阶B-树的最大高度是多少”?
一次检索中最多走一条从根到叶子的途径,由于根结点至少有两棵子树,其余每一个(除叶子)结点至少有⎡m/2⎤棵子树,那么第三层至少有⎡m/2⎤*2个结点,第l+1层至少有2*⎡m/2⎤l-1个结点。
设B-树深度为l+1,即第l+1层是叶子结点,叶子结点数是n+1(下面推导),故有n+1≥2*⎡m/2⎤l-1,即l≤log⎡m/2⎤()+1。
注:
推导B-树中叶子结点数s与关键字数n的关系式:
s=n+1
设B-树某结点的子树数为Ci,那么该结点的关键字数Ni=Ci-1。
关于有k个结点的B-树,有
∑Ni=∑(Ci-1)=∑Ci-k(1≤i≤k)……
(1)
因为B树上的关键字数,即∑Ni=n(1≤i≤k)……
(2)
而B-树上的子树数可如此计算:
每一个结点(除根结点)都是一棵子树,设叶子(子树)数为s;那么
∑Ci=(k-1)+s(1≤i≤k)……(3)
综合
(1)
(2)(3)式,有s=n+1。
证毕。
设有一棵空的3阶B-树,依次插入关键字30,20,10,40,80,58,47,50,29,22,56,98,99,请画出该树。
【解答】
4058
2029
50
98
10
22
30
47
56
80
99
含9个叶子结点的3阶B-树中至少有多少个非叶子结点?
含10个叶子结点的3阶B-树中最多有多少个非叶子结点?
【解答】含9个叶子结点的3阶B-树至少有4个非叶子结点,当每一个非叶子结点均含3棵子树,第三层是叶子结点时确实是这种情形。
当4层3阶B-树有10个叶子结点时,非叶子结点达到最大值8个:
其中第一层1个,第二层2个,第三层5个。
选择题:
对顺序表进行二分查找时,要求顺序表必需:
A.以顺序方式存储B.以顺序方式存储,且数据元素有序
C.以链接方式存储D.以链接方式存储,且数据元素有序
【解答】B
选择题:
以下二叉排序树中查找效率最高的是:
A.平稳二叉树B.二叉查找树
C.没有左子树的二叉排序树D.没有右子树的二叉排序树
【解答】A
二、算法设计题
元素集合已存入整型数组A[1..n]中,试写出依次取A中各值A[i](1<=i<=n)构造一棵二叉排序树T的非递归算法。
【题目分析】此题以非递归形式成立二叉排序树
voidCSBT(BSTreeT,ElemTypeA[],intn)
{∥以存储在数组K中的n个关键字,成立一棵初始为空的二叉排序树
for(i=1;i<=n;i++)
{
p=T;f=null;∥在挪用Creat_BST时,T=null
while(p!
=null)
if(p->data{f=p;p=p->rchild;}∥f是p的双亲
elseif(p->data>A[i]){f=p;p=p->lchild;}
s=(BSTree)malloc(sizeof(BiNode));∥申请结点空间
s->data=A[i];s->lchild=null;s->rchild=null;
if(f==null)T=s;∥根结点
elseif(s->datadata)f->lchild=s;∥左子女
elsef->rchild=s;∥右子树根结点的值大于等于根结点的值
}
}∥算法终止
编写删除二叉排序树中值是X的结点的算法。
要求删除结点后仍然是二叉排序树,而且高度没有增加。
【题目分析】在二叉排序树上删除结点,第一要查找该结点。
查找成功后,假设该结点无左子树,那么可直接将其右子树的根结点接到其双亲结点上;假设该结点有左子树,那么将其左子树中按中序遍历的最后一个结点代替该结点,从而不增加树的高度。
voidDelete(BSTreebst,keytypeX)∥在二叉排序树bst上,删除其关键字为X的结点
{BSTreef,p=bst;
while(p&&p->key!
=X)∥查找值为X的结点
if(p->key>X){f=p;p=p->lchild;}
else{f=p;p=p->rchild;}
if(p==null){printf(“无关键字为X的结点\n”);exit(0);}
if(p->lchild==null)∥被删结点无左子树
if(f->lchild==p)f->lchild=p->rchild;∥将被删结点的右子树接到其双亲上
elsef->rchild=p->rchild;
else{
q=p;s=p->lchild;∥被删结点有左子树
while(s->rchild!
=null)∥查左子树中最右下的结点(中序最后结点)
{q=s;s=s->rchild;}
p->key=s->key;∥结点值用其左子树最右下的结点的值代替
if(q==p)
p->lchild=s->lchild;∥被删结点左子树的根结点无右子女
elseq->rchild=s->lchild;∥s是被删结点左子树中序序列最后一个结点
free(s);
}∥else
}∥算法终止
假设二叉排序树的各个元素值均不相同,设计一个递归算法按递减顺序打印各元素的值。
【题目分析】按着“右子树-根结点-左子树”遍历二叉排序树,并输出结点的值。
voidInOrder(BSTreebt)∥按递减顺序输出二叉排序树结点的值
{
BiTrees[],p=bt;∥s是元素为二叉树结点指针的栈,容量足够大
inttop=0;
while(p||top>0){
while(p)
{s[++top]=p;bt=p->rchild;}∥沿右子树向下
if(top>0)
{p=s[top--];printf(p->data);p=p->lchild;}
}
}∥终止
以下是递归输出,算法思想是一样的。
voidInvertOrder(BSTreebt)∥按递减顺序输出二叉排序树结点的值
{BiTreep=bt;
if(p)
{InOrder(bt->rchild);∥中序遍历右子树
printf(p->data);∥访问根结点
InOrder(bt->lchild);∥中序遍历左子树
}∥if
}∥终止
设记录R1,R2,…,Rn按关键字值从小到大顺序存储在数组r[1..n]中,在r[n+1]处设立一个监视哨,其关键字值为+∞;试写一查找给定关键字k的算法;并画出此查找进程的判定树,求出在等概率情形下查找成功时的平均查找长度。
intSearch(rectyper[],intn,keytypek)
{∥在n个关键字从小到大排列的顺序表中,查找关键字为k的结点
r[n+1].key=MAXINT;∥在高端设置监视哨
i=1;
while(r[i].keyif(r[i].key==k)returni%(n+1);
elsereturn(0);
}∥算法终止
查找进程的判定树是单枝树,限于篇幅再也不画出。
此题中尽管表按关键字有序,但进行顺序查找,查找成功的平均查找长度亦为(n+1)/2。
在二叉排序树中查找值为X的结点,假设找到,那么记数(count)加1;不然,作为一个新结点插入树中,插入后仍为二叉排序树,写出其递归和非递归算法(要求给出结点的概念)。
typedefstructnode
{ElemTypedata;intcount;structnode*llink,*rlink;
}BiTNode,*BSTree;
voidSearch_InsertX(BSTreet,ElemTypeX)
{∥在二叉排序树t中查找值为X的结点,假设查到,那么其结点的count域值增1
∥不然,将其插入到二叉排序树中
p=t;
while(p!
=null&&p->data!
=X)∥查找值为X的结点,f指向当前结点的双亲
{f=p;
if(p->datarlink;elsep=p->llink;
}
if(!
p)∥无值为x的结点,插入之
{p=(BiTNode*)malloc(sizeof(BiTNode));
p->data=X;p->llink=null;p->rlink=null;
if(t==null)t=p;∥假设初始为空树,那么插入结点为根结点
elseif(f->data>X)
f->llink=p;
elsef->rlink=p;
}
elsep->count