数据结构的试题有答案讲解 下载本文

第一章绪论 一、单选题

1. 一个数组元素a[i]与 A 2.对于两个函数,若函数名相同,但只是A *(a+i) B a+i C *a+i 的表示等价。D &a+i

C 不同则不是重载函数。

3.A 参数类型 B 参数个数 C 函数类型B 若需要利用形参直接访问实参,则应把形参变量说明为 参数。 4.A

下面程序段的复杂度为指针 B 引用 C 值 C 。 for(int i=0;i

5. for(int i=1;i<=n;i++) 执行下面程序段时,执行S语句的次数为

D 。 S;

for(int j=1; j<=i;j++) A n2 B n2/2 C n(n+1) D n(n+1)/2 6. 下面算法的时间复杂度为 B 。 if(n==0||n==1) return 1; int f(unsigned int n){

Else return n*f(n-1); }

A O(1) B O(n) C O(n2) D O(n!) 二、填空题

1.数据的逻辑结构被除数分为 集合结构 、 线性结构 、 树型结构 和 图形结构 四种。

2.数据的存储结构被分为 顺序结构 、 链接结构 、 索引结构 和 散列结构 四种。

3.在线性结构、树型结构和图形结构中,前驱和后继结点之间分别存在着 1对1 、 1对N 和 M对N 的关系。 4.5.一种抽象数据类型包括当一个形参类型的长度较大时,应最好说明为 数据 和 操作 两个部分。 引用 ,以节省参数值的传输时间和存储参数的空间。 6.当需要用一个形参访问对应的实参时,则该形参应说明为 引用 。

7.在函数中对引用形参的修改就是对相应 实参 的修改,对 值(或赋值)形参的修改只局限在该函数的内部,不会反映到对应的实参上。

8.iostream.h 当需要进行标准头文件,I/O当需要进行文件操作时,则应在程序文件中包含I/O操作时,则应在 程序文件中包含 fstream.h 头文件。

9.rand()! 在包含有10.一个记录能够产生 stdlib.h r理论上占有的存储空间的大小等于所有域0-20头文之间的一个随机数。件的程序文件中

,使用 的 长度之和 ,实际上占有的存储空间的大小即记录长度为 sizeof(r) 。

11.sizeof(a) 一个数组,下标为a所占有的存储空间的大小即数组长度为i的元数a[i]的存储地址为 a+1 ,或 者为 (char*)a+i*sizeof(a[i]) 。

12.函数重载要求 参数类型 、 参数个数 或 排列顺序 有所不同。

13.对于双目操作符,其重载函数带有 2 个参数,其中至少有一个为 用户自定义的类型。

14.若对象ra和rb中至少有一个属于用户定义的类型,则执行ra==rb时,需要调用 等于

号(==) 重载函数,该函数第一个参数应与 ra ,的类型相同,第二个参数应与rb 的类型相同。

15.从一维数组a[n]中顺序查找出一个最大值元素的时间复杂度为 O(n) ,输出一个二维数组b[m][n]中所有元素值的时间复杂度为 O(m*n) 。 16.在下面程序段中,s=s+p语句的执行次数为 n ,p*=j

1/7

语句的执行次数为n(n+1)/2,该程序段的时间复杂度为

O(n2) 。

while(++i<=n){ int i=0,s=0;

int p=1;

for(int j=1;j<=i;j++) P*=j; 17.一个算法的时间复杂度为}

s=s+p; (3n2+2nlog2n+4n-7)/(5n),其数量级表示为 O(n) 。

18.从一个数组a[7]中顺序查找元素时,假定查找第一个元素a[0]的概率为1/3,查找第二个元素a[1]的概率为1/4,查找其余元素的概率均相同,则在查找成功时同元素的平均比较次数为 35/12 。 三、应用题

1.设计二次多项式ax2+bx+c的一种抽象数据类型,假定起名为QIAdratic,该类型的数据部分分为三个系数项a、b和c,操作部分为:(请写出下面每一个操作的具体实现)。 ⑴ 初始化数据成员ab和c(假定用记录类型Quadratie定义成员),每个数据成员的默认值为0。

cc=0);

Quadratic InitQuadratic(float aa=0,float bb=0,float 解 {

Quadratic InitQuadratic(float aa,float bb,float cc) q.a=aa; Quadratic q; q.b=bb; q.c=cc; return q; }

⑵ 做两个多项式加法,即使对应的系数相加,并返回相加的结果。

Quadratic Add(Quadratic q1,Quadratic q2); 解:

Quadratic Add(Quadratic q1,Quadratic q2); Quadratic q; {

q.a=q1.a+q2.a; q.b=q1.b+q2.b; q.c=q1.c+q2.c; return q; }

⑶ 根据给定x的值计算多项式的值。 float Eval(Quadratic q,float x); 解:

float Eval(Quadratic q,float x) return(q.a*x*x+q.b*x+q.c);

{

⑷ 计算方程ax2+bx+c=0的两个实数根,对于有实根、无实根和不是实根方程(即a==0)这三种情况要返回不同的整数值,以便于工作调用函数做不同的处理。 int Root(Quadratic q,float& r1,float& r2); 解:

int Root(Quadratic q,float& r1,float& r2) if(q.a==0)return -1;

{

float x=q.b*q.b-4*q.a*q.c; if(x>=0){

r1=(float)(-q.b+sqrt(x))/(2*q.a); r2=(float)(-q.b-sqrt(x))/(2*q.a); } return 1; return 0;

else

}

⑸ 按照ax**2+bx+c的格式(x2用x**2表示)输出二次多项式,在输出时要注意去掉系数为0的项,并且当b和c的值为负时,其前不能出现加号。void Print(Quadratic q)

解:void Print(Quadratic q) {

if(q.a) cout<0)

if(q.b)

cout<<\ else

cout<0)

if(q.c) cout<<\ else

cout<

⑴ int prime(int n) int i=1;

{

int x=(int)sqrt(n); while(++i<=x)

if(i>x) return 1; if(n%i==0)break; else return 0; }

解: 判断n是否是一个素数,若是则返回数值1,否则

返回0。该算法的时间复杂度为 O(n1/2

)。 ⑵ int sum1(int n) {

int p=1,s=0;

{

for(int i=1;i<=n;i++) p*=i; s+=p; }

return s; } 解:

计算∑i!(上标为n,下标为i=1)的值,其时间的复杂度为O(n)。

⑶ int sum2(int n) {

int s=0;

for(int i=1;i<=n;i++){ int p=1;

for(int j=1;j<=i;j++) s+=p; p*=j; }

return s; } 解:

计算∑i!的值,时间复杂度为O(n2) ⑷ int fun(int n) {

int i=1,s=1; s+=++i;

while(s

return i; }

解: 求出满足不等式1+2+3...+i≥n的最小i值, 间复杂度为O(n1/2

其时

)。

⑸ void UseFile(ifstream& inp,int c[10])

//假定inp所对应的文件中保存有n个整数 for(int i=0;i<10;i++) {

c[i]=0; i=x; while(inp>>x){ int x;

c[i]++; } } 解:利用数组c[10]中的每个元素c[i]对应统计出inp所联系的整数文件中个位值同为i的整数个数,时间复杂度为O(n)

⑹ void mtable(int n) {

for(int i=1;i<=n;i++){ cout<

解: 打印出一个具有n行的乘法表,第i行(1≤i≤n)中有n-i+1个乘法项,每个乘法项为i与j(i≤j≤n)的乘积,时间复杂度为O(n2)。

⑺ void cmatrix(int a[M][N],int d) //M 和N为全局整型常量 for(int i=0;i

for(int j=0;j

使数组a[M][N]中的每一个元素均详细以d的值,时间复杂度为O(M*N)

⑻ void matrimult(int a[M][N],int b[N][L],int c[M][L]) {

int i,j,k;

for(i=0;i

for(j=0;j

} c[i][j]+=a[i][k]*b[k][j]; 解:

矩阵相乘,即a[M][N]×b[N][L]→c[M][L],时间复杂度为O(M×N?L)。 第二章线性表 一、(答案)

⑴解:(79,62,34,57,26,48) ⑵解:(26,34,48,57,62,79) ⑶解:(48,56,57,62,79,34) ⑷解:(56,57,79,34)

⑸解:(26,34,39,48,57,62)

二、对于List类型的线性表,编写出下列每个算法。 ⑴ 从线性表中删除具有最小值的元素并由函数返回,空

出的位置由最后一个元素填补,若

线性表为空则显示出错信息并退出运行。 解: ElemType DMValue(List&L)

//从线性表中删除具有最小值的元素并由函数返回,空出的位置

//由最后一个元素填补,若线性表为空则显示出错信息并退出运行 {

if(ListEmpty(L)){

cerr<<\ }

exit(1); ElemType x; int k=0;

x=L.list[0]; for(int i=1;i

if(y

⑵ 从线性表中删除第i个元素并由函数返回。 解:int Deletel(List& L,int i)

{

//从线性表中删除第i个元素并由函数返回 cerr<<\if(i<1||i>L.size){

exit(1); ElemType x; }

x=L.list[i-1];

L.list[j]=L.list[j+1]; for(int j=i-1;j

return x; ⑶ 向线性表中第i个元素位置插入一个元素。 解:void Inser1(List& L,int i,ElemType x)

//向线性表中第i个元素位置插入一个元素 {

if(i<1||i>L.size+1){

cerr<<\ }

exit(1); if(L.size==MaxSize) {

cerr<<\ exit(1); for(int j=L.size-1;j>i-1;j--) }

L.list[j+1]=L.list[j]; L.list[i-1]=x; L.size++; }

⑷ 从线性表中删除具有给定值x的所有元素。 解:void Delete2(List& L,ElemType x)

{

//从线性表中删除具有给定值x的所有元素 int i=0;

if(L.list[i]==x){

while(i

3/7

L.list[j-1]=L.list[j]; } L.size--; i++; else }

4.对于结点类型为LNode的单链接表,编写出下列每个算法。

⑴ 将一个单链接表按逆序链接,即若原单链表中存储元素的次序为a1,a2,...,an,则

逆序链接后变为an,an-1,...a1。 解:void Contrary(LNode*&HL)

{

//将一个单多办实事有按逆序链接 LNode*p=HL;//p指向待逆序的第一个结点,初始指向原表头结点 //HL 仍为逆序后的表头指针,禄始值为空HL=NULL;

{ //while(p!=NULL)

LNode*q=p; //q把原单链表中的结点依次进行逆序链接 p=p->next; //p指向待处理的结点

//将q结点插入到已陈序单链表的表头指向下一个待逆序的结点 HL=q; q->next=HL; } }

⑵ 删除单链表中的第i个结点。 解:void Delete1(LNode*&HL,int i) {

//删除单链表中的第i个结点 if(i<1||HL==NULL){

exit(1); cerr<<\ }

LNode*ap,*cp;

ap=NULL;cp=HL; //cp指向当前结点,ap指向其前驱结点

while(cp!=NULL) int j=1;

break; //cpif(j==i)

else{ // 继续向后寻找结点即为第 i个结点 j++; cp=cp->next; ap=cp;

}

if(cp==NULL){

excerr<<\ it(1); }

if(ap==NULL) HL=HL->next; ap->next=cp->next; else

delete cp; }

⑶ 从单链表中查找出所有元素的最大值,该值由函数返回,若单链表为空,则显示出错信息并停止运行。 解:ElemType MaxValue(LNode*HL)

//从单链表中查找出所有元素的最大值,该值由函数返回 {

if(HL==NULL){

cerr<<\ exit(1); }

ElemType max=HL->data; LNode*p=HL->next; if(maxdata) max=p->data; while(p!=NULL){

p=p->next; return max; }

}

⑷ 统计出单链表中结点的值等于给定值x的结点数。 解:int Count(LNode*HL,ElemType x)

//统计出单链表中结点的值等于给定值x的结点数 int n=0;

{

if(HL->data==x) n++; while(HL!=NULL){

}

HL=HL->next; return n; }

第三章 稀疏距阵和广义表 一、单选题

1.在稀疏矩阵的带行指针指向量的链接存储中,每个行单链表中的结点都具有相同的A 。

2.设一个具有A 行号 B t个非零元素的列号 C 元素值m*n 大小的稀疏矩阵采用顺D 地址

序存储,求其转置矩阵的普通转置算法的时间复杂度为 D 3.设一个广义表中结点的个数为A O(m) 。

B O(n) C O(n+t) n,则求广义表深度算法D O(n*t)

的时间复杂度为 B。

A O(1) B O(n) C O(n2) D O(log2n) 二、填空题

1.在一个稀疏矩阵中,每个非零元素所对应的三元组包括该元素的 行号 、 列号 、和元素值 。 2.在稀疏矩阵所对应的三元组线性表中,每个三元组元素按 行号 为主序、 列号 为辅助的次序排列。 3.在初始化一个稀疏矩阵的函数定义中,矩阵形参应说明为 引用 参数。

4.在稀疏矩阵的顺序存储中,利用一个数组来存储非零元素,该数组的长度应 大于等于 对应的三元线性表的长度。

5.在稀疏矩阵的带行指针向量的链接存储中,每个结点包含有 4 个域,在相应的十字链接存储中,每个结点包含有 5 个域。

6.在稀疏矩阵的十字链接存储中,每个结点的down指针域指向 行号 相同的下一个结点,right指针指向 列号 相同的下一个结点。

7.8.一个广义表中的元素为 单 元素和9.一个广义表的深度等于 表 元素两类。 10.在广义表的存储结构中,每个结点均包含有 括号 嵌套的最大层数。

在广义表的存储结构中,单元素结点与表元素结点有 3 个域。 一个域对应不同,各自分别为值 域和 子表指针域 。 11.若把整个广义表也看为一个表结点,则该结点的tag域的值为 true或1 、next域的值为 NULL或0 。 三、应用题

1. 已知一个稀疏矩阵如图3-11所示: 0 4 0 0 0 0 0

0 0 0 -3 0 0 1 8 0 0 0 0 0 0 0 0 0 5 0 0 0

4/7

0 -7 0 0 0 2 0 0 0 0 6 0 0 0

图3-11 具有6行×7列的一个稀疏矩阵 ⑴写出它的三元组线性表; 解:((1,2,4),(2,4,-3),(2,7,1),(3,1,8),(4,4,5),(5,,2,-7),(5,6,2),(6,4,6))

⑵给出它的顺序存储表示; 解:

下标 1 2 3 4 5 6 7 8 ... MaxTerms row(col(行号) 1 2 2 3 4 5 5 6 val(列号 ⑶给出它的转置矩阵的三元组线性表和顺序存储表示;元素值) 2 4 7 1 4 2 6 4 ) 4 -3 1 8 5 -7 2 6

解:

((1,3,8),(2,1,4),(2,5,-7),(4,2,-3),(4,4,5),(4,6,6),(6,5,2),(7,2,1))

解:下标 1 2 3 4 5 6 7 row(col(行号) 1 2 val(列号3.画出下列每个广义表的带表头附加结点的链接存储结元素值) 3 1 ) 8 4

构图并分别计算出它们的长度和深度。 ⑴ A=(()) ⑵ B=(a,b,c) ⑶ C=(a,(b,(c))) ⑷ D=((a,b),(c,d)) ⑸ E=(a,(b,(c,d)),(e))

⑹ F=((a,(b,(),c),((d)),e)))

解:每小题的长度和深度如下表示。

题号 1 2 3 4 5 6 长度 1 3 2 2 3 1 深度 2 1 3 2 3 4 第四章 栈和队列 一、应用题

1.MS[MaxSize]设用第二建立三个链接堆栈,章定义的类型为其中前三个元素的AlinkList的一维数next组域用来存储三个栈顶指针,从下标为3的元素起作为空闲元素提供给三个栈共同使用,试编写一个算法把从键盘上输入的n个整数按照下列条件分别进入不同的栈: ⑴若输入的整数x小于60,则进第一个栈;

⑵若输入的整数x大于等于60同时小于100,则进第二个栈;

⑶若输入的整数大于100,则进第三个栈。 解:

void MoreStack(ALinkList MS,int n)

//把从键盘上输入的n个整数按不同条件分别进入到三个不同的链接栈中 if(n>MaxSize-3){

{

cerr<<\ exit(1); 存储空间不足!\ }

for(i=0;i<3;i++)

int i,x,av;

av=3;//avMS[i].next=0//置空栈,即给三个栈顶指针赋 cout<<\ for(i=0;i

输入指向可利用元素的下标,赋初值为\个整数:\3 0 // cin>>x;

从键盘读入一个整数并把它赋给av元素的值域 //MS[av].data=x;

按条件把av元素压入不同的栈,即链接到相应栈

的栈顶

if(x<60){

Ms[av].next=MS[0].next; }

MS[0].next=av; else if(x>=60&&x<=100){ MS[av].next=MS[1].next; } MS[1].next=av; else{

MS[av].next=MS[2].next; }

MS[2].next=av; //使av指向下一个可利用元素 } av++; 2.编写一个程序,首先调用上题算法,然后分别打印出每}

个栈中的内容。 解:

#include const int MaxSize=50;

#include // typedef int ElemType; 要至少定义为比输入的整数个数大3 struct ALNode{ ElemType data; typedef ALNode ALinkList[MaxSize]; };

int next; {//void MoreStack(ALinkList MS,int n) }

函数体在此省略 void main() {

ALinkList a; cout<<\int n;

从键盘输入的整数个数(1 cin>>n;

~47):\ for(int i=0;i<3;i++)

MoreStack(a,n); int j=a[i].next; { //依次将每个栈中的元素全部出栈并打印出来 while(j!=0){

cout<

cout<

一次输入和运行结果如下:

从键盘上输入的整数个数为(1 输入12个整数:

~47):12 38 64 97 120 78 33 45 214 88 25 143 60 25 45 33 38 60 88 78 97 64 3. 3+4/(25-(6+15))*8@ 已知一个中缀算术表达式为:143 214 120

⑴写出对应的后缀算术表达式。 解:3 4 25 6 15 + - /8 * + @

⑵画出在转换成后缀表达式的过程中运算符栈的变化。 解:略

4.已知一个后缀算术表达式为:

5/7

24 8 + 3 * 4 10 7 - * / @ ⑴写出对应的中缀算术表达式。 解: (24+8)*3/(4*(10-7))

⑵画出在进行后缀算术表达式求值的过程中数值栈的变化。 解:略

5.编写把十进制正整数转换为十六进制数输出的算法。 解: void Transform(long num)

// {

把一个正整数num转为一个十六进制数输出 Stack a; while(num!=0){ InitStack(a); int k=num % 16; Push(a,k); }

num/=16; while(!StackEmpty(a)) int X=Pop(a); {

if(x<10) cout<

{

cass 10: break; cout<<'A'; cass 11: cout<<'B'; cass 12: break; cout<<'C'; cass 13: break; cout<<'D'; cass 14: break; cout<<'E'; cass 15: break; } cout<<'F'; } }

cout<

S进制(2≤S≤9)数输出的递归算法,然后若把425转换为六进制数,画出每次递归调用前和返回后系统栈的状态。 解:

只给出递归算法,画图从略。

void Transform(long num,int s)

//把十进制正整数转换为S进制数的递归算法 {

if(num!=0){ int k;

k=num%S;

cout<

(Fibonacci)数列的定义为:它的第一项和第二项均为1,以后各项为其前两项之和。

若裴波那契数列中的第n项用Fid(n)表示,则计算公式为: 1 (n=1或 试编写计算Fib(n)= Fib(n-1)+Fib(n-2) Fib(n)的递归算法和非递归算法,(n>=2) n=2) 并分析它们的时间复杂度和空间复杂度。 解:

递归算法为: {

long Fib(int n)

return 1; if(n==1||n==2) //终止递归条件 else

return Fib(n-1)+Fib(n-2); }

long Fib1(int n) 非递归算法为 {

int a,b,c;//C代表当前项,a和b分别代表当前项前面的第2项和第1项

a=b=1; // if(n==1||n==2) 给a和b赋初值1 else

return 1; for(int i=3;i<=n;i++){ c=a+b; // a=b;// }

b=c;//把当前项赋给前面第把前面第求出当前项1项赋给前面第

1项 2项 }

return c;//返回所求的第n项 递归算法时间复杂度O(2n)、空间复杂度O(n) 非递归算法时间复杂度O(n)、空间复杂度O(1) 第五章 树和二叉树 1.一、填空题对于一棵具有

n个结点的树,该树中所有结点的度数之和为 n-1 。

2.5 假定一棵三叉树的结点个数为3.在一棵高度为,最大深度为 50,则它的最小深度为 h50 的四叉树中,最多含有。

(4h-1)/3 结点。

4.在地棵三叉树中,度为3的结点数有2个,度为2的结点数有1个,度为1的结点数为2个,那么度为0的结点数有 6 个。

5.一棵深度为5的满二叉树中的结点数为 31 个,一棵深度为3的满四叉树中的结点数为21 个。

6.J)))假定一棵树的广义表示为,则树中所含的结点数为A(B(C 10 个,树的深度为,D(E,F,G), H(I4 个,,树的度为 3 。

7.J)))假定一棵树的广义表表示为6 ,则度为3,2,1,0的结点数分别为A(B(C,D(E 2 ,、F, 1 G)、, 1 H(I和, 8.J)))假定一棵树的广义表示为个。

A(B(C,D(E,F,G)9.在一棵二叉树中,,则结点H的双亲结点为假定双亲结点数为 B 个,孩子结点为,H(I,5个,单分支结点 I和J 。 数为6个,则叶子结点数为 6 个。

10.对于一棵二叉树,若一个结点的编号为i,则它的左孩子结点的编号为 2i ,右孩子结点的编号为 2i+1 ,双亲结点编号为 i/2 。

11.12.在一棵二叉树中,第5层上的结点数最多为 16 5 13.,最大深度为假定一棵二叉树的结点数为一棵二叉树的广义表表示为 18 。

18,则它的最小深度为。 a(b(e,d),e(f(,g))),则e结点的双亲结点为 a,左孩子结点为 f ,右孩子结点为 空 14.一棵二叉树的广义表表示为a(b(e,d),e(f(,g))),它含有

6/7

双亲结点 2 个,单分支结点 2 个,叶子结点 3 个。 15.16.对于一棵含有假一定一棵二叉树顺序存储在一维数组40个结点的理想平衡树,它的高度为a中,则a[i] 6 元素的左孩子元素为 a[2i] ,右

孩子元素为 a[2i+1] ,双亲元素(i-1)为 a[i/2] 。

17.假定一棵二叉树顺序存储在一维数组a中,但让编号为1的结点存入a[0]元素中,

让编号为2的结点存入a[1]元素中,其余类推,则编号为i结点的左孩子结点对应的

存储位置为 2i-1 ,若编号为i结点的存储位置用j表示,则其左孩子结点对应的存储位置为 2j+1 。

18.若对一棵二叉树从0开始进行结点编号,并按此编号把它顺序存储到一维数组a中,即编号为0的结点存储到a[0]中,其余类推,则a[i]元素的左孩子元素为 a[2i+1] ,右孩子元素为 a[2i+2] ,双亲元素(i->0)为 a[(i-1)/2] 。 19.对于一棵具有n个结点的二叉树,对应二叉链接表中指针总数为 2n 个,其中n-1 个用于指向孩子结点, n+1 个指针空闲着。

20.一棵二叉树广义表表示为a(b(d(,h)),c(e,f(g,i(k)))),该树的结点数为 10 个,深度为 5 。

21.在一棵高度为5的理想平衡树中,最少含有 16 个结点,最多含有 31 个结点。

22.在一棵高度为h的理想平衡树中,最少含有 2h-1 个结点,最多含有 2h-1个结点。

23.假定一棵二叉树广义表表示为a(b(c),d(e,f)),则对它进行的先序遍历结果为 a b c d e f,中序遍历结果为 c b a e d f,e f后序遍历结果为 c b e f d a,按层遍历结果为 a b d c 24.。a(b((e),c(f(h,i,j),g),d),假

定一棵普通树的广义表表示为f h i j g d,按层遍历结果为则先根遍历结果为 a b c d e f g h i j a b e c 。 二、应用题

1.已知一棵具有n个结点的完全二叉树被顺序存储于一维数组的A[1]~A[n]元素中,试编写一个算法打印出编号为i的结点的双亲和所有孩子。 解:

//void Request(int a[],int n,int i)

从数组A中打印出编号为i的结点的双亲和孩子 if(i>n){

{

cerr<<\\

编号为\的结点不存在! exit(1); cout<<\}

int j=i/2;

if(j>0)

//下标为j的结点是下标为i结点的双亲 else

cout<<\ cout<<\ if(2*i

树根结点没有双亲结点!\ cout<<\ cout<<\ }

else if(2*i==n){

cout<<\ cout<<\ } cout<<\else

2.编写一算法,求出一棵二叉树中所有结点数和叶子结}

点,假定分别用变参C1和C2统计所有结点数和叶子结

点数,初值均为0。 解:

//void Count(BTreeNode* BT {

分别统计出二叉树中所有结点数和叶子结点数,int& C1,int& C2)

if(BT!=NULL){

C1++;//统计所有结点

C2++; //if(BT->left==NULL&&BT->right==NULL) 统计叶子结点数 Count(BT->left,C1,C2); Count(BT->right,C1,C2); 12.}

} ?? 写出先根遍历得到的结点序列;对于图5-16所示的树: ? 写出按层遍历得到的结点序列;a b e c f g k d h I l m j 画出转换后得到的二叉树和二叉链表。a b c d e f g h I j k l m 解:略

第六章 二叉树的应用 一、单选题

1.C 从二叉搜索树中查找一个元素时,其时间复杂度大致为 2.A O(n) B O(1) C O(log2n) D O(n2) 。

B 向二叉搜索树中插入一个元素时,其时间复杂度大致为 。

3.根据A O(1) B O(log2n) n个元素建立一棵二叉搜索树时,C O(n) D O(nlog2n) 其时间复杂度大致为 D 。

4.A O(n) B O(log2n) C O(n2) D O(nlog2n) 从堆中删除一个元素的时间复杂度为5.A O(1) C 。 向堆中插入一个元素的时间复杂度为B O(n) C O(log2n) D O(nlog2n) A 。 6.权值分别为A O(log2n) 3,B O(n) 8,6,2,C O(1) D O(nlog2n)

5的叶子结点生成一棵哈夫曼树,它的带权路径长度为 D 。 A 24 B 48 C 72 D 53 二、填空题

1.在一棵二叉搜索树中,每个分支结点的左子树上所有结点的值一定 小于 该结点的值,右子树上所有结点的值一定 大于 该结点的值。

2.对一棵二叉搜索树进行中序遍历时,得到结点序列是一个 有序序列 。

3.从一棵二叉搜索树中查找一个元素时,若元素的值等于根结点的值,则表明 查找成功 ,若元素的值小于根结点的值,则继续向 左子树 查找,若元素的值大于根结点的值,则继续向 右子树 查找。

4.在一个堆的顺序存储中,若一个元素的下标为i,则它的左孩子元素的下标为 2i+1 ,右孩子元素的下标为 2i+2 5.在一个小根堆中,堆顶结点的值是所有结点中的。

最小值 ,在一个大根堆中,堆顶结点的值是所有结点中的 最大值 。

6.当向一个小根堆插入一个具有最小值的元素时,该元素需要逐层 向上 调整,直到被调整到 堆顶 位置为止。 7.当从一个小根堆中删除一个元素时,需要把 堆尾 元素填补到 堆顶 位置,然后再按条件把它逐层 向下 调整。 8.在哈夫曼编码中,若编码长度只允许小于等于4,则除了已对两个字符编码为0和10外,还可以最多对 4 个字符编码。 三、应用题

1.已知一组元素(46,25,78,62,12,37,70,29),画出按元素排列顺序输入生成的一棵二叉树。

2.72,12,49,28已知一棵二叉排序树如图结点,试分别画出每删除一个结点后得到的

6-11所示,若从中依次删除7/7

二叉排序树。

/ 28 12 \\ 49 \\ / \\ 16 34 72 30 / /

63 3.编写一个非递归算法,求出二叉排序树中的关键字最大的元素。

解:ElemType FindMax(BTreeNode* BST)

{

//从二叉排序树中返回关键字最大的元素 if(BST==NULL){

cerr<<\ exit(1); 不能在空树上查找最大值!\ BTreeNode* t=BST; }

while(t->right!=NULL) t=t->right; return t->data; 4.~7. } 解略