清华数据结构习题集答案(C语言版严蔚敏)

合集下载

数据结构课后习题答案详解C语言版严蔚敏

数据结构课后习题答案详解C语言版严蔚敏

数据结构习题集答案(C语言版严蔚敏)第2章线性表2.1 描述以下三个概念的区别:头指针,头结点,首元结点(第一个元素结点)。

解:头指针是指向链表中第一个结点的指针。

首元结点是指链表中存储第一个数据元素的结点。

头结点是在首元结点之前附设的一个结点,该结点不存储数据元素,其指针域指向首元结点,其作用主要是为了方便对链表的操作。

它可以对空表、非空表以及首元结点的操作进行统一处理。

2.2 填空题。

解:(1) 在顺序表中插入或删除一个元素,需要平均移动表中一半元素,具体移动的元素个数与元素在表中的位置有关。

(2) 顺序表中逻辑上相邻的元素的物理位置必定紧邻。

单链表中逻辑上相邻的元素的物理位置不一定紧邻。

(3) 在单链表中,除了首元结点外,任一结点的存储位置由其前驱结点的链域的值指示。

(4) 在单链表中设置头结点的作用是插入和删除首元结点时不用进行特殊处理。

2.3 在什么情况下用顺序表比链表好解:当线性表的数据元素在物理位置上是连续存储的时候,用顺序表比用链表好,其特点是可以进行随机存取。

2.4 对以下单链表分别执行下列各程序段,并画出结果示意图。

解:2.5 画出执行下列各行语句后各指针及链表的示意图。

L=(LinkList)malloc(sizeof(LNode)); P=L;for(i=1;i<=4;i++){P->next=(LinkList)malloc(sizeof(LNode));P=P->next; P->data=i*2-1;}P->next=NULL;for(i=4;i>=1;i--) Ins_LinkList(L,i+1,i*2);for(i=1;i<=3;i++) Del_LinkList(L,i);解:2.6 已知L是无表头结点的单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的答案中选择合适的语句序列。

a. 在P结点后插入S结点的语句序列是__________________。

严蔚敏结构题集(C语言版)完整答案

严蔚敏结构题集(C语言版)完整答案

严蔚敏 数据结构C 语言版答案详解第1章 绪论1.1简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型。

解:数据是对客观事物的符号表示。

在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。

b5E2RGbCAP 数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。

数据对象是性质相同的数据元素的集合,是数据的一个子集。

数据结构是相互之间存在一种或多种特定关系的数据元素的集合。

存储结构是数据结构在计算机中的表示。

数据类型是一个值的集合和定义在这个值集上的一组操作的总称。

抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。

是对一般数据类型的扩展。

1.2 试描述数据结构和抽象数据类型的概念与程序设计语言中数据类型概念的区别。

解:抽象数据类型包含一般数据类型的概念,但含义比一般数据类型更广、更抽象。

一般数据类型由具体语言系统内部定义,直接提供给编程者定义用户数据,因此称它们为预定义数据类型。

抽象数据类型通常由编程者定义,包括定义它所使用的数据和在这些数据上所进行的操作。

在定义抽象数据类型中的数据部分和操作部分时,要求只定义到数据的逻辑结构和操作说明,不考虑数据的存储结构和操作的具体实现,这样抽象层次更高,更能为其他用户提供良好的使用接口。

p1EanqFDPw 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 试仿照三元组的抽象数据类型分别写出抽象数据类型复数和有理数的定义<有理数是其分子、分母均为自然数且分母不为零的分数)。

DXDiTa9E3d 解:ADT Complex{数据对象:D={r,i|r,i 为实数} 数据关系:R={<r,i>} 基本操作: 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,否则返回0IsDescending(C>操作结果:如果复数C的两个元素按降序排列,则返回1,否则返回0Max(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和m DestroyRationalNumber(&R>操作结果:销毁有理数RGet(R,k,&e>操作结果:用e返回有理数R的第k元的值Put(&R,k,e>操作结果:改变有理数R的第k元的值为eIsAscending(R>操作结果:若有理数R的两个元素按升序排列,则返回1,否则返回0IsDescending(R>操作结果:若有理数R的两个元素按降序排列,则返回1,否则返回0Max(R,&e>操作结果:用e返回有理数R的两个元素中值较大的一个Min(R,&e>操作结果:用e返回有理数R的两个元素中值较小的一个}ADT RationalNumber1.5 试画出与下列程序段等价的框图。

《数据结构》习题集答案(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={<r,i>}基本操作: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,否则返回0IsDescending(C)操作结果:如果复数C 的两个元素按降序排列,则返回1,否则返回0Max(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和m DestroyRationalNumber(&R)操作结果:销毁有理数RGet(R,k,&e)操作结果:用e返回有理数R的第k元的值Put(&R,k,e)操作结果:改变有理数R的第k元的值为eIsAscending(R)操作结果:若有理数R的两个元素按升序排列,则返回1,否则返回0IsDescending(R)操作结果:若有理数R的两个元素按降序排列,则返回1,否则返回0Max(R,&e)操作结果:用e返回有理数R的两个元素中值较大的一个Min(R,&e)操作结果:用e返回有理数R的两个元素中值较小的一个}ADT RationalNumber1.5 试画出与下列程序段等价的框图。

清华大学严蔚敏数据结构习题集(C版)答案

清华大学严蔚敏数据结构习题集(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; 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);}//polyvalue第二章线性表2.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; //插入在链表头部}{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的所有元素{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]; //找到了相同元素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语言版

清华数据结构习题集答案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版)(清华大学严蔚敏)

数据结构习题集答案(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++;elsesame=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的剩余元素重新存储。

《数据结构》习题集答案(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={<r,i>}基本操作: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,否则返回0IsDescending(C)操作结果:如果复数C 得两个元素按降序排列,则返回1,否则返回0Max(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与m DestroyRationalNumber(&R)操作结果:销毁有理数RGet(R,k,&e)操作结果:用e返回有理数R得第k元得值Put(&R,k,e)操作结果:改变有理数R得第k元得值为eIsAscending(R)操作结果:若有理数R得两个元素按升序排列,则返回1,否则返回0IsDescending(R)操作结果:若有理数R得两个元素按降序排列,则返回1,否则返回0Max(R,&e)操作结果:用e返回有理数R得两个元素中值较大得一个Min(R,&e)操作结果:用e返回有理数R得两个元素中值较小得一个}ADT RationalNumber1、5 试画出与下列程序段等价得框图。

数据结构课后习题答案详解C语言版严蔚敏

数据结构课后习题答案详解C语言版严蔚敏

数据结构习题集答案(C语言版严蔚敏)第2章线性表2.1描述以下三个概念的区别:头指针,头结点,首元结点(第一个元素结点)。

解:头指针是指向链表中第一个结点的指针。

首元结点是指链表中存储第一个数据元素的结点。

头结点是在首元结点之前附设的一个结点,该结点不存储数据元素,其指针域指向首元结点,其作用主要是为了方便对链表的操作。

它可以对空表、非空表以及首元结点的操作进行统一处理。

2.2填空题。

解:(1)在顺序表中插入或删除一个元素,需要平均移动表中一半元素,具体移动的元素个数与元素在表中的位置有关。

(2)顺序表中逻辑上相邻的元素的物理位置必定紧邻。

单链表中逻辑上相邻的元素的物理位置不一定紧邻。

(3)在单链表中,除了首元结点外,任一结点的存储位置由其前驱结点的链域的值指示。

(4)在单链表中设置头结点的作用是插入和删除首元结点时不用进行特殊处理。

2.3在什么情况下用顺序表比链表好?解:当线性表的数据元素在物理位置上是连续存储的时候,用顺序表比用链表好,其特点是可以进行随机存取。

2.4对以下单链表分别执行下列各程序段,并画出结果示意图。

解:2.5画出执行下列各行语句后各指针及链表的示意图。

L=(LinkList)malloc(sizeof(LNode)); P=L;for(i=1;i<=4;i++){P->next=(LinkList)malloc(sizeof(LNode));P=P->next; P->data=i*2-1;}P->next=NULL;for(i=4;i>=1;i--)Ins_LinkList(L,i+1,i*2);for(i=1;i<=3;i++)Del_LinkList(L,i);解:2.6已知L是无表头结点的单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的答案中选择合适的语句序列。

a.在P结点后插入S结点的语句序列是__________________。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

、清华数据结构习题集答案(C 语言版严蔚敏)第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和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 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试画出与下列程序段等价的框图。

(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) 用exit语句终止执行并报告错误;(2) 以函数的返回值区别正确返回或错误返回;)(3) 设置一个整型变量的函数参数以区别正确返回或某种错误返回。

试讨论这三种方法各自的优缺点。

解:(1)exit常用于异常错误处理,它可以强行中断程序的执行,返回操作系统。

(2)以函数的返回值判断正确与否常用于子程序的测试,便于实现程序的局部控制。

(3)用整型函数进行错误处理的优点是可以给出错误类型,便于迅速确定错误。

在程序设计中,可采用下列三种方法实现输出和输入:(1) 通过scanf和printf语句;(2) 通过函数的参数显式传递;"(3) 通过全局变量隐式传递。

试讨论这三种方法的优缺点。

解:(1)用scanf和printf直接进行输入输出的好处是形象、直观,但缺点是需要对其进行格式控制,较为烦琐,如果出现错误,则会引起整个系统的崩溃。

(2)通过函数的参数传递进行输入输出,便于实现信息的隐蔽,减少出错的可能。

(3)通过全局变量的隐式传递进行输入输出最为方便,只需修改变量的值即可,但过多的全局变量使程序的维护较为困难。

设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; .+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) 1100假设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-n已知有实现同一功能的两个算法,其时间复杂度分别为()nO2和()10n O ,假设现实计算机可连续运算的时间为710秒(100多天),又每秒可执行基本操作(根据这些操作来估算算法时间复杂度)510次。

试问在此条件下,这两个算法可解问题的规模(即n 值的范围)各为多少哪个算法更适宜请说明理由。

解:12102=nn=40 121010=nn=16则对于同样的循环次数n ,在这个规模下,第二种算法所花费的代价要大得多。

故在这个规模下,第一种算法更适宜。

设有以下三个函数:\()10002124++=n n n f ,()3450015n n n g+=,()nn 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 (5) h(n)是O(nlogn)解:(1)对 (2)错 (3)错 (4)对 (5)错{试设定若干n 值,比较两函数2n 和n n 2log 50的增长趋势,并确定n 在什么范围内,函数2n 的值大于n n 2log 50的值。

解:2n 的增长趋势快。

但在n 较小的时候,n n 2log 50的值较大。

当n>438时,n n n22log 50>判断下列各对函数()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)()()()2223n n n f +=,()()52n n n g n +=[解:(1)g(n)快 (2)g(n)快 (3)f(n)快 (4) f(n)快试用数学归纳法证明:(1)()()6/12112++=∑=n n n ini ()0≥n (2)()()1/110--=+=∑x xx n ni i()0,1≥≠n x(3)12211-=∑=-n ni i()1≥n (4)()2112ni ni =-∑=()1≥n试写一算法,自大至小依次输出顺序读入的三个整数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;:}已知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 均以值调用的形式在函数参数表中出现。

解:k>0为阶数,n 为数列的第n 项 int Fibonacci(int k,int n){[if(k<1) exit(OVERFLOW); int *p,x; p=new int[k+1]; if(!p) exit(OVERFLOW); int i,j;for(i=0;i<k+1;i++){ if(i<k-1) p[i]=0;else p[i]=1;|}for(i=k+1;i<n+1;i++){ x=p[0];for(j=0;j<k;j++) p[j]=p[j+1]; p[k]=2*p[k-1]-x; }return p[k];}|假设有A ,B ,C ,D ,E 五个高等院校进行田径对抗赛,各院校的单项成绩均已存入计算机,并构成一张表,表中每一行的形式为编写算法,处理上述表格,以统计各院校的男、女总分和团体总分,并输出。

相关文档
最新文档