数据结构 第九章查找
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第九章查找:习题
习题
一、选择题
1.散列表查找中k个关键字具有同一散列值,若用线性探测法将这k个关键字对应的记录存入散列表中,至少要进行( )次探测。
A. k
B.k+l
C. k(k+l)/2
D. l+k (k+l)/2
2.下述命题( )是不成立的。
A. m阶B-树中的每一个结点的子树个数都小于或等于m
B. m阶B-树中的每一个结点的子树个数都大于或等于『m/2-1
C. m阶B-树中的每一个结点的子树高度都相等
D.m阶B-树具有k个子树的非叶子结点含有(k-l)个关键字
3.如果要求一个基本线性表既能较快地查找,又能适应动态变化的要求,可以采用( ) 查找方法。
A.分块
B. 顺序
C. 二分
D.散列
4.设有100个元素,用折半查找法进行查找时,最大比较次数是( ),最小比较次数
是( )。
A.7,1
B.6,l
C.5,1
D. 8,1
5.散列表长m=15,散列表函数H(key)=key%13。
表中已有4个结点:addr(18)=5;addr(32)=6; addr(59)=7; addr(73)=8;其余地址为空,如果用二次探测再散列处理冲突,关键字为109的结点的地址是( )。
A. 8
B. 3
C. 5
D. 4
6.用分块查找时,若线性表中共有729个元素,查找每个元素的概率相同,假设采用顺序查找来确定结点所在的块时,每块应分( )个结点最佳。
A. 15
B. 27
C. 25
D. 30
7.散列函数有一个共同性质,即函数值应当以( )取其值域的每个值。
A.同等概率
B. 最大概率
C. 最小概率
D.平均概率
8.设散列地址空间为O..m-1,k为关键字,假定散列函数为h(k)=k%p,为了减少冲突,一般应取p为( )。
A.小于m的最大奇数
B. 小于m的最大素数
C.小于m的最大偶数
D.小于m的最大合数
9.当向一棵m阶的B-树做插入操作时,若使一个结点中的关键字个数等于( ),则必
须分裂成两个结点。
A.m
B. m-l
C.m+l
D.[m+1]
10.当向一棵m阶的B壤f做删除操作时,若使一个结点中的关键字个数等于( ),则可能需要用它的左兄弟或右兄弟结点合并成一个结点。
A. [m/2]
B.[m-l]
C. [m/2]+1
D. [m+l]-2
11.衡量查找算法效率的主要标准是( )。
A. 元素个数
B. 所需的存储量
C. 平均查找长度
D.算法难易程度
二、填空题
1.顺序查找长度为n的顺序表,查找成功的平均查找长度为____。
2.折半查找要求线性表的存储结构为____;而用顺序查找的线性表,既可以采用,也可以采用____。
3.散列查找是一种对关键字进行____的查找方法。
4.散列法既是一种查找方法,又是一种____方法。
5.在有序表(12,24,36,48,60,72,84)中二分查找关键字72时所需进行的关键字比较次数为____。
6.在散列存储中,装填因子α的值越大,存取元素时发生冲突的可能性就____;α的值越小,存取元素时发生冲突的可能性就____。
7.在线性表的散列存储中,处理冲突有____和____两类;当装填因子一定时,
采用链地址法处理冲突比采用开放定址法处理冲突的平均查找长度要____。
8.在一棵10阶的B-树上,每一个树根结点中所含的关键字数目最多允许为____;
最少允许为____。
9.当向B-树中插入关键字时,可能引起结点的____;最终可能导致整个B-树的高
度____。
三、简答题
1.对含有n个互不相同元素的集合,同时找最大元素和最小元素至少需要多少次比较?
2.若对具有n个元素的有序的顺序表和无序的顺序表分别进行顺序查找,试在下述两种情况下分别讨论两者在等概率时的平均查找长度:
(1)查找不成功,即表中无关键字等于给定值。
(2)查找成功,即表中有关键字等于给定值k的记录。
3.对给定的关键字集合,以不同的次序插入初始为空的树中,是否有可能得到同一棵二叉排序树?
4.将二叉排序树T的前序序列中关键字依次插入初始为空的树中,所得到的二叉排序树T’与T是否相同?为什么?
5.设二叉排序树中关键字由1到1000内的整数构成,现要查找关键字为363的结点,下述关键字序列哪一个不可能是在二叉排序树上查找到的序列。
(1) 2,252,401,398,330,344,397,363
(2) 924,220,911,244,898,258,362,363
(3) 925,202,911,240,912,245,363
(4) 2,399,387,219,266,382,381,278,363
6.为什么二叉排序树长高时,新结点总是一个叶子,而B-树长高时,新结点总是根?哪一种长高能保证树平衡?
7.设有一组关键字(17,13,14,153,29,35)需插入到表长为12的散列表中.请回答以下问题:
(l)设计一个适合该散列表的散列函数;
(2)设计的散列函数将上述关键字插入到散列表中,画出其结构;并指出用线性探测法
解冲突时构造散列表的装填因子为多少?
8.已知记录关键字集合( 53,17,19,61,98,75,79,63,46,49),要求散列到地址区间(100,101,102,103,104,105,106,107,108,109)内,若产生冲突用开放定址法的线性探测法解决,要求写出选用的散列函数;形成散列表;计算出查找成功时平均查找长度(设等概率情况)。
9.已知一个含有100条记录的表,关键字为中国姓氏的拼音,若采用散列存储方式存放此表,请给出此表的一个散列表设计方案,要求它在等概率的情况下查找成功的平均查找长度不超过3。
四、算法设计题
1.利用二叉树遍历的思想写一个判断二叉树是否为平衡二叉树的算法test(BsTree *p,i nt balance,…);其中p初值指向待判二叉树的根,balance是一判断结果的输出标志,初值为True(l),根据需要可增加其他必要的参数。
在判断各点平衡的过程中,一旦发现有悖于平衡二叉树的定义,则balance应转变为False(0),且终止该过程。
2.设单链表的结点按关键字的大小从小到大排列,试写出对此链表的查找算法,并说明是否可用折半查找。
3.试设计一个算法,求出指定结点在给定的二叉排序树中的层次。
4.编写对有序表进行顺序查找的算法,并画出对有序表进行顺序查找的判定树,假设每次查找时的给定值为随机值,查找成功和不成功的概率也相等,试求进行每依次查找时,与给定值进行比较的关键字个数的期望值。
5.已知一组递增有序的关键字k[0…n-1];k0≤k i≤…≤k n-1,在等概率查找的前提下,可以生成一棵二叉排序树。
以哪个关键字为根结点,按什么方式生成二叉排序树既有平衡性又简单?阐明算法思路,写出相应的算法。
如果k[0…10]为:(7,12,13,15,21,33,38, 41,49,55,58)。
按你的算法画出这棵二叉排序树。
6.编写判定给定的二叉树是否是二叉排序树的函数。
7.编写一个算法,删除二叉排序树中除根结点以外的任一结点p,已知p的双亲结点f。
8.已知某散列表的装填因子小于1,散列函数h(k)为k(k为标识符,均小写)的第一个字母在字母表中的序号。
采用开放定址法的线性探测再散列解决冲突。
试编写一个按第一个字母的顺序输出散列表中所有关键字的算法。
第九章查找
第9章查找
一.选择题
1.C 2.D 3.A 4.D 5.D 6.B
7.A 8.B 9.A 10.D 11.C
二.填空题
1.(n+l)/2。
2.顺序存储结构、顺序存储结构、链接存储结构。
3.运算。
4.存储。
5.2 6.越大,越小。
7.开放定址法,链地址法,短。
8.9,4。
9.分裂,增加l。
三、简答题
1.按照下面的顺序查找算法,如果初始序列递增有序,则只需比较n-l次;如果初始序列递减有序,则需比较2(n-l)次。
因此,对含有n个互不相同元素的集合,同时找最大元素和最小元素至少需要比较n-l次,最多需要比较2(n-l)次。
max=min=r[O].key;
for(i=1;i<n;i++)
if(r[i]. key>max) max-r[i]. key;
else if(r[i]. key<min) min=r[i].key;
2.(1)查找不成功的情况。
1)对于有序表,第一小的元素在0号位置,第二小的元素在l号位置,第n小的元素,
即最大的元素在n-l号位置。
显然,查找第i小的元素只要比较i+l次就能够确定查找不成功。
因此,在等概率的情况下,查找不成功的平均查找长度为
2)对于无序的顺序表,查找每一个元素都要比较n+l次才能确定其查找不成功。
因此在等概率的情况下查找不成功的平均查找长度为n+l。
(2)查找成功的情况。
不论是有序表还是无序表,在位置i上查找成功的比较次数均为i+l次,因此在等概率的情况下,其成功的平均查找长度均为(n+l)/2。
3.除单元素外,对给定关键字集合,以不同的次序插入初始为空的树中不可能得到同一棵二叉排序树。
4.因为按二叉排序树T的前序序列将关键字依次插入到初始为空的二叉排序树T’中的插入过程与二叉排序T,的前序遍历过程完全一致,次序不会改变,所以T’与T完全相同。
5.关键字序列(3)不可能是在二叉排序树上查找到的序列。
因为根据序列(3),240是911的左孩子,912在240的后面,是240的右孩子;而实际上,912比911大,应当在911的右子树上,即912不可能出现在911的左子树上,所以序列(3)不可能出现。
6.因为二叉排序树的插入总是从根结点开始逐层往下比较,若比根小,则走左边;若比根大,则走右边。
这样找到的插入位置,不是某结点的空闲左链域就是某结点的空闲右链域,即新结点总是作为叶结点插入进来的。
B-树的插入不是在树中添加一个叶结点;而是首先在最底层的某个终端结点中添加一个关键字,若该结点的关键字数不超过m-l,则完成插入,否则进行向上“分裂”,从而使新结点总是以根的形式出现。
B-树的插入能保证树的平衡。
7.(1)由于散列表的长度为12,则可选不超过表长的最大素数ll作为除留余数法的模,则可得其散列函数为h(k)=k%11。
(2)若用线性探测法解决冲突,则可构造出散列表如下:
此时,其装填因子为:α= 6/12=0.5。
8.散列函数:H(key)=lOO+(key个位数+key十位数)%10。
形成散列表为:
查找成功时的平均长度为:(1×5+2×1+3×1+5×3)/10=2.5
9.(1)确定该散列表的装填因子a。
散列表的查找效率与采用的处理冲突的方法及散列表的装填因子α有关。
α越小,表中的记录数越少或表越长,发生冲突的可能性就越小,此时的查找效率越高:反之,α越大,表中的记录数越多或表的长度越小,表中记录的密度越高,发生冲突的可能性越大,查找效率越低,所花的时间也越长。
依据这些因素,可以采用二次探测法作为处理冲突的方法,此时在等概率的情况下查找成功的平均查找长度为:Sn ≈-(ln(1-α))/α
由题意可知要求S。
<3,即使Sn≈-(ln(1-α))/α<3,求解α可取0.8。
(2)确定散列表的长度。
由于表中具有100个记录,可选择散列表的长度约为100/0.8= 125,选择表长127(最接近125的质数)。
(3)依据关键字的特性和散列表的长度选择合适的散列函数。
由于表中的记录关键字为中国姓氏的拼音,它们长度不等,可以选择随机法构造散列函数。
比如:
H(key)=(姓氏的拼音中各字母的序号和)%127
从而就可以简单地设计一个散列表。
四、算法设计题
1.一棵二叉树是平衡二叉树的充要条件是:左右子树都是平衡二叉树,且左右子树的高度差的绝对值不超过l。
具体实现算法如下:
void test (BsTree *p, int *balance, int *h)
{ int hl, hr, bl, br;
if (p){*blance=l;*h=0;) //h表示树高
else if(! p->lchild&& !p->rchild){
*balance=l; *h=l;)
else ( test (p->lchild, &bl, &hl);
test (p->rchild, &br, &hr);
*h=l+max( hl, hr);
if (abs (hl-hr)<2) +balance=l;
else *balance=0;
}
}
2.设单链表的头指针为head,若查找成功,则返回待查找结点的指针。
否则查找失败,返回一个空指针,算法描述如下:
LinkList *Search (LinkList *head,KeyType k) //head为单链表类型
{ LinkList *q;
q=head;
while(q&&k>q->key) q=q->next;
if (k==q->key) return q;
else return NULL;
}
容易看出,查找成功时的平均查找长度为:ASL= :(i+1)/n=(n+1)/2。
虽然单链表中的结点是按从小到大的顺序排列,但结点没有序号的概念,查找结点时只能从头指针开始逐步搜索,故不能用折半查找。
3.采用二叉链表存储二叉排序,根结点为t,算法实现如下:
int count (BsTree*t, BsTree *p)
//求指定结点p在以*t为根的二叉排序树中的层次
{ int level=0;
if(t){
level++;
while(t&&t->key! -p->key){
if(t->key<p->key) t=t->rchild;
else t=t->lchild;
level++;
)
if(!t) level=0; //结点p不在二叉树t中
}
return level;
}
4. int search(Stable L, KeyType key)
//在有序顺序表中顺序查找关键字为key的元素。
//若找到,返回该元素在表中的位置,否则返回一1
{ for (i=0; i<L.length; i++)
if (L.elem [i]. key==key) return i;
else if (L.elem[i]. key>key) return -l;
return -l;
}
顺序查找的判定树如图9-1所示。
比较次数的期望值:(1+2+ .n/n=(n+1)/2
5.以中间的关键字为根结点,按二分法生成二叉排序
树既有平衡性又简单,算法如下:
voidbuild (BsTree **t,int low,int high, int*k)
//low和high分别为关键字组k的下界和上界,初始值分别为O,n-l
{ int m;
if (low>high) *kt=NULL;
else{
m= (low+high) /2;
*t= (BsTree*)malloc( sizeof (BsTree));
(*t)一>key=k[m];
build( (*t) ->lchild, low, m-l,k);
build( (*t) ->rchild, m+l, high,k);
}
}
build(&t,O,n-l,k); //调用建立函数
对所给关键字序列,根据上述算法可得二叉排序树如图9-2所示。
6.二叉树是二叉排序树的条件是,左右分支都是二叉排序树,且根结点的值大于左分支中结点的所有值(也即大于左分支的最大值)而小于右分支中结点的所有值(也即小于右分支的最小值)。
具体实现算法如下:
int isbisorttree (BsTree *t)
( if( !t) return 1;
if (isbisorttree (t->lchild) &&isbisorttree (t->rchild))(
m=max( t->lchild); n=min( t->rchild);
return(t->key>m&&t->key<=n);
}
else return 0;
}
int max (BsTree *p) //求二叉排序树左分支中结点的最大值
{ if( !p) return -Maxint; //最小的整数
while (p->rchild) p=p->rchild;
return p->key;
}
int min (BsTree *p) //求二叉排序树右分支中结点的最小值
( if(!p) return Maxint; //最大的整数
while (p->lchild) p=p->lchild;
return p->key;
}
}
7.算法的基本思想是在p的左子树找一个最大值结点s,用s替代p。
void deltree (BsTree *p, BsTree*f)
{ if(! p->lchild) s=p->rchild;
else if(!p->rchild) s=p->lchild;
else{
q=p; s=q->lchild;
while(s->rchild)f
q=s; s=s->rchild;)
if(q!=p){
q->rchild=s->lchild; s->lchild=p->lchild;}
}
if (p==f->lchild) f->lchild=s;
else f->rchild=s;
free (p);
}
8.设散列表为HT[O]~HT[MaxSize-1],每个数组元素的类型为字符串,算法描述如下: #define MaxSize=100
typedef DataType char[50]j
int h(DataType k)
{ return k[0] -'a'+1;)
Hashout( DataType *HT)
{ int i,j;
for(i=1;i<=26;i++){
j=0;
while (HT[j]){ //HT[j]不空
if(h(HT[j])==i) printf("%C\t", HT[j]);
j= (j+l)%MaxSize;
}
printf("\n");
}}。