最新数据结构习题集答案解析--清华大学版
数据结构答案(清华大学出版)
若是N维数组,其中任一元素的地址该如何计算? 若是 维数组,其中任一元素的地址该如何计算? 维数组 低维优先的地址计算公式,该式称为n维数组的映像函数: 低维优先的地址计算公式,该式称为n维数组的映像函数: 优先的地址计算公式
n
0)+ Loc(j1,j2,…jn)=LOC(0,0, 0)+i =1 j )=LOC(0,0,…0)
a11 a12 … a1n ^
… …
am1 am2 … amn ^
^ 注:数组的运算参见下一节实例(稀疏矩阵的转置) 数组的运算参见下一节实例(稀疏矩阵的转置)
13
5.3 矩阵的压缩存储
讨论: 讨论: 1. 什么是压缩存储? 什么是压缩存储? 若多个数据元素的值都相同 则只分配一个元素值的存储空间, 值都相同, 若多个数据元素的值都相同,则只分配一个元素值的存储空间, 且零元素不占存储空间。 且零元素不占存储空间。 2. 所有二维数组(矩阵)都能压缩吗? 所有二维数组(矩阵)都能压缩吗? 未必,要看矩阵是否具备以上压缩条件。 未必,要看矩阵是否具备以上压缩条件。 3. 什么样的矩阵具备以上压缩条件? 什么样的矩阵具备以上压缩条件? 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩 一些特殊矩阵, 对称矩阵,对角矩阵,三角矩阵, 阵等。 阵等。 4. 什么叫稀疏矩阵? 什么叫稀疏矩阵 稀疏矩阵? 矩阵中非零元素的个数较少(一般小于5% 5%) 矩阵中非零元素的个数较少(一般小于5%) 重点介绍稀疏矩阵的压缩和相应的操作。 重点介绍稀疏矩阵的压缩和相应的操作。
8
无论规定行优先或列优先, 无论规定行优先或列优先,只要知道以下三要素便可随时求出 任一元素的地址(这样数组中的任一元素便可以随机存取! 任一元素的地址(这样数组中的任一元素便可以随机存取!): ①开始结点的存放地址(即基地址) 开始结点的存放地址(即基地址) 维数和每维的上、下界; ②维数和每维的上、下界; ac1,c2 … ac1,d2 ③每个数组元素所占用的单元数 Amn= … aij … ad1,c2 … ad1,d2 则行优先存储时的地址公式为: 行优先存储时的地址公式为: 存储时的地址公式为 LOC(aij)=LOC(ac1,c2)+[(i-c1)*(d2-c2+1)+j-c2)]*L , aij之前的 数组基址 a 本行前面的
数据结构(C语言版清华大学出版社)-章课后部分答案
第八章选择题1. C2.A3.B4.C5.D6.B7.B8.A9.D 10.D 11.C 12.C填空题1.n、n+12. 43.8.25( 折半查找所在块 )4.左子树、右子树5.266.顺序、(n+1)/2、O(log2n)7.m-1、[m/2]-18.直接定址应用题1.进行折半查找时,判定树是唯一的,折半查找过程是走了一条从根节点到末端节点的路径,所以其最大查找长度为判定树深度[log2n]+1.其平均查找长度约为[log2n+1]-1.在二叉排序树上查找时,其最大查找长度也是与二叉树的深度相关,但是含有n个节点的二叉排序树不是唯一的,当对n个元素的有序序列构造一棵二叉排序树时,得到的二叉排序树的深度也为n,在该二叉树上查找就演变成顺序查找,此时的最大查找长度为n;在随机情况下二叉排序树的平均查找长度为1+4log2n。
因此就查找效率而言,二分查找的效率优于二叉排序树查找,但是二叉排序树便于插入和删除,在该方面性能更优。
3. 评价哈希函数优劣的因素有:能否将关键字均匀的映射到哈希表中,有无好的处理冲突的方法,哈希函数的计算是否简单等。
冲突的概念:若两个不同的关键字Ki和Kj,其对应的哈希地址Hash(Ki) =Hash(Kj),则称为地址冲突,称Ki和K,j为同义词。
(1)开放定址法(2)重哈希法(3)链接地址法4.(1)构造的二叉排序树,如图(2)中序遍历结果如下:10 12 15 20 24 28 30 35 46 50 55 68(4)平均查找长度如下:ASLsucc = (1x1+2x2+3x3+4x3+5x3)/12 = 41/128.哈希地址如下:H(35) = 35%11 = 2H(67) = 67%11 = 1H(42) = 42%11 = 9H(21) = 21%11 = 10H(29) = 29%11 = 7H(86) = 86%11 = 9H(95) = 95%11 = 7H(47) = 47%11 = 3H(50) = 50%11 = 6H(36) = 36%11 = 3H(91) = 91%11 = 3第九章选择题1. D2.C3.B4.D5.C6.B7.A8.A9.D 10.D填空题1.插入排序、交换排序、选择排序、归并排序2.移动(或者交换)3.归并排序、快速排序、堆排序4.保存当前要插入的记录,可以省去在查找插入位置时的对是否出界的判断5.O(n)、O(log2n)6.直接插入排序或者改进了的冒泡排序、快速排序7.Log2n、n8.完全二叉树、n/29.1510.{12 38 25 35 50 74 63 90}应用题11.(1)Shell排序(步长为5 3 1)每趟的排序结果初始序列为100 87 52 61 27 170 37 45 61 118 14 88 32步长为5的排序14 37 32 61 27 100 87 45 61 118 170 88 52步长为3的排序结果14 27 32 52 37 61 61 45 88 87 170 100 118步长为1的排序结果14 27 32 37 45 52 61 61 87 88 100 118最后结果14 27 32 37 45 52 61 61 87 88 100 118 170(2)快速排序每趟的排序结果如图初始序列100 87 52 61 27 170 37 45 61 118 14 88 32第一趟排序[32 87 52 61 27 88 37 45 61 14]100[118 170]第二趟排序[14 27]32[61 52 88 37 45 61 87]100 118[170]第三趟排序14[27]32[45 52 37]61[88 61 87]100 118[170]第四趟排序14[27]32[37]45[52]61[87 61]88 100 118[170]第五趟排序14[27]32[37]45[52]61[87 61]88 100 118[170]最后结果14[27]32[37]45[52]61[61]87 88 100 118[170](3)二路归并排序每趟的排序结果初始序列[100][87][52][61][27][170][37][45][61][118][14][88][32]第一趟归并[87 100][52 61][27 170][37 45][61 118][14 88][32]第二趟归并[52 61 87 100][27 37 45 170][14 61 88 118][32]第三趟归并排序[27 37 45 52 61 87 100 170][14 32 61 88 118]第四趟归并排序[14 27 32 37 45 52 61 61 87 88 100 118 170]最后结果14 27 32 37 45 52 61 61 87 88 100 118 17012.采用快速排序时,第一趟排序过程中的数据移动如图:算法设计题1.分析:为讨论方便,待排序记录的定义为(后面各算法都采用此定义):#define MAXSIZE 100 /* 顺序表的最大长度,假定顺序表的长度为100 */ typedef int KeyType; /* 假定关键字类型为整数类型 */typedef struct {KeyType key; /* 关键字项 */OtherType other; /* 其他项 */}DataType; /* 数据元素类型 */typedef struct {DataType R[MAXSIZE+1]; /* R[0]闲置或者充当哨站 */int length; /* 顺序表长度 */}sqList; /* 顺序表类型 */设n个整数存储在R[1..n]中,因为前n-2个元素有序,若采用直接插入算法,共要比较和移动n-2次,如果最后两个元素做一个批处理,那么比较次数和移动次数将大大减小。
清华大学出版社数据结构(C++版)(第2版)课后习题答案最全整理
清华大学出版社数据结构(C++版)(第2版)课后习题答案最全整理第1 章绪论课后习题讲解1. 填空⑴()是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
【解答】数据元素⑵()是数据的最小单位,()是讨论数据结构时涉及的最小数据单位。
【解答】数据项,数据元素【分析】数据结构指的是数据元素以及数据元素之间的关系。
⑶从逻辑关系上讲,数据结构主要分为()、()、()和()。
【解答】集合,线性结构,树结构,图结构⑷数据的存储结构主要有()和()两种基本方法,不论哪种存储结构,都要存储两方面的内容:()和()。
【解答】顺序存储结构,链接存储结构,数据元素,数据元素之间的关系⑸算法具有五个特性,分别是()、()、()、()、()。
【解答】有零个或多个输入,有一个或多个输出,有穷性,确定性,可行性⑹算法的描述方法通常有()、()、()和()四种,其中,()被称为算法语言。
【解答】自然语言,程序设计语言,流程图,伪代码,伪代码⑺在一般情况下,一个算法的时间复杂度是()的函数。
【解答】问题规模⑻设待处理问题的规模为n,若一个算法的时间复杂度为一个常数,则表示成数量级的形式为(),若为n*log25n,则表示成数量级的形式为()。
【解答】Ο(1),Ο(nlog2n)【分析】用大O记号表示算法的时间复杂度,需要将低次幂去掉,将最高次幂的系数去掉。
2. 选择题⑴顺序存储结构中数据元素之间的逻辑关系是由()表示的,链接存储结构中的数据元素之间的逻辑关系是由()表示的。
A 线性结构B 非线性结构C 存储位置D 指针【解答】C,D【分析】顺序存储结构就是用一维数组存储数据结构中的数据元素,其逻辑关系由存储位置(即元素在数组中的下标)表示;链接存储结构中一个数据元素对应链表中的一个结点,元素之间的逻辑关系由结点中的指针表示。
⑵假设有如下遗产继承规则:丈夫和妻子可以相互继承遗产;子女可以继承父亲或母亲的遗产;子女间不能相互继承。
清华数据结构习题集答案C语言版
清华数据结构习题集答案C语⾔版清华数据结构习题集答案(C 语⾔版严蔚敏)第1章绪论1.1 简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型。
解:数据是对客观事物的符号表⽰。
在计算机科学中是指所有能输⼊到计算机中并被计算机程序处理的符号的总称。
数据元素是数据的基本单位,在计算机程序中通常作为⼀个整体进⾏考虑和处理。
数据对象是性质相同的数据元素的集合,是数据的⼀个⼦集。
数据结构是相互之间存在⼀种或多种特定关系的数据元素的集合。
存储结构是数据结构在计算机中的表⽰。
数据类型是⼀个值的集合和定义在这个值集上的⼀组操作的总称。
抽象数据类型是指⼀个数学模型以及定义在该模型上的⼀组操作。
是对⼀般数据类型的扩展。
1.2 试描述数据结构和抽象数据类型的概念与程序设计语⾔中数据类型概念的区别。
解:抽象数据类型包含⼀般数据类型的概念,但含义⽐⼀般数据类型更⼴、更抽象。
⼀般数据类型由具体语⾔系统内部定义,直接提供给编程者定义⽤户数据,因此称它们为预定义数据类型。
抽象数据类型通常由编程者定义,包括定义它所使⽤的数据和在这些数据上所进⾏的操作。
在定义抽象数据类型中的数据部分和操作部分时,要求只定义到数据的逻辑结构和操作说明,不考虑数据的存储结构和操作的具体实现,这样抽象层次更⾼,更能为其他⽤户提供良好的使⽤接⼝。
1.3 设有数据结构(D,R),其中{}4,3,2,1d d d d D =,{}r R =,()()(){}4,3,3,2,2,1d d d d d d r =试按图论中图的画法惯例画出其逻辑结构图。
解:1.4 试仿照三元组的抽象数据类型分别写出抽象数据类型复数和有理数的定义(有理数是其分⼦、分母均为⾃然数且分母不为零的分数)。
解:ADT Complex{数据对象:D={r,i|r,i 为实数}数据关系:R={}基本操作:InitComplex(&C,re,im) 操作结果:构造⼀个复数C ,其实部和虚部分别为re 和imDestroyCmoplex(&C) 操作结果:销毁复数CGet(C,k,&e) 操作结果:⽤e 返回复数C 的第k 元的值Put(&C,k,e)操作结果:改变复数C的第k元的值为eIsAscending(C)操作结果:如果复数C的两个元素按升序排列,则返回1,否则返回0 IsDescending(C)操作结果:如果复数C的两个元素按降序排列,则返回1,否则返回0 Max(C,&e)操作结果:⽤e返回复数C的两个元素中值较⼤的⼀个Min(C,&e)操作结果:⽤e返回复数C的两个元素中值较⼩的⼀个}ADT ComplexADT RationalNumber{数据对象:D={s,m|s,m为⾃然数,且m不为0}数据关系:R={}基本操作:InitRationalNumber(&R,s,m)操作结果:构造⼀个有理数R,其分⼦和分母分别为s和m DestroyRationalNumber(&R)操作结果:销毁有理数RGet(R,k,&e)操作结果:⽤e返回有理数R的第k元的值Put(&R,k,e)操作结果:改变有理数R的第k元的值为eIsAscending(R)操作结果:若有理数R的两个元素按升序排列,则返回1,否则返回0 IsDescending(R)操作结果:若有理数R的两个元素按降序排列,则返回1,否则返回0 Max(R,&e)操作结果:⽤e返回有理数R的两个元素中值较⼤的⼀个Min(R,&e)操作结果:⽤e返回有理数R的两个元素中值较⼩的⼀个}ADT RationalNumber1.5 试画出与下列程序段等价的框图。
数据结构(C语言版)9-12章练习 答案 清华大学出版社
数据结构(C语言版)9-12章练习答案清华大学出版社9-12章数据结构作业答案第九章查找选择题1、对n个元素的表做顺序查找时,若查找每个元素的概率相同,则平均查找长度为( A )A.(n+1)/2 B. n/2 C. n D. [(1+n)*n ]/2 2. 下面关于二分查找的叙述正确的是 ( D )A. 表必须有序,表可以顺序方式存储,也可以链表方式存储B. 表必须有序且表中数据必须是整型,实型或字符型 C. 表必须有序,而且只能从小到大排列 D. 表必须有序,且表只能以顺序方式存储3. 二叉查找树的查找效率与二叉树的( (1)C)有关, 在 ((2)C )时其查找效率最低 (1): A. 高度 B. 结点的多少 C. 树型 D. 结点的位置(2): A. 结点太多 B. 完全二叉树 C. 呈单枝树 D. 结点太复杂。
4. 若采用链地址法构造散列表,散列函数为H(key)=key MOD 17,则需 ((1)A)个链表。
这些链的链首指针构成一个指针数组,数组的下标范围为 ((2)C) (1) A.17 B. 13 C. 16 D. 任意(2) A.0至17 B. 1至17 C. 0至16 D. 1至16判断题1.Hash表的平均查找长度与处理冲突的方法无关。
(错) 2. 若散列表的负载因子α<1,则可避免碰撞的产生。
(错)3. 就平均查找长度而言,分块查找最小,折半查找次之,顺序查找最大。
(错)填空题1. 在顺序表(8,11,15,19,25,26,30,33,42,48,50)中,用二分(折半)法查找关键码值20,需做的关键码比较次数为 4 .算法应用题1. 设有一组关键字{9,01,23,14,55,20,84,27},采用哈希函数:H(key)=key mod7 ,表长为10,用开放地址法的二次探测再散列方法Hi=(H(key)+di) mod 10解决冲突。
要求:对该关键字序列构造哈希表,并计算查找成功的平均查找长度。
数据结构(C 语言 清华出版社)习题答案
习题1参考答案一、单项选择题1. A2. C3. D4. B5. C、A6. C、B7. B8. D9. B 10. B二、填空题1.线性结构,非线性结构2.集合,线性,树,图3.一对一,一对多或多对多4. 时间,空间5. 前趋,一,后继,多6. 有多个7. 一对一,一对多,多对多8. O(2n)9. O(n)10. O(2n)11. O(log3n)12. 程序对于精心设计的典型合法数据输入能得出符合要求的结果。
13. 事后统计,事前估计三、算法设计题1. O(2n)2. O(2n)3. O(n3)4. O(n)5. O(n)习题2参考答案一、单项选择题1.A 2.A 3.D 4.C 5.D 6.A 7.B 8.B 9.C 10.A 11.D 12.B 13.C 14.B 15.C 16.C 17.B 18.D 19.C 20.A二、填空题1.线性2.n-i+1 3.相邻4.前移,前,后5.物理存储位置,链域的指针值6.前趋,后继7.顺序,链接8.一定,不一定9.线性,任何,栈顶,队尾,队头10.单链表,双链表,非循环链表,循环链表11.使空表和非空表统一;算法处理一致12.O(1),O(n)13.栈满,栈空,m,栈底,两个栈的栈顶在栈空间的某一位置相遇14.2、3;15.O(1)三、简答题1.头指针是指向链表中第一个结点(即表头结点)的指针;在表头结点之前附设的结点称为头结点;表头结点为链表中存储线性表中第一个数据元素的结点。
若链表中附设头结点,则不管线性表是否为空表,头指针均不为空,否则表示空表的链表的头指针为空。
2.线性表具有两种存储结构即顺序存储结构和链接存储结构。
线性表的顺序存储结构可以直接存取数据元素,方便灵活、效率高,但插入、删除操作时将会引起元素的大量移动,因而降低效率:而在链接存储结构中内存采用动态分配,利用率高,但需增设指示结点之间关系的指针域,存取数据元素不如顺序存储方便,但结点的插入、删除操作较简单。
数据结构习题集答案(c版)(清华大学 严蔚敏)
1.16void print_descending(int x,int y,int z)//按从大到小顺序输出三个数{scanf("%d,%d,%d",&x,&y,&z);if(x<y) x<->y; //<->为表示交换的双目运算符,以下同if(y<z) y<->z;if(x<y) x<->y; //冒泡排序printf("%d %d %d",x,y,z);}//print_descending1.17Status fib(int k,int m,int &f)//求k阶斐波那契序列的第m项的值f{int tempd;if(k<2||m<0) return ERROR;if(m<k-1) f=0;else if (m==k-1) f=1;else{for(i=0;i<=k-2;i++) temp=0;temp[k-1]=1; //初始化for(i=k;i<=m;i++) //求出序列第k至第m个元素的值{sum=0;for(j=i-k;j<i;j++) sum+=temp[j];temp=sum;}f=temp[m];}return OK;}//fib分析:通过保存已经计算出来的结果,此方法的时间复杂度仅为O(m^2).如果采用递归编程(大多数人都会首先想到递归方法),则时间复杂度将高达O(k^m).1.18typedef struct{char *sport;enum{male,female} gender;char schoolname; //校名为'A','B','C','D'或'E'char *result;int score;} resulttype;typedef struct{int malescore;int femalescore;int totalscore;} scoretype;void summary(resulttype result[ ])//求各校的男女总分和团体总分,假设结果已经储存在result[ ]数组中{scoretype score;i=0;while(result.sport!=NULL){switch(result.schoolname){case 'A':score[ 0 ].totalscore+=result.score;if(result.gender==0) score[ 0 ].malescore+=result.score;else score[ 0 ].femalescore+=result.score;break;case 'B':score.totalscore+=result.score;if(result.gender==0) score.malescore+=result.score;else score.femalescore+=result.score;break;……?……?……}i++;}for(i=0;i<5;i++){printf("School %d:\n",i);printf("Total score of male:%d\n",score.malescore);printf("Total score of female:%d\n",score.femalescore);printf("Total score of all:%d\n\n",score.totalscore);}}//summary1.19Status algo119(int a[ARRSIZE])//求i!*2^i序列的值且不超过maxint{last=1;for(i=1;i<=ARRSIZE;i++){a[i-1]=last*2*i;if((a[i-1]/last)!=(2*i)) reurn OVERFLOW;last=a[i-1];return OK;}}//algo119分析:当某一项的结果超过了maxint时,它除以前面一项的商会发生异常.1.20void polyvalue(){float ad;float *p=a;printf("Input number of terms:");scanf("%d",&n);printf("Input the %d coefficients from a0 to a%d:\n",n,n);for(i=0;i<=n;i++) scanf("%f",p++);printf("Input value of x:");scanf("%f",&x);p=a;xp=1;sum=0; //xp用于存放x的i次方for(i=0;i<=n;i++){sum+=xp*(*p++);xp*=x;}printf("Value is:%f",sum);}//polyvalue2.10Status DeleteK(SqList &a,int i,int k)//删除线性表a中第i个元素起的k个元素{if(i<1||k<0||i+k-1>a.length) return INFEASIBLE;for(count=1;i+count-1<=a.length-k;count++) //注意循环结束的条件a.elem[i+count-1]=a.elem[i+count+k-1];a.length-=k;return OK;}//DeleteK2.11Status Insert_SqList(SqList &va,int x)//把x插入递增有序表va中{if(va.length+1>va.listsize) return ERROR;va.length++;for(i=va.length-1;va.elem>x&&i>=0;i--)va.elem[i+1]=va.elem;va.elem[i+1]=x;return OK;}//Insert_SqList2.12int ListComp(SqList A,SqList B)//比较字符表A和B,并用返回值表示结果,值为正,表示A>B;值为负,表示A<B;值为零,表示A=B{for(i=1;A.elem||B.elem;i++)if(A.elem!=B.elem) return A.elem-B.elem;return 0;}//ListComp2.13LNode* Locate(LinkList L,int x)//链表上的元素查找,返回指针{for(p=l->next;p&&p->data!=x;p=p->next);return p;}//Locate2.14int Length(LinkList L)//求链表的长度{for(k=0,p=L;p->next;p=p->next,k++);return k;}//Length2.15void ListConcat(LinkList ha,LinkList hb,LinkList &hc)//把链表hb接在ha后面形成链表hc {hc=ha;p=ha;while(p->next) p=p->next;p->next=hb;}//ListConcat2.16见书后答案.2.17Status Insert(LinkList &L,int i,int b)//在无头结点链表L的第i个元素之前插入元素b {p=L;q=(LinkList*)malloc(sizeof(LNode));q.data=b;if(i==1){q.next=p;L=q; //插入在链表头部}else{while(--i>1) p=p->next;q->next=p->next;p->next=q; //插入在第i个元素的位置}}//Insert2.18Status Delete(LinkList &L,int i)//在无头结点链表L中删除第i个元素{if(i==1) L=L->next; //删除第一个元素else{p=L;while(--i>1) p=p->next;p->next=p->next->next; //删除第i个元素}}//Delete2.19Status Delete_Between(Linklist &L,int mink,int maxk)//删除元素递增排列的链表L中值大于mink且小于maxk的所有元素{p=L;while(p->next->data<=mink) p=p->next; //p是最后一个不大于mink的元素if(p->next) //如果还有比mink更大的元素{q=p->next;while(q->data<maxk) q=q->next; //q是第一个不小于maxk的元素p->next=q;}}//Delete_Between2.20Status Delete_Equal(Linklist &L)//删除元素递增排列的链表L中所有值相同的元素{p=L->next;q=p->next; //p,q指向相邻两元素while(p->next){if(p->data!=q->data){p=p->next;q=p->next; //当相邻两元素不相等时,p,q都向后推一步}else{while(q->data==p->data){free(q);q=q->next;}p->next=q;p=q;q=p->next; //当相邻元素相等时删除多余元素}//else}//while}//Delete_Equal2.21void reverse(SqList &A)//顺序表的就地逆置{for(i=1,j=A.length;i<j;i++,j--)A.elem<->A.elem[j];}//reverse2.22void LinkList_reverse(Linklist &L)//链表的就地逆置;为简化算法,假设表长大于2{p=L->next;q=p->next;s=q->next;p->next=NULL;while(s->next){q->next=p;p=q;q=s;s=s->next; //把L的元素逐个插入新表表头}q->next=p;s->next=q;L->next=s;}//LinkList_reverse分析:本算法的思想是,逐个地把L的当前元素q插入新的链表头部,p为新表表头.2.23void merge1(LinkList &A,LinkList &B,LinkList &C)//把链表A和B合并为C,A和B的元素间隔排列,且使用原存储空间{p=A->next;q=B->next;C=A;while(p&&q){s=p->next;p->next=q; //将B的元素插入if(s){t=q->next;q->next=s; //如A非空,将A的元素插入}p=s;q=t;}//while}//merge12.24void reverse_merge(LinkList &A,LinkList &B,LinkList &C)//把元素递增排列的链表A和B合并为C,且C中元素递减排列,使用原空间{pa=A->next;pb=B->next;pre=NULL; //pa和pb分别指向A,B的当前元素while(pa||pb){if(pa->data<pb->data||!pb){pc=pa;q=pa->next;pa->next=pre;pa=q; //将A的元素插入新表}else{pc=pb;q=pb->next;pb->next=pre;pb=q; //将B的元素插入新表}pre=pc;}C=A;A->next=pc; //构造新表头}//reverse_merge分析:本算法的思想是,按从小到大的顺序依次把A和B的元素插入新表的头部pc处,最后处理A或B的剩余元素.2.25void SqList_Intersect(SqList A,SqList B,SqList &C)//求元素递增排列的线性表A和B的元素的交集并存入C中{i=1;j=1;k=0;while(A.elem&&B.elem[j]){if(A.elem<B.elem[j]) i++;if(A.elem>B.elem[j]) j++;if(A.elem==B.elem[j]){C.elem[++k]=A.elem; //当发现了一个在A,B中都存在的元素,i++;j++; //就添加到C中}}//while}//SqList_Intersect2.26void LinkList_Intersect(LinkList A,LinkList B,LinkList &C)//在链表结构上重做上题{p=A->next;q=B->next;pc=(LNode*)malloc(sizeof(LNode));while(p&&q){if(p->data<q->data) p=p->next;else if(p->data>q->data) q=q->next;else{s=(LNode*)malloc(sizeof(LNode));s->data=p->data;pc->next=s;pc=s;p=p->next;q=q->next;}}//whileC=pc;}//LinkList_Intersect2.27void SqList_Intersect_True(SqList &A,SqList B)//求元素递增排列的线性表A和B的元素的交集并存回A中{i=1;j=1;k=0;while(A.elem&&B.elem[j]){if(A.elem<B.elem[j]) i++;else if(A.elem>B.elem[j]) j++;else if(A.elem!=A.elem[k]){A.elem[++k]=A.elem; //当发现了一个在A,B中都存在的元素i++;j++; //且C中没有,就添加到C中}}//whilewhile(A.elem[k]) A.elem[k++]=0;}//SqList_Intersect_True2.28void LinkList_Intersect_True(LinkList &A,LinkList B)//在链表结构上重做上题{p=A->next;q=B->next;pc=A;while(p&&q){if(p->data<q->data) p=p->next;else if(p->data>q->data) q=q->next;else if(p->data!=pc->data){pc=pc->next;pc->data=p->data;p=p->next;q=q->next;}}//while}//LinkList_Intersect_True2.29void SqList_Intersect_Delete(SqList &A,SqList B,SqList C){i=0;j=0;k=0;m=0; //i指示A中元素原来的位置,m为移动后的位置while(i<A.length&&j<B.length&& k<C.length){if(B.elem[j]<C.elem[k]) j++;else if(B.elem[j]>C.elem[k]) k++;else{same=B.elem[j]; //找到了相同元素samewhile(B.elem[j]==same) j++;while(C.elem[k]==same) k++; //j,k后移到新的元素while(i<A.length&&A.elem<same)A.elem[m++]=A.elem[i++]; //需保留的元素移动到新位置while(i<A.length&&A.elem==same) i++; //跳过相同的元素}}//whilewhile(i<A.length)A.elem[m++]=A.elem[i++]; //A的剩余元素重新存储。
清华大学数据结构试题及答案
清华大学数据结构试题及答案以下是清华大学数据结构试题及答案:试题一:1. 请解释什么是数据结构。
答案:数据结构是计算机科学中研究数据的组织、存储和管理方式的学科。
它涉及到数据的表示、操作以及与之相关的算法的设计和实现。
2. 请列举常见的数据结构类型。
答案:常见的数据结构类型包括数组、链表、栈、队列、树、图等。
3. 请解释什么是算法。
答案:算法是一系列解决特定问题的指令和计算步骤。
它描述了在给定输入的情况下,如何进行计算并产生所需输出。
4. 请列举一些常见的算法。
答案:常见的算法包括排序算法(如冒泡排序、插入排序、快速排序)、查找算法(如二分查找、哈希查找)、图算法(如深度优先搜索、广度优先搜索)等。
5. 请解释什么是时间复杂度和空间复杂度。
答案:时间复杂度是描述算法执行时间与输入规模之间的关系。
空间复杂度是描述算法所需内存空间与输入规模之间的关系。
试题二:1. 请给出数组和链表的区别。
答案:数组是一块连续的内存空间,元素在内存中按照索引顺序排列。
链表是由节点组成的数据结构,每个节点包含数据和指向下一个节点的指针。
2. 请解释什么是栈和队列。
答案:栈是一种后进先出(LIFO)的数据结构,只允许在栈顶进行插入和删除操作。
队列是一种先进先出(FIFO)的数据结构,允许在队尾插入数据,在队头删除数据。
3. 请给出树和图的区别。
答案:树是一种由节点和边组成的数据结构,每个节点可以有多个子节点。
图是一种由节点和边组成的数据结构,节点之间的关系可以是任意的,包括有向和无向边。
4. 请解释什么是哈希表。
答案:哈希表是一种通过哈希函数将键映射到特定位置的数据结构。
它能够快速地进行插入、删除和查找操作。
5. 请解释什么是递归。
答案:递归是一种通过调用自身的方法或函数来解决问题的编程技巧。
在递归过程中,问题会被拆分成一个或多个规模较小的子问题,直到达到基本情况。
以上就是清华大学数据结构试题及答案,希望对您有所帮助。
数据结构(C语言版)清华大学出版社课后题1-5章答案
数据结构(C语言版)清华大学出版社课后题1-5章答案第一章选择题1.A2.B3.C4.D5.B6.C第二章选择题1.A2.D3.D4.C5.A6.C7.B8.B9.D 10.D应用题1.应该选用链接存储表示。
如果才用顺序表示法,必须在一个连续的可用空间中为这N 个表分配空间。
初始时候因为不知道哪个表增长得快,必须平均分配空间。
在程序运行过程中,有的表占用的空间增长得快,有的表占用空间增长得慢,有的表很快就使用完了分配给它的空间,有的表才占用了少许空间,在进行元素的插入时候就必须成片的移动其他表的空间,以空出位置进行插入;在元素删除时为填补空白,也可能移动许多元素。
这个处理过程及其繁琐和低效。
如果采用链接存储,一个表的空间可以连续也可以不连续。
表的增长通过动态分配内存得以解决,只要存储器未满,就不会发生表溢出;表的收缩可以通过动态存储释放实现,释放的空间还可以在以后动态分配给其他的存储需求,非常灵活方便。
对于N个表(包括表的总数可能变化)共存的情形,处理十分简单快捷,插入、删除时间复杂度为O(1)。
所以才用链接存储表示较好。
2.一般来说,链式存储结构克服了顺序存储结构的三个缺点。
首先,插入、删除操作不需要移动元素,只修改指针;其次,不需要预先分配空间,可根据需要动态申请空间;其三,表容量只受到内存空间的限制。
其缺点是因为指针增加了空间开销,当空间不允许时,就不能克服顺序存储的缺点。
3.顺序结构时ai与ai+1的物理位置相邻,链表结构时两者的位置不要求一定相邻。
7.在顺序表中插入和删除一个节点需平均移动全表一半的节点。
具体的移动次数取决于所插入和删除的节点的位置i和全表的长度n这两个因素。
算法设计题1.分析:遍历整个顺序表,用k记录在x~y之间元素的个数,k的初始值为0。
对于当前遍历到的元素,若其值在x~y之间,则前移k个位置;否则执行++k。
这样每个不在x~y之间的元素仅仅移动一次,所以效率较高。
数据结构——清华大学出版社(第二版答案)
4-13
int huiwen(char A[],int s,int e) { if(A[s]!=A[e]) return 0; else if(s>e) return 1; else huiwen(A,s+1,e-1); }
4-15
• • • • • • void frequency(String &s,int C[]) { for (int i=0;i<128;i++) C[i]=0; for (int i=0;i<s.length();i++) C[atoi(s[i])]++; }
3-12
int BaseTrans(int N,int B) { int i,j; int result=0; LinkStack<int> S; while(N!=0) { i=N%B;N=N/B;S.Push(i); } while(!S.Empty()) { S.Top(i);S.Pop(j);result=result*10+i; } return result; }
int mid(int a,int b,int c) { int m1=a,m2; if(b<m1) {m2=m1;m1=b;} else m2=b; if(c<m1) {m2=m1;m1=c;} else if(c<m2) {m2=c;} return m2; }
1-16
char Compare(int a,int b) { if(a>b) return '>'; else if(a==b) return '='; else return '<'; }
数据结构(C语言版)第三版__清华大学出版社_习题参考答案
数据结构(C语言版)第三版__清华大学出版社_习题参考答案数据结构(C语言版)第三版__清华大学出版社_习题参考答案引言:数据结构是计算机科学的基础,对于学习和理解数据结构的相关概念和算法非常重要。
本文将对清华大学出版社出版的《数据结构(C语言版)第三版》中的习题进行参考答案的提供。
通过正确的理解和掌握这些习题的解答,读者可以加深对数据结构的认识,并提高自己的编程能力。
第一章:绪论1.1 数据结构的定义与作用数据结构是指数据对象以及数据对象之间的关系、运算和存储结构的总称。
数据结构的作用是在计算机中高效地组织和存储数据,同时支持常见的数据操作和算法。
1.2 算法的定义与特性算法是解决特定问题的一系列步骤和规则。
算法具有确定性、有穷性、可行性和输入输出性等特点。
第二章:线性表2.1 线性表的定义和基本操作线性表是同类型数据元素的一个有限序列。
线性表的基本操作包括初始化、查找、插入、删除和遍历等。
2.2 顺序存储结构顺序存储结构是将线性表中的元素按顺序存放在一块连续的存储空间中。
顺序存储结构的特点是随机存取、插入和删除操作需要移动大量元素。
2.3 链式存储结构链式存储结构通过结点之间的指针链表来表示线性表。
链式存储结构的特点是插入和删除操作方便,但查找操作需要遍历整个链表。
第三章:栈和队列3.1 栈的定义和基本操作栈是只能在一端进行插入和删除操作的线性表。
栈的基本操作包括初始化、入栈、出栈和获取栈顶元素等。
3.2 队列的定义和基本操作队列是只能在一端插入操作,在另一端进行删除操作的线性表。
队列的基本操作包括初始化、入队、出队和获取队头元素等。
第四章:串4.1 串的定义和基本操作串是由零个或多个字符组成的有限序列。
串的基本操作包括初始化、串的赋值、串的连接和串的比较等。
第五章:树5.1 树的基本概念和术语树是n(n>=0)个结点的有限集。
树的基本概念包括根结点、子树、深度和高度等。
5.2 二叉树二叉树是每个结点最多有两个子树的树结构。
数据结构(C语言版清华大学出版社)-章课后部分答案
第八章选择题1. C2.A3.B4.C5.D6.B7.B8.A9.D 10.D 11.C 12.C填空题1.n、n+12. 43.8.25( 折半查找所在块 )4.左子树、右子树5.266.顺序、(n+1)/2、O(log2n)7.m-1、[m/2]-18.直接定址应用题1.进行折半查找时,判定树是唯一的,折半查找过程是走了一条从根节点到末端节点的路径,所以其最大查找长度为判定树深度[log2n]+1.其平均查找长度约为[log2n+1]-1.在二叉排序树上查找时,其最大查找长度也是与二叉树的深度相关,但是含有n个节点的二叉排序树不是唯一的,当对n个元素的有序序列构造一棵二叉排序树时,得到的二叉排序树的深度也为n,在该二叉树上查找就演变成顺序查找,此时的最大查找长度为n;在随机情况下二叉排序树的平均查找长度为1+4log2n。
因此就查找效率而言,二分查找的效率优于二叉排序树查找,但是二叉排序树便于插入和删除,在该方面性能更优。
3. 评价哈希函数优劣的因素有:能否将关键字均匀的映射到哈希表中,有无好的处理冲突的方法,哈希函数的计算是否简单等。
冲突的概念:若两个不同的关键字Ki和Kj,其对应的哈希地址Hash(Ki) =Hash(Kj),则称为地址冲突,称Ki和K,j为同义词。
(1)开放定址法(2)重哈希法(3)链接地址法4.(1)构造的二叉排序树,如图(2)中序遍历结果如下:10 12 15 20 24 28 30 35 46 50 55 68(4)平均查找长度如下:ASLsucc = (1x1+2x2+3x3+4x3+5x3)/12 = 41/128.哈希地址如下:H(35) = 35%11 = 2H(67) = 67%11 = 1H(42) = 42%11 = 9H(21) = 21%11 = 10H(29) = 29%11 = 7H(86) = 86%11 = 9H(95) = 95%11 = 7H(47) = 47%11 = 3H(50) = 50%11 = 6H(36) = 36%11 = 3H(91) = 91%11 = 3第九章选择题1. D2.C3.B4.D5.C6.B7.A8.A9.D 10.D填空题1.插入排序、交换排序、选择排序、归并排序2.移动(或者交换)3.归并排序、快速排序、堆排序4.保存当前要插入的记录,可以省去在查找插入位置时的对是否出界的判断5.O(n)、O(log2n)6.直接插入排序或者改进了的冒泡排序、快速排序7.Log2n、n8.完全二叉树、n/29.1510.{12 38 25 35 50 74 63 90}应用题11.(1)Shell排序(步长为5 3 1)每趟的排序结果初始序列为100 87 52 61 27 170 37 45 61 118 14 88 32步长为5的排序14 37 32 61 27 100 87 45 61 118 170 88 52步长为3的排序结果14 27 32 52 37 61 61 45 88 87 170 100 118步长为1的排序结果14 27 32 37 45 52 61 61 87 88 100 118最后结果14 27 32 37 45 52 61 61 87 88 100 118 170(2)快速排序每趟的排序结果如图初始序列100 87 52 61 27 170 37 45 61 118 14 88 32第一趟排序[32 87 52 61 27 88 37 45 61 14]100[118 170]第二趟排序[14 27]32[61 52 88 37 45 61 87]100 118[170]第三趟排序14[27]32[45 52 37]61[88 61 87]100 118[170]第四趟排序14[27]32[37]45[52]61[87 61]88 100 118[170]第五趟排序14[27]32[37]45[52]61[87 61]88 100 118[170]最后结果14[27]32[37]45[52]61[61]87 88 100 118[170](3)二路归并排序每趟的排序结果初始序列[100][87][52][61][27][170][37][45][61][118][14][88][32]第一趟归并[87 100][52 61][27 170][37 45][61 118][14 88][32]第二趟归并[52 61 87 100][27 37 45 170][14 61 88 118][32]第三趟归并排序[27 37 45 52 61 87 100 170][14 32 61 88 118]第四趟归并排序[14 27 32 37 45 52 61 61 87 88 100 118 170]最后结果14 27 32 37 45 52 61 61 87 88 100 118 17012.采用快速排序时,第一趟排序过程中的数据移动如图:算法设计题1.分析:为讨论方便,待排序记录的定义为(后面各算法都采用此定义):#define MAXSIZE 100 /* 顺序表的最大长度,假定顺序表的长度为100 */ typedef int KeyType; /* 假定关键字类型为整数类型 */typedef struct {KeyType key; /* 关键字项 */OtherType other; /* 其他项 */}DataType; /* 数据元素类型 */typedef struct {DataType R[MAXSIZE+1]; /* R[0]闲置或者充当哨站 */int length; /* 顺序表长度 */}sqList; /* 顺序表类型 */设n个整数存储在R[1..n]中,因为前n-2个元素有序,若采用直接插入算法,共要比较和移动n-2次,如果最后两个元素做一个批处理,那么比较次数和移动次数将大大减小。
数据结构习题集答案解析--清华大学版
第1章 绪论简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型。
解:数据是对客观事物的符号表示。
在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
数据对象是性质相同的数据元素的集合,是数据的一个子集。
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
存储结构是数据结构在计算机中的表示。
数据类型是一个值的集合和定义在这个值集上的一组操作的总称。
抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。
是对一般数据类型的扩展。
试描述数据结构和抽象数据类型的概念与程序设计语言中数据类型概念的区别。
}解:抽象数据类型包含一般数据类型的概念,但含义比一般数据类型更广、更抽象。
一般数据类型由具体语言系统内部定义,直接提供给编程者定义用户数据,因此称它们为预定义数据类型。
抽象数据类型通常由编程者定义,包括定义它所使用的数据和在这些数据上所进行的操作。
在定义抽象数据类型中的数据部分和操作部分时,要求只定义到数据的逻辑结构和操作说明,不考虑数据的存储结构和操作的具体实现,这样抽象层次更高,更能为其他用户提供良好的使用接口。
设有数据结构(D,R),其中{}4,3,2,1d d d d D =,{}r R =,()()(){}4,3,3,2,2,1d d d d d d r =试按图论中图的画法惯例画出其逻辑结构图。
解:试仿照三元组的抽象数据类型分别写出抽象数据类型复数和有理数的定义(有理数是其分子、分母均为自然数且分母不为零的分数)。
解:ADT Complex{数据对象:D={r,i|r,i 为实数} .数据关系:R={<r,i>} 基本操作: InitComplex(&C,re,im)操作结果:构造一个复数C ,其实部和虚部分别为re 和im DestroyCmoplex(&C)操作结果:销毁复数C Get(C,k,&e) 操作结果:用e 返回复数C 的第k 元的值 Put(&C,k,e)操作结果:改变复数C 的第k 元的值为e;IsAscending(C)操作结果:如果复数C的两个元素按升序排列,则返回1,否则返回0 IsDescending(C)操作结果:如果复数C的两个元素按降序排列,则返回1,否则返回0 Max(C,&e)操作结果:用e返回复数C的两个元素中值较大的一个Min(C,&e)操作结果:用e返回复数C的两个元素中值较小的一个}ADT Complex…ADT RationalNumber{数据对象:D={s,m|s,m为自然数,且m不为0}数据关系:R={<s,m>}基本操作:InitRationalNumber(&R,s,m)操作结果:构造一个有理数R,其分子和分母分别为s和mDestroyRationalNumber(&R)操作结果:销毁有理数RGet(R,k,&e)操作结果:用e返回有理数R的第k元的值?Put(&R,k,e)操作结果:改变有理数R的第k元的值为eIsAscending(R)操作结果:若有理数R的两个元素按升序排列,则返回1,否则返回0 IsDescending(R)操作结果:若有理数R的两个元素按降序排列,则返回1,否则返回0 Max(R,&e)操作结果:用e返回有理数R的两个元素中值较大的一个Min(R,&e)操作结果:用e返回有理数R的两个元素中值较小的一个-}ADT RationalNumber试画出与下列程序段等价的框图。
清华大学严蔚敏数据结构习题集(C版)答案
清华大学严蔚敏数据结构习题集(C版)答案清华大学严蔚敏数据结构习题集(C版)答案第一章绪论1.16void print_descending(int x,int y,int z)//按从大到小顺序输出三个数{scanf("%d,%d,%d",&x,&y,&z);if(x<y) x<->y; //<->为表示交换的双目运算符,以下同if(y<z) y<->z;if(x<y) x<->y; //冒泡排序printf("%d %d %d",x,y,z);}//print_descending1.17Status fib(int k,int m,int &f)//求k阶斐波那契序列的第m项的值f{int tempd;if(k<2||m<0) return ERROR;if(m<k-1) f=0;else if (m==k-1) f=1;else{for(i=0;i<=k-2;i++) temp=0;temp[k-1]=1; //初始化for(i=k;i<=m;i++) //求出序列第k至第m个元素的值{sum=0;for(j=i-k;j<i;j++) sum+=temp[j];temp=sum;}f=temp[m];}return OK;}//fib分析:通过保存已经计算出来的结果,此方法的时间复杂度仅为O(m^2).如果采用递归编程(大多数人都会首先想到递归方法),则时间复杂度将高达O(k^m).1.18typedef struct{char *sport;enum{male,female} gender; char schoolname; //校名为'A','B','C','D'或'E'char *result;int score;} resulttype;typedef struct{int malescore;int femalescore;int totalscore;} scoretype;void summary(resulttype result[ ])//求各校的男女总分和团体总分,假设结果已经储存在result[ ]数组中{scoretype score;i=0;while(result.sport!=NULL){switch(result.schoolname){case 'A':score[ 0 ].totalscore+=result.score;if(result.gender==0)score[ 0 ].malescore+=result.score;elsescore[ 0 ].femalescore+=result.score;break;case 'B':score.totalscore+=result.score;if(result.gender==0)score.malescore+=result.score;else score.femalescore+=result.score;break;………………}i++;}for(i=0;i<5;i++){printf("School %d:\n",i);printf("Total score ofmale:%d\n",score.malescore);printf("Total score offemale:%d\n",score.femalescore);printf("Total score ofall:%d\n\n",score.totalscore);}}//summary1.19Status algo119(int a[ARRSIZE])//求i!*2^i序列的值且不超过maxint{last=1;for(i=1;i<=ARRSIZE;i++){a[i-1]=last*2*i;if((a[i-1]/last)!=(2*i)) reurn OVERFLOW;last=a[i-1];return OK;}}//algo119分析:当某一项的结果超过了maxint时,它除以前面一项的商会发生异常.1.20void polyvalue(){float ad;float *p=a;printf("Input number of terms:");scanf("%d",&n);printf("Input the %d coefficients from a0 toa%d:\n",n,n);for(i=0;i<=n;i++) scanf("%f",p++);printf("Input value of x:");scanf("%f",&x);p=a;xp=1;sum=0; //xp用于存放x的i次方for(i=0;i<=n;i++){sum+=xp*(*p++);xp*=x;}printf("Value is:%f",sum);}//polyvalue第二章线性表2.10Status DeleteK(SqList &a,int i,int k)//删除线性表a中第i个元素起的k个元素{if(i<1||k<0||i+k-1>a.length) returnINFEASIBLE;for(count=1;i+count-1<=a.length-k;c ount++) //注意循环结束的条件a.elem[i+count-1]=a.elem[i+count+k-1];a.length-=k;return OK;}//DeleteK2.11Status Insert_SqList(SqList &va,int x)//把x插入递增有序表va中{if(va.length+1>va.listsize) returnERROR;va.length++;for(i=va.length-1;va.elem>x&&i>=0;i--)va.elem[i+1]=va.elem;va.elem[i+1]=x;return OK;}//Insert_SqList2.12int ListComp(SqList A,SqList B)//比较字符表A和B,并用返回值表示结果,值为正,表示A>B;值为负,表示A<B;值为零,表示A=B{for(i=1;A.elem||B.elem;i++)if(A.elem!=B.elem) returnA.elem-B.elem;return 0;}//ListComp2.13LNode* Locate(LinkList L,int x)//链表上的元素查找,返回指针{for(p=l->next;p&&p->data!=x;p=p->next);return p;}//Locate2.14int Length(LinkList L)//求链表的长度{for(k=0,p=L;p->next;p=p->next,k++);return k;}//Length2.15void ListConcat(LinkList ha,LinkList hb,LinkList &hc)//把链表hb接在ha后面形成链表hc{hc=ha;p=ha;while(p->next) p=p->next;p->next=hb;}//ListConcat2.16见书后答案.2.17Status Insert(LinkList &L,int i,int b)//在无头结点链表L的第i个元素之前插入元素b{p=L;q=(LinkList*)malloc(sizeof(LNode));q.data=b;if(i==1){q.next=p;L=q; //插入在链表头部}else{while(--i>1) p=p->next;q->next=p->next;p->next=q; //插入在第i个元素的位置}}//Insert2.18Status Delete(LinkList &L,int i)//在无头结点链表L中删除第i个元素{if(i==1) L=L->next; //删除第一个元素else{p=L;while(--i>1) p=p->next;p->next=p->next->next; //删除第i个元素}}//Delete2.19Status Delete_Between(Linklist &L,int mink,int maxk)//删除元素递增排列的链表L中值大于mink且小于maxk的所有元素{p=L;while(p->next->data<=mink) p=p->next;//p是最后一个不大于mink的元素if(p->next) //如果还有比mink更大的元素{q=p->next;while(q->data<maxk) q=q->next; //q 是第一个不小于maxk的元素p->next=q;}}//Delete_Between2.20Status Delete_Equal(Linklist &L)//删除元素递增排列的链表L中所有值相同的元素{p=L->next;q=p->next; //p,q指向相邻两元素while(p->next){if(p->data!=q->data){p=p->next;q=p->next; //当相邻两元素不相等时,p,q都向后推一步}else{while(q->data==p->data){free(q);q=q->next;}p->next=q;p=q;q=p->next; //当相邻元素相等时删除多余元素}//else}//while}//Delete_Equal2.21void reverse(SqList &A)//顺序表的就地逆置{for(i=1,j=A.length;i<j;i++,j--)A.elem<->A.elem[j];}//reverse2.22void LinkList_reverse(Linklist &L)//链表的就地逆置;为简化算法,假设表长大于2{p=L->next;q=p->next;s=q->next;p->next=NULL;while(s->next){q->next=p;p=q;q=s;s=s->next; //把L的元素逐个插入新表表头}q->next=p;s->next=q;L->next=s;}//LinkList_reverse分析:本算法的思想是,逐个地把L的当前元素q插入新的链表头部,p为新表表头.2.23void merge1(LinkList &A,LinkList &B,LinkList &C)//把链表A和B合并为C,A 和B的元素间隔排列,且使用原存储空间{p=A->next;q=B->next;C=A;while(p&&q){s=p->next;p->next=q; //将B的元素插入if(s){t=q->next;q->next=s; //如A非空,将A的元素插入}p=s;q=t;}//while}//merge12.24void reverse_merge(LinkList&A,LinkList &B,LinkList &C)//把元素递增排列的链表A和B合并为C,且C中元素递减排列,使用原空间{pa=A->next;pb=B->next;pre=NULL; //pa 和pb分别指向A,B的当前元素while(pa||pb){if(pa->data<pb->data||!pb){pc=pa;q=pa->next;pa->next=pre;p a=q; //将A的元素插入新表}else{pc=pb;q=pb->next;pb->next=pre;p b=q; //将B的元素插入新表}pre=pc;}C=A;A->next=pc; //构造新表头}//reverse_merge分析:本算法的思想是,按从小到大的顺序依次把A和B的元素插入新表的头部pc处,最后处理A或B的剩余元素.2.25void SqList_Intersect(SqList A,SqList B,SqList &C)//求元素递增排列的线性表A 和B的元素的交集并存入C中{i=1;j=1;k=0;while(A.elem&&B.elem[j]){if(A.elem<B.elem[j]) i++;if(A.elem>B.elem[j]) j++;if(A.elem==B.elem[j]){C.elem[++k]=A.elem; //当发现了一个在A,B中都存在的元素,i++;j++; //就添加到C中}}//while}//SqList_Intersect2.26void LinkList_Intersect(LinkList A,LinkList B,LinkList &C)//在链表结构上重做上题{p=A->next;q=B->next;pc=(LNode*)malloc(sizeof(LNode));while(p&&q){if(p->data<q->data) p=p->next;else if(p->data>q->data) q=q->next;else{s=(LNode*)malloc(sizeof(LNode));s->data=p->data;pc->next=s;pc=s;p=p->next;q=q->next;}}//whileC=pc;}//LinkList_Intersect2.27void SqList_Intersect_True(SqList&A,SqList B)//求元素递增排列的线性表A 和B的元素的交集并存回A中{i=1;j=1;k=0;while(A.elem&&B.elem[j]){if(A.elem<B.elem[j]) i++;else if(A.elem>B.elem[j]) j++;else if(A.elem!=A.elem[k]){A.elem[++k]=A.elem; //当发现了一个在A,B中都存在的元素i++;j++; //且C中没有,就添加到C中}}//whilewhile(A.elem[k]) A.elem[k++]=0;}//SqList_Intersect_True2.28void LinkList_Intersect_True(LinkList &A,LinkList B)//在链表结构上重做上题{p=A->next;q=B->next;pc=A;while(p&&q){if(p->data<q->data) p=p->next; else if(p->data>q->data) q=q->next;else if(p->data!=pc->data){pc=pc->next;pc->data=p->data;p=p->next;q=q->next;}}//while}//LinkList_Intersect_True2.29void SqList_Intersect_Delete(SqList&A,SqList B,SqList C){i=0;j=0;k=0;m=0; //i指示A中元素原来的位置,m为移动后的位置while(i<A.length&&j<B.length&&k<C.length){if(B.elem[j]<C.elem[k]) j++;else if(B.elem[j]>C.elem[k]) k++;else{same=B.elem[j];//找到了相同元素same while(B.elem[j]==same) j++;while(C.elem[k]==same)k++; //j,k后移到新的元素while(i<A.length&&A.elem<same)A.elem[m++]=A.elem[i++];//需保留的元素移动到新位置while(i<A.length&&A.elem==same) i++; //跳过相同的元素}}//whilewhile(i<A.length)A.elem[m++]=A.elem[i++]; //A的剩余元素重新存储。
最新数据结构(C语言版)第三版__清华大学出版社_习题参考答案
只要有信心,努力,一切可以改变。
附录习题参考答案习题1参考答案1.1.选择题(1). A. (2). A. (3). A. (4). B.C. (5). A. (6). A. (7). C. (8). A. (9). B. (10.) A.1.2.填空题(1). 数据关系(2). 逻辑结构物理结构(3). 线性数据结构树型结构图结构(4). 顺序存储链式存储索引存储散列表(Hash)存储(5). 变量的取值范围操作的类别(6). 数据元素间的逻辑关系数据元素存储方式或者数据元素的物理关系(7). 关系网状结构树结构(8). 空间复杂度和时间复杂度(9). 空间时间(10). Ο(n)1.3 名词解释如下:数据:数据是信息的载体是计算机程序加工和处理的对象包括数值数据和非数值数据数据项:数据项指不可分割的、具有独立意义的最小数据单位数据项有时也称为字段或域数据元素:数据元素是数据的基本单位在计算机程序中通常作为一个整体进行考虑和处理一个数据元素可由若干个数据项组成数据逻辑结构:数据的逻辑结构就是指数据元素间的关系数据存储结构:数据的物理结构表示数据元素的存储方式或者数据元素的物理关系数据类型:是指变量的取值范围和所能够进行的操作的总和算法:是对特定问题求解步骤的一种描述是指令的有限序列1.4 语句的时间复杂度为:(1) Ο(n2)(2) Ο(n2)(3) Ο(n2)(4) Ο(n-1)(5) Ο(n3)1.5 参考程序:main(){int XYZ;scanf("%d %d%d"&X&YZ);if (X>=Y)if(X>=Z)if (Y>=Z) { printf("%d %d%d"XYZ);}else{ printf("%d %d%d"XZY);}else{ printf("%d %d%d"ZXY);}else if(Z>=X)if (Y>=Z) { printf("%d %d%d"YZX);}else{ printf("%d%d%d"ZYX);}else{ printf("%d%d%d"YXZ);}}1.6 参考程序:main(){int in;float xa[]p;printf("\nn=");scanf("%f"&n);printf("\nx=");scanf("%f"&x);for(i=0;i<=n;i++)scanf("%f "&a[i]);p=a[0];for(i=1;i<=n;i++){ p=p+a[i]*x;x=x*x;}printf("%f"p)'}习题2参考答案2.1选择题(1). C. (2). B. (3). B. (4). B. 5. D. 6. B. 7. B. 8. A. 9. A. 10. D.2.2.填空题(1). 有限序列(2). 顺序存储和链式存储(3). O(n) O(n)(4). n-i+1 n-i(5). 链式(6). 数据指针(7). 前驱后继(8). Ο(1) Ο(n)(9). s->next=p->next; p->next=s ;(10). s->next2.3. 解题思路:将顺序表A中的元素输入数组a若数组a中元素个数为n将下标为012...(n-1)/2的元素依次与下标为nn-1...(n-1)/2的元素交换输出数组a的元素参考程序如下:main(){int in;float ta[];printf("\nn=");scanf("%f"&n);for(i=0;i<=n-1;i++)scanf("%f "&a[i]);for(i=0;i<=(n-1)/2;i++){ t=a[i]; a[i] =a[n-1-i]; a[n-1-i]=t;} for(i=0;i<=n-1;i++)printf("%f"a[i]);}2.4 算法与程序:main(){int in;float ta[];printf("\nn=");scanf("%f"&n);for(i=0;i<n;i++)scanf("%f "&a[i]);for(i=1;i<n;i++)if(a[i]>a[0]{ t=a[i]; a[i] =a[0]; a[0]=t;}printf("%f"a[0]);for(i=2;i<n;i++)if(a[i]>a[1]{ t=a[i]; a[i] =a[1]; a[1]=t;}printf("%f"a[0]);}2.5 算法与程序:main(){int ijkn;float xta[];printf("\nx=");scanf("%f"&x);printf("\nn=");scanf("%f"&n);for(i=0;i<n;i++)scanf("%f "&a[i]); // 输入线性表中的元素for (i=0; i<n; i++) { // 对线性表中的元素递增排序k=i;for (j=i+1; j<n; j++) if (a[j]<a[k]) k=j; if (k<>j) {t=a[i];a[i]=a[k];a[k]=t;}}for(i=0;i<n;i++) // 在线性表中找到合适的位置if(a[i]>x) break;for(k=n-1;k>=i;i--) // 移动线性表中元素然后插入元素xa[k+1]=a[k];a[i]=x;for(i=0;i<=n;i++) // 依次输出线性表中的元素printf("%f"a[i]);}2.6 算法思路:依次扫描A和B的元素比较A、B当前的元素的值将较小值的元素赋给C如此直到一个线性表扫描完毕最后将未扫描完顺序表中的余下部分赋给C即可C的容量要能够容纳A、B两个线性表相加的长度有序表的合并算法:void merge (SeqList ASeqList BSeqList *C){ int ijk;i=0;j=0;k=0;while ( i<=st && j<=st )if (A.data[i]<=B.data[j])C->data[k++]=A.data[i++];elseC->data[k++]=B.data[j++];while (i<=st )C->data[k++]= A.data[i++];while (j<=st )C->data[k++]=B.data[j++];C->last=k-1;}2.7 算法思路:依次将A中的元素和B的元素比较将值相等的元素赋给C如此直到线性表扫描完毕线性表C就是所求递增有序线性表算法:void merge (SeqList ASeqList BSeqList *C){ int ijk;i=0;j=0;k=0;while ( i<=st)while(j<=st )if (A.data[i]=B.data[j])C->data[k++]=A.data[i++];C->last=k-1;}习题3参考答案3.1.选择题(1). D (2). C (3). D (4). C (5). B (6). C (7). C (8). C (9). B (10).AB (11). D (12). B (13). D (14). C (15). C (16). D(17). D (18). C (19). C (20). C 3.2.填空题(1) FILOFIFO(2) -13 4 X * + 2 Y * 3 / -(3) stack.topstack.s[stack.top]=x(4) p>llink->rlink=p->rlinkp->rlink->llink=p->rlink(5) (R-F+M)%M(6) top1+1=top2(7) F==R(8) front==rear(9) front==(rear+1)%n(10) N-13.3 答:一般线性表使用数组来表示的线性表一般有插入、删除、读取等对于任意元素的操作而栈只是一种特殊的线性表栈只能在线性表的一端插入(称为入栈push)或者读取栈顶元素或者称为"弹出、出栈"(pop)3.4 答:相同点:栈和队列都是特殊的线性表只在端点处进行插入删除操作不同点:栈只在一端(栈顶)进行插入删除操作;队列在一端(top)删除一端(rear)插入3.5 答:可能序列有14种:ABCD; ACBD; ACDB; ABDC; ADCB; BACD; BADC; BCAD; BCDA; BDCA; CBAD; CBDA; CDBA; DCBA3.6 答:不能得到435612最先出栈的是4则按321的方式出不可能得到1在2前的序列可以得到135426按如下方式进行push(1)pop()push(2)push(3)pop()push(4)push(5)pop()pop()pop()push(6)pop()3.7 答:stack3.8 非递归:int vonvert (int noint a[]) //将十进制数转换为2进制存放在a[] 并返回位数{int r;SeStack s*p;P=&s;Init_stack(p);while(no){push(pno%2);no/=10;}r=0;while(!empty_stack(p)){pop(pa+r);r++;}return r;}递归算法:void convert(int no){if(no/2>0){Convert(no/2);Printf("%d"no%2);}elseprintf("%d"no);}3.9 参考程序:void view(SeStack s){SeStack *p; //假设栈元素为字符型char c;p=&s;while(!empty_stack(p)){c=pop(p);printf("%c"c);}printf("\n");}3.10 答:char3.11 参考程序:void out(linkqueue q){int e;while(q.rear !=q.front ){dequeue(qe);print(e); //打印}}习题4参考答案4.1 选择题:(1). A (2). D (3). C (4). C (5). B (6). B (7). D (8). A (9). B (10). D 4.2 填空题:(1)串长相等且对应位置字符相等(2)不含任何元素的串(3)所含字符均是空格所含空格数(4) 10(5) "hello boy"(6) 13(7) 1066(8)模式匹配(9)串中所含不同字符的个数(10) 364.3 StrLength (s)=14StrLength (t)=4SubStr( s87)=" STUDENT"SubStr(t21)="O"StrIndex(s"A")=3StrIndex (st)=0StrRep(s"STUDENT"q)=" I AM A WORKER"4.4 StrRep(s"Y""+");StrRep(s"+*""*Y");4.5 空串:不含任何字符;空格串:所含字符都是空格串变量和串常量:串常量在程序的执行过程中只能引用不能改变;串变量的值在程序执行过程中是可以改变和重新赋值的主串与子串:子串是主串的一个子集串变量的名字与串变量的值:串变量的名字表示串值的标识符4.6int EQUAl(ST){char *p*q;p=&S;q=&T;while(*p&&*q){if(*p!=*q)return *p-*q;p++;q++;}return *p-*q;}4.7(1)6*8*6=288(2)1000+47*6=1282(3)1000+(8+4)*8=1096(4)1000+(6*7+4)*8=13684.8习题5参考答案5.1 选择(1)C(2)B(3)C(4)B(5)C(6)D(7)C(8)C(9)B(10)C (11)B(12)C(13)C(14)C(15)C(16)B5.2 填空(1)1(2)1036;1040(3)2i(4) 1 ; n ; n-1 ; 2(5)2k-1;2k-1(6)ACDBGJKIHFE(7)p!=NULL(8)Huffman树(9)其第一个孩子; 下一个兄弟(10)先序遍历;中序遍历5.3叶子结点:C、F、G、L、I、M、K;非终端结点:A、B、D、E、J;各结点的度:结点: A B C D E F G L I J K M度: 4 3 0 1 2 0 0 0 0 1 0 0树深:4无序树形态如下:二叉树形态如下:5.5二叉链表如下:三叉链表如下:5.6先序遍历序列:ABDEHICFJG中序遍历序列:DBHEIAFJCG后序遍历序列:DHIEBJFGCA5.7(1) 先序序列和中序序列相同:空树或缺左子树的单支树;(2) 后序序列和中序序列相同:空树或缺右子树的单支树;(3) 先序序列和后序序列相同:空树或只有根结点的二叉树5.8这棵二叉树为:先根遍历序列:ABFGLCDIEJMK后根遍历序列:FGLBCIDMJKEA层次遍历序列:ABCDEFGLIJKM5.10证明:设树中结点总数为n叶子结点数为n0则n=n0 + n1 + ...... + nm (1)再设树中分支数目为B则B=n1 + 2n2 + 3n3 + ...... + m nm (2)因为除根结点外每个结点均对应一个进入它的分支所以有n= B + 1 (3)将(1)和(2)代入(3)得n0 + n1 + ...... + nm = n1 + 2n2 + 3n3 + ...... + m nm + 1 从而可得叶子结点数为:n0 = n2 + 2n3 + ...... + (m-1)nm + 15.11由5.10结论得n0 = (k-1)nk + 1又由 n=n0 + nk得nk= n-n0代入上式得n0 = (k-1)(n-n0)+ 1叶子结点数为:n0 = n (k-1) / k5.12int NodeCount(BiTree T){ //计算结点总数if(T)if (T-> lchild==NULL )&&( T --> rchild==NULL )return 1;elsereturn NodeCount(T-> lchild ) +Node ( T --> rchild )+1; elsereturn 0;}void ExchangeLR(Bitree bt){/* 将bt所指二叉树中所有结点的左、右子树相互交换 */ if (bt && (bt->lchild || bt->rchild)) {bt->lchild<->bt->rchild;Exchange-lr(bt->lchild);Exchange-lr(bt->rchild);}}/* ExchangeLR */5.14int IsFullBitree(Bitree T){/* 是则返回1否则返回0*/Init_Queue(Q); /* 初始化队列*/flag=0;In_Queue(QT); /* 根指针入队列按层次遍历*/while(!Empty_Queue (Q)){Out_Queue(Qp);if(!p) flag=1; /* 若本次出队列的是空指针时则修改flag值为1若以后出队列的指针存在非空则可断定不是完全二叉树 */else if (flag) return 0; /*断定不是完全二叉树 */ else{In_Queue(Qp->lchild);In_Queue(Qp->rchild); /* 不管孩子是否为空都入队列*/}}/* while */return 1; /* 只有从某个孩子指针开始之后所有孩子指针都为空才可断定为完全二叉树*/}/* IsFullBitree */转换的二叉树为:5.16对应的森林分别为:5.17typedef char elemtype;typedef struct{ elemtype data;int parent;} NodeType;(1) 求树中结点双亲的算法:int Parent(NodeType t[ ]elemtype x){/* x不存在时返回-2否则返回x双亲的下标(根的双亲为-1 */for(i=0;i<MAXNODE;i++)if(x==t[i].data) return t[i].parent; return -2;}/*Parent*/(2) 求树中结点孩子的算法:void Children(NodeType t[ ]elemtype x){for(i=0;i<MAXNODE;i++){if(x==t[i].data)break;/*找到x退出循环*/}/*for*/if(i>=MAXNODE) printf("x不存在\n"); else {flag=0;for(j=0;j<MAXNODE;j++)if(i==t[j].parent){ printf("x的孩子:%c\n"t[j].data);flag=1;}if(flag==0) printf("x无孩子\n");}/*Children*/5.18typedef char elemtype;typedef struct ChildNode{ int childcode;struct ChildNode *nextchild;}typedef struct{ elemtype data;struct ChildNode *firstchild;} NodeType;(1) 求树中结点双亲的算法:int ParentCL(NodeType t[ ]elemtype x){/* x不存在时返回-2否则返回x双亲的下标 */for(i=0;i<MAXNODE;i++)if(x==t[i].data) {loc=i;/*记下x的下标*/break;}if(i>=MAXNODE) return -2; /* x不存在 *//*搜索x的双亲*/for(i=0;i<MAXNODE;i++)for(p=t[i].firstchild;p!=NULL;p=p->nextchild) if(loc==p->childcode)return i; /*返回x结点的双亲下标*/}/* ParentL */(2) 求树中结点孩子的算法:void ChildrenCL(NodeType t[ ]elemtype x){for(i=0;i<MAXNODE;i++)if(x==t[i].data) /*依次打印x的孩子*/{flag=0; /* x存在 */for(p=t[i].firstchild;p;p=p->nextchild){ printf("x的孩子:%c\n"t[p-> childcode].data);flag=1;}if(flag==0) printf("x无孩子\n");return;}/*if*/printf("x不存在\n");return;}/* ChildrenL */5.19typedef char elemtype;typedef struct TreeNode{ elemtype data;struct TreeNode *firstchild; struct TreeNode *nextsibling; } NodeType;void ChildrenCSL(NodeType *telemtype x){ /* 层次遍历方法 */Init_Queue(Q); /* 初始化队列 */In_Queue(Qt);count=0;while(!Empty_Queue (Q)){Out_Queue(Qp);if(p->data==x){ /*输出x的孩子*/p=p->firstchild;if(!p) printf("无孩子\n");else{ printf("x的第%i个孩子:%c\n"++countp->data);/*输出第一个孩子*/p=p->nextsibling; /*沿右分支*/while(p){printf("x的第%i个孩子:%c\n"++countp->data);p=p-> nextsibling;}}return;}if(p-> firstchild) In_Queue(Qp-> firstchild);if(p-> nextsibling) In_Queue(Qp-> nextsibling);}}/* ChildrenCSL */5.20(1) 哈夫曼树为:(2) 在上述哈夫曼树的每个左分支上标以1右分支上标以0并设这7个字母分别为A、B、C、D、E、F和H如下图所示:则它们的哈夫曼树为分别为:A:1100B:1101C:10D:011E:00F:010H:111习题6参考答案6.1 选择题(1)C (2)A (3)B(4)C(5)B______条边(6)B(7)A(8)A(9)B(10)A(11)A(12)A(13)B(14)A(15)B(16)A(17)C 6.2 填空(1) 4(2) 1对多 ; 多对多(3) n-1 ; n(4) 0_(5)有向图(6) 1(7)一半(8)一半(9)___第i个链表中边表结点数___(10)___第i个链表中边表结点数___(11)深度优先遍历;广度优先遍历(12)O(n2)(13)___无回路6.3(1)邻接矩阵:(2)邻接链表:(3)每个顶点的度:顶点度V1 3V2 3V3 2V4 3V5 36.4(1)邻接链表:(2)逆邻接链表:(3)顶点入度出度V1 3 0V2 2 2V3 1 2V4 1 3V5 2 1V6 2 36.5(1)深度优先查找遍历序列:V1 V2 V3 V4 V5; V1 V3 V5 V4 V2; V1 V4 V3 V5 V2 (1)广度优先查找遍历序列:V1 V2 V3 V4 V5; V1 V3 V2 V4 V5; V1 V4 V3 V2 V56.6有两个连通分量:6.7顶点(1)(2)(3)(4)(5)Low Close Cost VexLow CloseCost VexLow CloseCost VexLow CloseCost VexLow CloseCost VexV10 00 00 00 00 0V21 00 00 00 00 0V31 01 00 00 00 0V43 02 12 10 10 1V5∞ 05 13 22 30 3U{v1} {v1v2} {v1v2v3} {v1 v2 v3 v4} {v1 v2 v3 v4 v5} T {} { (v1 v2) } {(v1 v2) (v1 v3) } {(v1 v2) (v1 v3) (v2 v4) } {(v1 v2) (v1v3)(v2v4)(v4v5) }最小生成树的示意图如下:6.8拓扑排序结果: V3--> V1 --> V4 --> V5 --> V2 --> V66.9(1)建立无向图邻接矩阵算法:提示:参见算法6.1因为无向图的邻接矩阵是对称的所以有for (k=0; k<G ->e; k++) /*输入e条边建立无向图邻接矩阵*/{ scanf("\n%d%d"&i&j);G ->edges[i][j]= G ->edges[j][i]=1;}(2)建立无向网邻接矩阵算法:提示:参见算法6.1初始化邻接矩阵:#define INFINITY 32768 /* 表示极大值*/for(i=0;i<G->n;i++)for(j=0;j<G->n;j++) G->edges[i][j]= INFINITY;输入边的信息:不仅要输入边邻接的两个顶点序号还要输入边上的权值for (k=0; k<G ->e; k++) /*输入e条边建立无向网邻接矩阵*/{ scanf("\n%d%d%d"&i&j&cost); /*设权值为int型*/G ->edges[i][j]= G ->edges[j][i]=cost;/*对称矩阵*/}(3)建立有向图邻接矩阵算法:提示:参见算法6.16.10(1)建立无向图邻接链表算法:typedef VertexType char;int Create_NgAdjList(ALGraph *G){ /* 输入无向图的顶点数、边数、顶点信息和边的信息建立邻接表 */scanf("%d"&n); if(n<0) return -1; /* 顶点数不能为负 */G->n=n;scanf("%d"&e); if(e<0) return =1; /*边数不能为负 */G->e=e;for(m=0;m< G->n ;m++)G-> adjlist [m].firstedge=NULL; /*置每个单链表为空表*/for(m=0;m< G->n;m++)G->adjlist[m].vertex=getchar(); /*输入各顶点的符号*/for(m=1;m<= G->e; m++){scanf("\n%d%d"&i&j); /* 输入一对邻接顶点序号*/if((i<0 || j<0) return -1;p=(EdgeNode*)malloc(sizeof(EdgeNode));/*在第i+1个链表中插入一个边表结点*/ p->adjvex=j;p->next= G-> adjlist [i].firstedge;G-> adjlist [i].firstedge=p;p=(EdgeNode*)malloc(sizeof(EdgeNode));/*在第j+1个链表中插入一个边表结点*/ p->adjvex=i;p->next= G-> adjlist [j].firstedge;G-> adjlist [j].firstedge=p;} /* for*/return 0; /*成功*/}//Create_NgAdjList(2)建立有向图逆邻接链表算法:typedef VertexType char;int Create_AdjList(ALGraph *G){ /* 输入有向图的顶点数、边数、顶点信息和边的信息建立逆邻接链表 */scanf("%d"&n); if(n<0) return -1; /* 顶点数不能为负 */G->n=n;scanf("%d"&e); if(e<0) return =1; /*弧数不能为负 */G->e=e;for(m=0;m< G->n; m++)G-> adjlist [m].firstedge=NULL; /*置每个单链表为空表*/for(m=0;m< G->n;m++)G->adjlist[m].vertex=getchar(); /*输入各顶点的符号*/for(m=1;m<= G->e ; m++){scanf("\n%d%d"&t&h); /* 输入弧尾和弧头序号*/if((t<0 || h<0) return -1;p=(EdgeNode*)malloc(sizeof(EdgeNode));/*在第h+1个链表中插入一个边表结点*/ p->adjvex=t;p->next= G-> adjlist [h].firstedge;G-> adjlist [h].firstedge=p;} /* for*/return 0; /*成功*/}//Create_AdjList6.11void Create_AdjM(ALGraph *G1MGraph *G2){ /*通过无向图的邻接链表G1生成无向图的邻接矩阵G2*/G2->n=G1->n; G2->e=G1->e;for(i=0;i<G2->n;i++) /* 置G2每个元素为0 */for(j=0;j<G2->n;j++) G2->edges[i][j]= 0;for(m=0;m< G1->n;m++)G2->vexs[m]=G1->adjlist[m].vertex; /*复制顶点信息*/num=(G1->n/2==0?G1->n/2:G1->n/2+1); /*只要搜索前n/2个单链表即可*/for(m=0;m< num;m++){ p=G1->adjlist[m].firstedge;while(p){ /* 无向图的存储具有对称性*/G2->edges[m][ p->adjvex ]= G2->edges[p->adjvex ] [m] =1;p==p->next;}}/* for */}/*Create_AdjM */void Create_AdjL(ALGraph *G1MGraph *G2){ /*通过无向图的邻接矩阵G1生成无向图的邻接链表G2*/G2->n=G1->n; G2->e=G1->e;for(i=0;i<G1->n;i++) /* 建立每个单链表 */{ G2->vexs[i]=G1->adjlist[i].vertex;G2->adjlist[i].firstedge=NULL;for(j=i; j<G1->n; j++) /*对称矩阵只要搜索主对角以上的元素即可*/{ if(G1->edges[i][j]== 1){ p=(EdgeNode*)malloc(sizeof(EdgeNode));/*在第i+1个链表中插入一个边表结点*/p->adjvex=j;p->next= G-> adjlist [i].firstedge;G-> adjlist [i].firstedge=p;p=(EdgeNode*)malloc(sizeof(EdgeNode));/*在第j+1个链表中插入一个边表结点*/p->adjvex=i;p->next= G-> adjlist [j].firstedge;G-> adjlist [j].firstedge=p;}/*if*/}/* for*/}/* for*/}/* Create_AdjL */6.13(1) 邻接矩阵中1的个数的一半;(2) 若位于[i-1j-1]或[j-1i-1]位置的元素值等于1则有边相连否则没有(3) 顶点i的度等于第i-1行中或第i-1列中1的个数6.14(1) 邻接链表中边表结点的个数的一半;(2) 若第i-1(或j-1)个单链表中存在adjvex域值等于j-1(或i-1)的边表结点则有边相连否则没有(3) 顶点i的度等于第i-1个单链表中边表结点的个数提示:参见算法6.2 和6.3习题 7参考答案7.1 选择题(1)C (2)C (3) C (4)B (5) A (6)A (7) D (8)B (9)D (10) B(11)B (12)A (13)C (14)C (15)A (16)D (17)C (18)BC (19)B (20)A7.2 填空题(1) O(n)O(log2n)(2) 12485log2(n+1)-1(3)小于大于(4)增序序列(5)m-1(6) 70; 342055(7) n/m(8)开放地址法链地址法(9)产生冲突的可能性就越大产生冲突的可能性就越小(10)关键码直接(11)②①⑦(12) 1616821(13)直接定址法数字分析法平方取中法折叠法除留余数法随机数法(14)开放地址法再哈希法链地址法建立一个公共溢出区(15)装满程度(16)索引快(17)哈希函数装填因子(18)一个结点(19)中序(20)等于7.3 一棵二叉排序树(又称二叉查找树)或者是一棵空树或者是一棵同时满足下列条件的二叉树:(1)若它的左子树不空则左子树上所有结点的键值均小于它根结点键值(2)若它的右子树不空则右子树上所有结点的键值均大于它根结点键值(3)它的左、右子树也分别为二叉排序树7.4 对地址单元d=H(K)如发生冲突以d为中心在左右两边交替进行探测按照二次探测法键值K的散列地址序列为:do=H(K)d1=(d0+12)mod md2=(d0-12)mod md3=(d0+22)mod md4=(d0-12)mod m......7.5 衡量算法的标准有很多时间复杂度只是其中之一尽管有些算法时间性能很好但是其他方面可能就存在着不足比如散列查找的时间性能很优越但是需要关注如何合理地构造散列函数问题而且总存在着冲突等现象为了解决冲突还得采用其他方法二分查找也是有代价的因为事先必须对整个查找区间进行排序而排序也是费时的所以常应用于频繁查找的场合对于顺序查找尽管效率不高但却比较简单常用于查找范围较小或偶而进行查找的情况7.6此法要求设立多个散列函数Hii=1...k当给定值K与闭散列表中的某个键值是相对于某个散列函数Hi的同义词因而发生冲突时继续计算该给定值K在下一个散列函数Hi+1下的散列地址直到不再产生冲突为止7.7散列表由两个一维数组组成一个称为基本表另一个称为溢出表插入首先在基本表上进行;假如发生冲突则将同义词存人溢出表7.8 结点个数为n时高度最小的树的高度为1有两层它有n-1个叶结点1个分支结点;高度最大的树的高度为n-l有n层它有1个叶结点n-1个分支结点7.9 设顺序查找以h为表头指针的有序链表若查找成功则返回结点指针p查找失败则返回null值pointer sqesrearch(pointer hint xpointerp){p=null;while(h)if(x>h->key)h=h->link;else{if(x==h->key)p=h;return(p);}}虽然链表中的结点是按从小到大的顺序排列的但是其存储结构为单链表查找结点时只能从头指针开始逐步进行搜索故不能用折半(二分)查找7.10 分析:对二叉排序树来讲其中根遍历序列为一个递增有序序列因此对给定的二叉树进行中根遍历如果始终能保证前一个值比后一个值小则说明该二叉树是二叉排序树int bsbtr (bitreptr T) /*predt记录当前结点前趋值初值为-∞*/{ if (T==NULL) return(1);else{b1=bsbtr(T->lchild);/*判断左子树*/if (!b1|| (predt>=T->data)) return(0);*当前结点和前趋比较*/ predt=T->data;/*修改当前结点的前趋值*/return(bsbtr(T->rchild));/*判断右子树并返回最终结果*/}}7.11 (1)使用线性探查再散列法来构造散列表如表下所示散列表───────────────────────────────地址 0 1 2 3 4 5 6 7 8 9 10───────────────────────────────数据 33 1 13 12 34 38 27 22───────────────────────────────(2)使用链地址法来构造散列表如下图(3)装填因子a=8/11使用线性探查再散列法查找成功所需的平均查找次数为Snl=0.5(1+1/(1-a))=0.5*(1+1/(1-8/11))=7/3使用线性探查再散列法查找不成功所需的平均查找次数为:Unl=0.5(1+1/(1-a)2)=0.5*(1+1/(1-8/11)2)=65/9 使用链地址法查找成功所需的平均查找次数为:Snc=l+a/2=1+8/22=15/11使用链地址法查找不成功所需的平均查找次数为: 'Unl=a+e-a=8/1l+e-8/117.12 分析:在等查区间的上、下界处设两个指针由此计算出中间元素的序号当中间元素大于给定值X时接下来到其低端区间去查找;当中间元素小于给定值X时接下来到其高端区间去查找;当中间元素等于给定值X时表示查找成功输出其序号Int binlist(sqtable Aint stkeytype X) /*t、s分别为查找区间的上、下界*/{ if(s<t) return(0);/*查找失败*/else{ mid=(S+t)/2;switCh(mid){case x<A.item[midJ.key: return(binlist(Asmid-lX));/*在低端区间上递归*/case x==A.item[mid].key: return(mid);/+查找成功*/ case x>A.item[mid].key: return(amid+ltX));/*在高端区间上递归*/}}}int sqsearch0 (sqtable Akeytype X) /*数组有元素n个*/{ i=l;A.item[n+1].key=X;/t设置哨兵*/while (A.item[n+1].key!=X) i++;return (i% (n/1));/*找不到返回0找到返回其下标*/}查找成功平均查找长度为:(1+2+3+...+n)/n:(1+n)/2查找不成功平均查找长度为:n+17.14散列函数:H(key)=100+(key个位数+key十位数) mod l0;形成的散列表:100 101 102 103 104 105 106 107 108 10998 75 63 46 49 79 61 53 17查找成功时的平均长度为:(1+2+1+1+5+1+1+5+5+3)/10=2.5次由于长度为10的哈希表已满因此在插人第11个记录时所需作的比较次数的期望值为10查找不成功时的平均长度为10习题 8参考答案8.1 选择题(1)B (2)A (3)D (4)C (5)B (6)A (7)B (8)C (9)A (10)C(11)D (12)C (13) C (14)D (15)C (16)B (17) D (18)C (19)B (20)D8.2填空题(1)快速归并(2) O(log2n)O(nlog2n)(3)归并(4)向上根结点(5) 1918162030(6)(7)4913275076386597(8)88(9)插入选择(每次选择最大的)(10)快速归并(11)O(1)O(nlog2n)(12)稳定(13)3(14)(15205040)(15)O(log2n)(16)O(n2)(17)冒泡排序快速排序(18)完全二叉树n/2(19)稳定不稳定(20)24(2015)8.3. 假定给定含有n个记录的文件(r1f2...rn)其相应的关键字为(k1k2...kn)则排序就是确定文件的一个序列rrr2...rn使得k1'≤k2'≤...≤kn'从而使得文件中n个记录按其对应关键字有序排列如果整个排序过程在内存中进行则排序叫内部排序假设在待排序的文件中存在两个或两个以上的记录具有相同的关键字若采用某种排序方法后使得这些具有相同关键字的记录在排序前后相对次序依然保持不变则认为该排序方法是稳定的否则就认为排序方法是不稳定的8.4.稳定的有:直接插入排序、二分法插入排序、起泡排序、归并排序和直接选择排序8.5.初始记录序列按关键字有序或基本有序时比较次数为最多8.6.设5个元素分别用abcde表示取a与b、c与d进行比较若a>bc>d(也可能是a<bc<d此时情况类似)显然此时进行了两次比较取b与d再比较若b>d则a>b>d若b<d则有c>d>b此时已进行了3次比较要使排序比较最多7次可把另外两个元素按折半检索排序插入到上面所得的有序序列中此时共需要4次比较从而可得算法共只需7次比较8.7.题目中所说的几种排序方法中其排序速度都很快但快速排序、归并排序、基数排序和Shell排序都是在排序结束后才能确定数据元素的全部序列而排序过程中无法知道部分连续位置上的最终元素而堆排序则是每次输出一个堆顶元素(即最大或最少值的元素)然后对堆进行再调整保证堆顶元素总是当前剩下元素的最大或最小的从而可知欲在一个大量数据的文件中如含有15000个元素的记录文件中选取前10个最大的元素可采用堆排序进行8.8.二分法排序8.9.void insertsort(seqlist r)  ;{ //对顺序表中记录R[0一N-1)按递增序进行插入排序&NBSP;int ij;  ;for(i=n-2;i>=0; i--) //在有序区中依次插入r[n-2]..r[0]  ;if(r[i].key>r[i+1].key) //若不是这样则r[i]原位不动 ;{  ;r[n]=r[i];j=i+l;//r[n]是哨兵 ;do{ //从左向右在有序区中查找插入位置 ;r[j-1]= r[j];//将关键字小于r[i].key的记录向右移 ;j++;  ;}whle(r[j].key r[j-1]=r[n];//将引i)插入到正确位置上 ;}//endif ;}//insertsort.  ;8.10.建立初始堆:[937 694 863 265 438 751 742129075 3011]&NBSP;&NBSP;第一次排序重建堆:[863 694 751 765 438 301 742 129 075]9378.11.在排序过程中每次比较会有两种情况出现若整个排序过程至少需作t次比较则显然会有2^t个情况由于n个结点总共有n!种不同的排列因而必须有n!种不同的比较路径于是: 2t≥n!即t≥log2n!因为log2nl=nlog2n-n/ln2+log2n/2+O(1)故有log2n!≈nlog2n从而t≧nlog2n得证8.12.依据堆定义可知:序列(1)、(2)、(4)是堆(3)不是堆从而可对其调整使之为如下的大根堆(1009580604095821020)8.13.第一趟:[265 301] [129 751] [863 937] [694 742] [076 438]&NBSP; &NBSP;第二趟:[129 265 301 751] [694 742 863 937] [076 438]&NBSP;&NBSP;第三趟:[129 265 301 694 742 751 863 937] [076 438]&NBSP;&NBSP;第四趟:[076 129 265 301 438 694 742 751 863 937]&NBSP;8.14.(1)归并排序:(1829) (2547) (1258) (1051)(18252947) (10125158)(1012182529475158)(2)快速排序:(1018251229585147)(1018251229475158)(1012182529475158)(3)堆排序:初始堆(大顶堆):(58 47512918122510)第一次调整:(51 472529181210)(58)第二次调整:(47 2925101812)(5158)第三次调整:(29 18251012)(475158)第四次调整:(25 181210)(29475158)第五次调整:(18 1012)(2529475158)第六次调整:(12 10) (182529475158)第七次调整:(10 12182529475158)8.15.(1)直接插入排序序号 1 2 3 4 5 6 7 8 9 10 11 12 关键字 83 40 63 13 84 35 96 57 39 79 61 151=2 40 83 [63 13 84 35 96 57 39 79 61 15] 1=3 40 63 83 [13 84 35 96 57 39 79 61 15] 1=4 13 40 63 83 [84 3 5 96 57 39 79 61 15] I=5 13 40 63 83 84 [35 96 57 39 79 61 15] I=6 13 35 40 63 83 84 [96 57 39 79 61 15] 1=7 13 35 40 63 83 84 96 [57 39 79 61 15] 1=8 13 35 40 57 63 83 84 96 [ 39 79 61 15] 1=9 13 35 39 40 57 63 83 84 96 [79 61 15] I=10 13 35 39 40 57 63 79 83 84 96 [61 15] I=11 13 35 39 40 57 61 63 79 83 84 96 [15] 1=12 13 15 35 39 40 57 61 63 79 83 84 96 (2)直接选择排序序号 1 2 3 4 5 6 7 8 9 10 11 12 关键字 83 40 63 13 84 35 96 57 39 79 61 15i=1 13 [ 40 63 83 84 35 96 57 39 79 61 15] i=2 13 15 [63 83 84 35 96 57 39 79 61 40] i=3 13 15 35 [83 84 63 96 57 39 79 61 40] i=4 13 15 35 39 [84 63 96 57 83 79 61 40] i=5 13 15 35 39 40 [63 96 57 83 79 61 84] i=6 13 15 35 39 40 57 [96 63 83 79 61 84] i=7 13 15 35 39 40 57 61 [63 83 79 96 84] i=8 13 15 35 39 40 57 61 63 [83 79 96 84] i=9 13 15 35 39 40 57 61 63 79 183 96 84] i=10 13 15 35 39 40 57 61 63 79 83 [96 84] i=11 13 15 35 39 40 57 61 63 79 83 84 [96] (3)快速排序关键字 83 40 63 13 84 35 96 57 39 79 61 15 第一趟排序后 [15 40 63 13 61 35 79 57 39] 83 [96 84] 第二趟排序后 [13] 15 [63 40 61 35 79 57 39] 83 84 [96] 第三趟排序后 13 15 [39 40 61 35 57] 63 [79] 83 84 96 第四趟排序后 13 15 [35] 39 [61 40 57] 63 79 83 84 96第五趟排序后 13 15 35 39 [57 40] 61 63 79 83 84 96 第六趟排序后 13 15 35 39 40 [57] 61 63 79 83 84 96 第七趟排序后 13 15 35 39 40 57 61 63 79 83 84 96 (4)堆排序关键字 83 40 63 13 84 35 96 57 39 79 61 15排序成功的序列 96 84 83 79 63 61 57 40 39 35 15 13(5)归并排序关键字 83 40 63 13 84 35 96 57 39 79 61 15 第一趟排序后 [40 83] [13 63] [3584] [57 96] [39 79] [15 61]第二趟排序后 [13 40 63 83] [35 57 84 96] [15 39 61 79] 第三趟排序后 [13 35 40 57 63 83 84 96]] [15 39 61 79] 第四趟排序后 13 15 35 39 40 57 61 63 79 83 84 96。
数据结构课后习题答案清华大学出版社殷人昆
}
friend ostream& operator<< (ostream&os, complex&ob ){
//友元函数:重载<<,将复数ob输出到输出流对象os中。
returnos << ob.Re << ( ob.Im >= 0.0 )?“+” : “-” <<fabs( ob.Im ) << “i”;
1-2什么是数据结构?有关数据结构的讨论涉及哪三个方面?
【解答】
数据结构是指数据以及相互之间的关系。记为:数据结构={D, R}。其中,D是某一数据对象,R是该对象中所有数据成员之间的关系的有限集合。
有关数据结构的讨论一般涉及以下三方面的内容:
1数据成员以及它们相互之间的逻辑关系,也称为数据的逻辑结构,简称为数据结构;
}
1-5用归纳法证明:
(1)
(2)
(3)
【证明】略
1-6什么是算法?算法的5个特性是什么?试根据这些特性解释算法与程序的区别。
【解答】
通常,定义算法为“为解决某一特定任务而规定的一个指令序列。”一个算法应当具有以下特性:
①有输入。一个算法必须有0个或多个输入。它们是算法开始运算前给予算法的量。这些输入取自于特定的对象的集合。它们可以使用输入语句由外部提供,也可以使用赋值语句在算法内给定。
doublegetReal ( ){ returnRe; }//取复数实部
doublegetImag ( ){ returnIm; }//取复数虚部
voidsetReal (doubler ){Re = r; }//修改复数实部
(完整版)清华大学数据结构试题及答案
一、单选题(每题 2 分,共20分)1.1.对一个算法的评价,不包括如下(B )方面的内容。
A.健壮性和可读性 B.并行性 C.正确性 D.时空复杂度2.2.在带有头结点的单链表HL中,要向表头插入一个由指针p指向的结点,则执行()。
A。
p—>next=HL->next; HL—>next=p; B。
p—〉next=HL; HL=p;C. p—>next=HL; p=HL;D. HL=p; p—〉next=HL;3.3。
对线性表,在下列哪种情况下应当采用链表表示?( )A.经常需要随机地存取元素 B。
经常需要进行插入和删除操作C。
表中元素需要占据一片连续的存储空间 D.表中元素的个数不变4.4.一个栈的输入序列为1 2 3,则下列序列中不可能是栈的输出序列的是( C )A。
2 3 1 B. 3 2 1C。
3 1 2 D。
1 2 35.5。
AOV网是一种( ).A.有向图 B.无向图 C.无向无环图 D.有向无环图6.6.采用开放定址法处理散列表的冲突时,其平均查找长度( )。
A.低于链接法处理冲突 B。
高于链接法处理冲突C.与链接法处理冲突相同 D.高于二分查找7.7.若需要利用形参直接访问实参时,应将形参变量说明为()参数。
A.值 B.函数 C.指针 D.引用8.8。
在稀疏矩阵的带行指针向量的链接存储中,每个单链表中的结点都具有相同的( )。
A.行号 B.列号 C.元素值 D.非零元素个数9.9。
快速排序在最坏情况下的时间复杂度为( ).A.O(log2n) B.O(nlog2n) C.0(n) D.0(n2)10.10.从二叉搜索树中查找一个元素时,其时间复杂度大致为()。
A。
O(n) B。
O(1) C. O(log2n) D。
O(n2)二、二、运算题(每题 6 分,共24分)1.1。
数据结构是指数据及其相互之间的______________.当结点之间存在M对N(M:N)的联系时,称这种结构为_____________________。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第1章 绪论1.1 简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型。
解:数据是对客观事物的符号表示。
在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。
数据对象是性质相同的数据元素的集合,是数据的一个子集。
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
存储结构是数据结构在计算机中的表示。
数据类型是一个值的集合和定义在这个值集上的一组操作的总称。
抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。
是对一般数据类型的扩展。
1.2 试描述数据结构和抽象数据类型的概念与程序设计语言中数据类型概念的区别。
解:抽象数据类型包含一般数据类型的概念,但含义比一般数据类型更广、更抽象。
一般数据类型由具体语言系统内部定义,直接提供给编程者定义用户数据,因此称它们为预定义数据类型。
抽象数据类型通常由编程者定义,包括定义它所使用的数据和在这些数据上所进行的操作。
在定义抽象数据类型中的数据部分和操作部分时,要求只定义到数据的逻辑结构和操作说明,不考虑数据的存储结构和操作的具体实现,这样抽象层次更高,更能为其他用户提供良好的使用接口。
1.3 设有数据结构(D,R),其中{}4,3,2,1d d d d D =,{}r R =,()()(){}4,3,3,2,2,1d d d d d d r =试按图论中图的画法惯例画出其逻辑结构图。
解:1.4 试仿照三元组的抽象数据类型分别写出抽象数据类型复数和有理数的定义(有理数是其分子、分母均为自然数且分母不为零的分数)。
解:ADT Complex{ 数据对象:D={r,i|r,i 为实数} 数据关系:R={<r,i>} 基本操作: InitComplex(&C,re,im)操作结果:构造一个复数C ,其实部和虚部分别为re 和im DestroyCmoplex(&C)操作结果:销毁复数C Get(C,k,&e) 操作结果:用e 返回复数C 的第k 元的值 Put(&C,k,e) 操作结果:改变复数C 的第k 元的值为eIsAscending(C)操作结果:如果复数C 的两个元素按升序排列,则返回1,否则返回0IsDescending(C)操作结果:如果复数C的两个元素按降序排列,则返回1,否则返回0 Max(C,&e)操作结果:用e返回复数C的两个元素中值较大的一个Min(C,&e)操作结果:用e返回复数C的两个元素中值较小的一个}ADT ComplexADT RationalNumber{数据对象:D={s,m|s,m为自然数,且m不为0}数据关系:R={<s,m>}基本操作:InitRationalNumber(&R,s,m)操作结果:构造一个有理数R,其分子和分母分别为s和mDestroyRationalNumber(&R)操作结果:销毁有理数RGet(R,k,&e)操作结果:用e返回有理数R的第k元的值Put(&R,k,e)操作结果:改变有理数R的第k元的值为eIsAscending(R)操作结果:若有理数R的两个元素按升序排列,则返回1,否则返回0 IsDescending(R)操作结果:若有理数R的两个元素按降序排列,则返回1,否则返回0 Max(R,&e)操作结果:用e返回有理数R的两个元素中值较大的一个Min(R,&e)操作结果:用e返回有理数R的两个元素中值较小的一个}ADT RationalNumber1.5 试画出与下列程序段等价的框图。
(1) product=1; i=1;while(i<=n){product *= i;i++;}(2) i=0;do {i++;} while((i!=n) && (a[i]!=x));(3) switch {case x<y: z=y-x; break;case x=y: z=abs(x*y); break;default: z=(x-y)/abs(x)*abs(y);}1.6 在程序设计中,常用下列三种不同的出错处理方式:(1) 用exit语句终止执行并报告错误;(2) 以函数的返回值区别正确返回或错误返回;(3) 设置一个整型变量的函数参数以区别正确返回或某种错误返回。
试讨论这三种方法各自的优缺点。
解:(1)exit常用于异常错误处理,它可以强行中断程序的执行,返回操作系统。
(2)以函数的返回值判断正确与否常用于子程序的测试,便于实现程序的局部控制。
(3)用整型函数进行错误处理的优点是可以给出错误类型,便于迅速确定错误。
1.7 在程序设计中,可采用下列三种方法实现输出和输入:(1) 通过scanf和printf语句;(2) 通过函数的参数显式传递;(3) 通过全局变量隐式传递。
试讨论这三种方法的优缺点。
解:(1)用scanf和printf直接进行输入输出的好处是形象、直观,但缺点是需要对其进行格式控制,较为烦琐,如果出现错误,则会引起整个系统的崩溃。
(2)通过函数的参数传递进行输入输出,便于实现信息的隐蔽,减少出错的可能。
(3)通过全局变量的隐式传递进行输入输出最为方便,只需修改变量的值即可,但过多的全局变量使程序的维护较为困难。
1.8 设n为正整数。
试确定下列各程序段中前置以记号@的语句的频度:(1) i=1; k=0;while(i<=n-1){@ k += 10*i;i++;}(2) i=1; k=0;do {@ k += 10*i;i++;} while(i<=n-1);(3) i=1; k=0;while (i<=n-1) {i++;@ k += 10*i;}(4) k=0;for(i=1; i<=n; i++) {for(j=i; j<=n; j++)@ k++;}(5) for(i=1; i<=n; i++) {for(j=1; j<=i; j++) {for(k=1; k<=j; k++)@ x += delta;}(6) i=1; j=0; while(i+j<=n) { @ if(i>j) j++; else i++; }(7) x=n; y=0; // n 是不小于1的常数 while(x>=(y+1)*(y+1)) { @ y++; }(8) x=91; y=100; while(y>0) {@ if(x>100) { x -= 10; y--; } else x++; } 解:(1) n-1 (2) n-1 (3) n-1(4) n+(n-1)+(n-2)+ (1)2)1(+n n (5) 1+(1+2)+(1+2+3)+...+(1+2+3+...+n)=∑=+ni i i 12)1( =∑∑∑∑====+=+=+ni n i n i n i i i i i i i 1121212121)(21)1(21=)32)(1(121)1(41)12)(1(121++=++++n n n n n n n n (6) n (7)⎣⎦n 向下取整(8) 11001.9 假设n 为2的乘幂,并且n>2,试求下列算法的时间复杂度及变量count 的值(以n 的函数形式表示)。
int Time(int n) { count = 0; x=2;while(x<n/2) {x *= 2; count++;}return count;}解:)(log 2n o count=2log 2-n1.11 已知有实现同一功能的两个算法,其时间复杂度分别为()nO 2和()10n O ,假设现实计算机可连续运算的时间为710秒(100多天),又每秒可执行基本操作(根据这些操作来估算算法时间复杂度)510次。
试问在此条件下,这两个算法可解问题的规模(即n 值的范围)各为多少?哪个算法更适宜?请说明理由。
解:12102=nn=40 121010=nn=16则对于同样的循环次数n ,在这个规模下,第二种算法所花费的代价要大得多。
故在这个规模下,第一种算法更适宜。
1.12 设有以下三个函数:()10002124++=n n n f ,()3450015n n n g+=,()n n n n h log 5005.3+=请判断以下断言正确与否:(1) f(n)是O(g(n)) (2) h(n)是O(f(n)) (3) g(n)是O(h(n)) (4) h(n)是O(n 3.5) (5) h(n)是O(nlogn)解:(1)对 (2)错 (3)错 (4)对 (5)错 1.13 试设定若干n 值,比较两函数2n 和n n 2log 50的增长趋势,并确定n 在什么范围内,函数2n 的值大于n n 2log 50的值。
解:2n 的增长趋势快。
但在n 较小的时候,n n 2log 50的值较大。
当n>438时,n n n22log 50>1.14 判断下列各对函数()n f 和()n g ,当∞→n 时,哪个函数增长更快?(1) ()()310!ln 102nn n n f ++=,()724++=n n n g(2)()()()25!ln +=n n f ,()5.213n n g=(3) ()141.2++=n n n f ,()()()n n n g +=2!ln(4)()()()2223nn n f +=,()()52n n n g n +=解:(1)g(n)快 (2)g(n)快 (3)f(n)快 (4) f(n)快 1.15 试用数学归纳法证明:(1)()()6/12112++=∑=n n n ini ()0≥n (2)()()1/11--=+=∑x xx n ni i()0,1≥≠n x(3)12211-=∑=-n ni i()1≥n (4)()2112ni ni =-∑=()1≥n1.16 试写一算法,自大至小依次输出顺序读入的三个整数X ,Y 和Z 的值解:int max3(int x,int y,int z) { if(x>y) if(x>z) return x; else return z; elseif(y>z) return y;else return z;}1.17 已知k 阶斐波那契序列的定义为 00=f ,01=f ,…,02=-k f ,11=-k f ;k n n n n f f f f ---+++= 21, ,1,+=k k n试编写求k 阶斐波那契序列的第m 项值的函数算法,k 和m 均以值调用的形式在函数参数表中出现。