数据结构(C语言)第二版 第七章课后答案

数据结构(C语言)第二版 第七章课后答案

1.选择题

1~5 C D C A B
6~10 C C C D C
11~15 B C A D A

(1)对n 个元素的表做顺序查找时, 若查找每个元素的概率相同, 则平均查找长度为(C)。
A. (n-1)/2 B . n/2 C. (n+1)/2 D . n

总查找次数N=1+2+3+…+n=n(n+1)/2 ,则平均查找长度为 N/n=(n+1)/2 。

(2)适用于折半查找的表的存储方式及元素排列要求为(D) 。
A.链接方式存储,元素无序B.链接方式存储,元素有序
C.顺序方式存储,元素无序D .顺序方式存储,元素有序

折半查找要求线性表必须采用顺序存储结构, 且表中元素按关键字有序排列。

(3)如果要求一个线性表既能较快的查找,又能适应动态变化的要求,最好采用(C )查找法。
A .顺序查找B.折半查找
C.分块查找D.哈希查找

分块查找的优点是: 在表中插入和删除数据元素时, 只要找到该元素对应的块,就可以在该块内进行插入和删除运算。由于块内是无序的,故插入和删除比较容易,无需进行大量移动。如果线性表既要快速查找又经常动态变化,则可采用分块查找。

(4)折半查找有序表( 4 , 6, 10, 12, 20 , 30 , 50 , 70 , 88 , 100 )。若查找表中元素58,则它将依次与表中(A)比较大小,查找结果是失败。
A. 20 , 70, 30, 50 B . 30, 88, 70 , 50
C. 20 , 50 D. 30 , 88, 50

表中共10 个元素, 第一次取(1+10)/2 =5 ,与第五个元素20 比较, 58 大于20,再取(6+10)/2 =8 ,与第八个元素70 比较,依次类推再与30 、50 比较,最终查找失败。

(5)对22 个记录的有序表作折半查找,当查找失败时,至少需要比较(B)次关键字。
A. 3 B. 4 C . 5 D. 6

22 个记录的有序表,其折半查找的判定树深度为log2 22 + 1=5 ,且该判定树不是满二叉树,即查找失败时至多比较5 次,至少比较4 次。

(6)折半搜索与二叉排序树的时间性能(C) 。
A.相同B.完全不同
C.有时不相同D.数量级都是O(log 2n)

二叉排序树不一定是平衡树,它是只要求了左右子树与根结点存在大小关系,但是对左右子树之间没有层次差异的约束,因此通过二叉排序树进行查找不一定能够满足logn的。
只有是一棵平衡的二叉排序树时,其查找时间性能才和折半查找类似。

(7)分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是(C) 。
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)

A 、B、C、D 四个选项构造二叉排序树都以100 为根,易知A 、B、D 三个序列中100 的左孩子为80,如图1 ,而C 选项中100 的左孩子为60,如图2
在这里插入图片描述

(8)在平衡二叉树中插入一个结点后造成了不平衡,设最低的不平衡结点为A ,并已知A 的左孩子的平衡因子为0 右孩子的平衡因子为1,则应作(C)型调整以使其平衡。
A . LL B . LR C. RL D .RR

由题意可知,A的平衡因子为1,又由于A的右孩子的平衡因子为1,左孩子的平衡因子为0,由此可知,A的右孩子上仅有右孩子,A的左孩子上无左右孩子,在平衡二叉树中插入一个结点后造成不平衡,说明插入结点只能插在A的右孩子的左孩子上,这种情形属于在右子树的左子树上插入结点的情形,即RL型。

(9)下列关于m 阶B- 树的说法错误的是(D) 。
A .根结点至多有m 棵子树
B .所有叶子都在同一层次上
C.非叶结点至少有m/2 (m 为偶数)或m/2+1 ( m 为奇数)棵子树
D .根结点中的数据是有序的

一个M阶的B-树有以下基本性质:
根结点的子女数为[2, M];
每个非根节点所包含的关键字个数 j 满足:m/2 - 1 <= j <= m - 1;
除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:m/2<= k <= m ;
所有的叶子结点都位于同一层。

(10)下面关于B- 和B+ 树的叙述中,不正确的是(C) 。
A. B- 树和B+ 树都是平衡的多叉树
B. B- 树和B+ 树都可用于文件的索引结构
C. B- 树和B+ 树都能有效地支持顺序检索
D. B- 树和B+ 树都能有效地支持随机检索

B树只能支持随机检索,而B+树是有序的树,既能支持随机检索,又能支持顺序检索。

(11) m 阶B- 树是一棵(B) 。
A. m 叉排序树B . m 叉平衡排序树
C. m-1 叉平衡排序树D. m+1 叉平衡排序树

树叶中的关键字是有序的。

(12)下面关于哈希查找的说法,正确的是(C) 。
A.哈希函数构造的越复杂越好,因为这样随机性好,冲突小
B.除留余数法是所有哈希函数中最好的
C.不存在特别好与坏的哈希函数,要视情况而定
D.哈希表的平均查找长度有时也和记录总数有关

哈希函数都要视情况而选择

(13)下面关于哈希查找的说法,不正确的是(A) 。
A .采用链地址法处理冲突时,查找一个元素的时间是相同的
B .采用链地址法处理冲突时,若插入规定总是在链首,则插入任一个元素的时间是相同

C.用链地址法处理冲突,不会引起二次聚集现象
D .用链地址法处理冲突,适合表长不确定的情况

在同义词构成的单链表中,查找该单链表表中不同元素,所消耗的时间不同。

(14)设哈希表长为14,哈希函数是H(key)=key%11 ,表中已有数据的关键字为15,38,61, 84 共四个,现要将关键字为49 的元素加到表中,用二次探测法解决冲突,则放入的位置是(D) 。
A .3 B . 5 C.8D. 9

关键字15 放入位置4,关键字38 放入位置5,关键字61 放入位置6,关键字84
放入位置7 ,再添加关键字49,计算得到地址为5,冲突,用二次探测法解决冲突得到新地址为6 ,仍冲突,再用用二次探测法解决冲突,得到新地址为4,仍冲突,再用用二次探测法解决冲突,得到新地址为9,不冲突,即将关键字49 放入位置9。

(15)采用线性探测法处理冲突,可能要探测多个位置,在查找成功的情况下,所探测的这些位置上的关键字(A )。
A.不一定都是同义词B.一定都是同义词
C.一定都不是同义词D .都相同

所探测的这些关键字可能是在处理其它关键字冲突过程中放入该位置的。

2.应用题

(1)假定对有序表: ( 3, 4, 5, 7, 24 , 30, 42, 54 , 63, 72, 87, 95)进行折半查找,试回答下列问题:
①画出描述折半查找过程的判定树;
②若查找元素54,需依次与哪些元素比较?
③若查找元素90,需依次与哪些元素比较?
④假定每个元素的查找概率相等,求查找成功时的平均查找长度。

答案:

① 先画出判定树;
② 查找元素54,需依次与30, 63, 42, 54 元素比较;
③ 查找元素90,需依次与30, 63,87, 95 元素比较;
④ 求ASL 之前,需要统计每个元素的查找次数。判定树的前3 层共查找1+ 2 × 2+ 4×3=17 次;最后一层只有5个元素,5× 4=20 次,
所以ASL = ( 17+ 20 )/12= 37/12

(2)在一棵空的二叉排序树中依次插入关键字序列为12, 7, 17, 11, 16, 2, 13, 9,21, 4,请画出所得到的二叉排序树。
在这里插入图片描述
(3)已知如下所示长度为12 的表:( Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct,Nov, Dec )
①试按表中元素的顺序依次插入一棵初始为空的二叉排序树,画出插入完成之后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
②若对表中元素先进行排序构成有序表,求在等概率的情况下对此有序表进行折半查找时查找成功的平均查找长度。
③按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。

答案:在这里插入图片描述
在这里插入图片描述
(4)对图7.31 所示的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 ,需要依次与哪些关键字比较?
④假定每个关键字的查找概率相等,求查找成功时的平均查找长度。

① 画表如下:
在这里插入图片描述
在这里插入图片描述
② 查找63, 首先要与地址值为 H(63)=63%16=15 的关键字比较,即63 与31 比较 , 不匹配,然后用线性探测法,与32,17,46,47,63 相比,一共比较 6 次.
③ 查找60, 首先要与H(60)=60%16=12 号单元内容比较,因为12 号单元为空 ,所以应当只比较这一次即可。
④ ASL=(1× 6+ 2×1+ 5× 3+6×1 )/11= 29/11

(6)设有一组关键字( 9, 01 , 23, 14, 55, 20, 84, 27 ),采用哈希函数: H( key )=key %7 ,表长为10 ,用开放地址法的二次探测法处理冲突。要求:对该关键字序列构造哈希表,并计算查找成功的平均查找长度。
在这里插入图片描述
平均查找长度: ASL =( 1+1+1+2+3+4+1+2 ) /8=15/8

(7)设哈希函数H( K) =3 K mod 11 ,哈希地址空间为0~ 10 ,对关键字序列( 32 , 13,49 , 24 , 38, 21, 4, 12 ),按下述两种解决冲突的方法构造哈希表,并分别求出等概率下查找成功时和查找失败时的平均查找长度ASLsucc 和ASLunsucc 。
①线性探测法;
②链地址法。

在这里插入图片描述

3.算法设计题

(1)试写出折半查找的递归算法。

[ 算法描述]

int BinSrch ( rectype r[ ], int k, int low , int high){
	if (low ≤ high) {
		mid= (low+high)/2 ;
		if (r[mid].key==k)  return(mid);
		else if(r[mid].key>k) return (BinSrch( r,k,mid+1,high )) ;
		else return(BinSrch(r,k,low,mid-1));
	}
	else return( 0); 
}

(2 )试写一个判别给定二叉树是否为二叉排序树的算法。

[ 算法描述]

#define true 1
#define false 0
typedef struct node{
	datatype data;
	struct node *lchild,*rchild;
} *BTree;
void JudgeBST (BTree T,int flag ){ 
	if ( T!=null && flag ){ 
		Judgebst(T->lchild,flag); 	// 中序遍历左子树
		if (pre==null) pre=T; 			// 中序遍历的第一个结点不必判断
		else if(pre->data<T->data) pre=T;		 // 前驱指针指向当前结点
		else{flag=flase;} 						// 不是完全二叉树
		Judgebst(T->rchild,flag);			 // 中序遍历右子树
}

(3) 已知二叉排序树采用二叉链表存储结构, 根结点的指针为T , 链结点的结构为( lchild,data,rchild ),其中lchild , rchild 分别指向该结点左、右孩子的指针, data 域存放结点的数据信息。请写出递归算法, 从小到大输出二叉排序树中所有数据值>=x 的结点的数据。要求先找到第一个满足条件的结点后,再依次输出其他满足条件的结点。

[ 算法描述]

void Print (BSTree t){
	 if (t) {  Print ( t->lchild );
	 	cout<<t-data;
		print(t->rchild);   
	}
}
void PrintAllx(BSTree bst , datatype x){
	p=bst;
	if (p){
		while( p && p->data<x) p=p->rchild ;
		bst=p; 
		if(p){f=p; p=p->lchild;
			while (p && p->data>= x) {		// 沿左分枝向下,找第一个值<x 的结点
				f=p; p=p->lchild ; 
			} 		//f 是p 的双亲结点的指针,指向第一个值≥ x 的结点
			if(p)	 f->lchild=null; 		// 双亲与找到的第一个值<x 的结点断开
			Print(bst);						 // 输出以bst 为根的子树
		}
	}
}

(4)已知二叉树T 的结点形式为( lling,data,count,rlink ),在树中查找值为X 的结点,若找到,则记数( count )加1,否则,作为一个新结点插入树中,插入后仍为二叉排序树,写出其非递归算法。

[ 算法描述]

void SearchBST(BiTree &T,int target){
	BiTree s,q,f;
	s=new BiTNode;
	s->data.x=target;
	s->data.count=0;
	s->lchild=s->rchild=NULL;
	if(!T){ T=s; return ;}
	f=NULL;  q=T;
	while (q){
		if (q->data.x==target){
			q->data.count++;
			return ;
		} 
		f=q;
		if(q->data.x>target)  q=q->lchild;
		else  q=q->rchild;
	}
	if(f->data.x>target) f->lchild=s;
	else  f->rchild=s;
}

(5)假设一棵平衡二叉树的每个结点都表明了平衡因子b ,试设计一个算法,求平衡二叉树的高度。

[ 算法描述]

int Height(BSTree t){
	level=0;p=t;
	while(p){
		level++;
		if(p->bf<0) p=p->rchild;
		else p=p->lchild;
	}
	return (level);
}

(6)分别写出在散列表中插入和删除关键字为K 的一个记录的算法,设散列函数为H,解决冲突的方法为链地址法。

[ 算法描述]

bool insert(){
	int data;
	cin>>data;
	int ant=hash(data);
	LinkList p=HT[ant]; 	
	while(p->next){
		if(p->next->data==data)  return false;
		p=p->next;
	} 
	LinkList s;
	s=new LNode;
	s->data=data;
	s->next=p->next;
	p->next=s; 
	return true;
}
bool deletes(){
	int data;
	cin>>data;
	int ant=hash(data);
	LinkList p=HT[ant]; 
	while(p->next){
		if(p->next->data==data){
			LinkList s=p->next;
			p->next=s->next;
			delete s;
			return true;
		}
		p=p->next ;
	}
	return false;
}
1. 经过以下栈运算后,x的值是( )。 InitStack(s); Push(s,'a'); Push(s,'b'); Pop(s,x); Gettop(s,x); A. a B. b C. 1 D. 0 2.循环队列存储在数组A[0..m]中,则入队时的操作为( )。 A.rear=rear+1 B. rear=(rear+1) mod(m-1) C. rear=(rear+1)mod m D. rear=(rear+1) mod(m+1) 3. 栈和队列的共同点是( )。 A.都是先进先出 B.都是先进后出 C.只允许在端点处插入和删除元素 D.没有共同点 4. 若用一个大小为6的数组来实现循环队列,且当 rear 和 front 的值分别为 0 和 3。当从队列中删除一个元素,再插入两个元素后,rear 和 front 的值分别为:( )。 A.1 和 5 B.2 和 4 C.4 和 2 D.5 和 1 5. 程序填顺序循环队列的类型定义如下: typedef int ET; typedef struct{ ET *base; int Front; int Rear; int Size; }Queue; Queue Q; 队列 Q 是否“满”的条件判断为( C )。 A.(Q.Front+1)=Q.Rear B.Q.Front=(Q.Rear+1) C.Q.Front=(Q.Rear+1)% Q.size D.(Q.Front+1) % Q.Size=(Q.Rear+1)% Q.size 6. 若进栈序列为1,2,3,4,进栈过程中可以出栈,则( )不可能是一个出栈序列。 A.3,4,2,1 B.2,4,3,1 C.1,4,2,3 D.3,2,1,4 7. 向顺序存储的循环队列 Q 中插入新元素的过程分为三步: ( )。 A.进行队列是否空的判断,存入新元素,移动队尾指针 B.进行队列是否满的判断,移动队尾指针,存入新元素 C.进行队列是否空的判断,移动队尾指针,存入新元素 D.进行队列是否满的判断,存入新元素,移动队尾指针 8. 关于栈和队列,( )说法不妥。 A. 栈是后进先出表 B. 队列是先进先出表 C. 递归函数在执行时用到栈 D. 队列非常适用于表达式求值的算符优先法 9. 若用数组S[0..m]作为两个栈S1和S2的共同存储结构,对任何一个栈,只有当S全满时才不能作入栈操作。为这两个栈分配空间的最佳方案是( )。 A.S1的栈底位置为0,S2的栈底位置为m B.S1的栈底位置为0,S2的栈底位置为m/2 C.S1的栈底位置为1,S2的栈底位置为m D.S1的栈底位置为1,S2的栈底位置为m/2 二、程序填空题(没特别标注分数的空的为3分,共 23 分)。 1.下面的算法是将一个整数e压入堆栈S,请在空格处填上适当的语句实现该操作。 typedef struct{ int *base; int *top; int stacksize; }SqStack; int Push(SqStack S,int e) { if ( S.top- S.base>= S.stacksize ) { S.base=(int *) realloc(S.base,(S.stacksize+1)*sizeof(int)); if( !S.base ) { printf(“Not Enough Memory!\n”); return(0); } S.top= S.base+ S.stacksize ; S.stacksize= S.stacksize+1 ; } * S.top++=e ; return 1; } 2. 在表达式:6+5+3*7/(4+9/3-2)求值过程中,处理到2时刻,运算符栈的状态为: + / ( - (4分),操作数栈的内容为11,21,7,2(4分)。 3. 递调用时,处理参数及返回地址,要用一种称为 栈 的数据结构。 4. 设循环队列中数组的下标范围是1-n,其头尾指针分别为f和r,则其元素个数为_(r-f+n) mod n。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值