严蔚敏数据结构习题集答案
- 格式:doc
- 大小:521.00 KB
- 文档页数:68
第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和mDestroyRationalNumber(&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 试画出与下列程序段等价的框图。
严蔚敏数据结构题集解答224页第一章基本概念和术语1.1数据结构的定义和作用数据结构是指数据对象中数据元素之间的关系,以及对这些关系的操作。
它在计算机科学中起着重要的作用,可以帮助我们更好地组织和管理数据。
1.2算法的定义和特性算法是一系列解决问题的清晰指令,它包含了一系列的步骤和规则,能够将输入转换为输出。
算法需要具备以下特性:确定性、有限性、可行性和输入输出。
第二章线性表2.1线性表的基本概念和表示线性表是由零个或多个数据元素组成的有限序列,它是一种常用的数据结构。
线性表可以使用顺序存储结构或链式存储结构进行表示。
2.2线性表的基本操作线性表的基本操作包括插入、删除、查找等。
插入操作可以在指定的位置插入一个新元素,删除操作可以删除指定位置的元素,查找操作可以根据给定条件来查找满足要求的元素。
第三章栈和队列3.1栈的定义和基本操作栈是一种特殊的线性表,它只允许在栈的一端进行插入和删除操作,这一端称为栈顶。
栈的基本操作包括进栈和出栈,以及栈空和栈满的判断。
3.2队列的定义和基本操作队列是一种特殊的线性表,它只允许在一端进行插入操作,在另一端进行删除操作,插入端称为队尾,删除端称为队头。
队列的基本操作包括入队和出队,以及队空和队满的判断。
第四章串4.1串的基本概念和表示方法串是由零个或多个字符组成的有限序列,它是一种特殊的线性表。
串的表示方法有两种:顺序存储和链式存储。
4.2朴素的模式匹配算法朴素的模式匹配算法是一种简单而有效的模式匹配算法,它通过逐个字符地比较主串和模式串的字符来进行匹配。
第五章数组和广义表5.1数组的定义和基本操作数组是一种线性表,它由一系列相同类型的元素组成。
数组的基本操作包括插入和删除元素,以及数组的查找和排序等。
5.2广义表的定义和基本操作广义表是一种扩展的线性表,它可以包含任意类型的元素,不仅可以是数据元素,还可以是另一个广义表。
广义表的基本操作包括对表头和表尾的操作,以及广义表的插入和删除等。
清华大学严蔚敏数据结构习题集(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的剩余元素重新存储。
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版)(清华大学严蔚敏)1.16void print_descending(int x,int y,int z)//按从大到小顺序输出三个数{scanf("%d,%d,%d",&x,&y,&z);if(x<-="">y; //<->为表示交换的双目运算符,以下同if(y<-="">z;if(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(melse 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;jtemp=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("T otal score of male:%d\n",score.malescore);printf("T otal score of female:%d\n",score.femalescore);printf("T otal 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< p="">{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->datanext; //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--)< p="">A.elem<->A.elem[j];}//reverse2.22void LinkList_reverse(Linklist &L)//链表的就地逆置;为简化算法,假设表长大于2 {p=L->next;q=p->next;s=q->next;p->next=NULL;{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 的当前元素{if(pa->datadata||!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<="" p="">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->datadata) 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<="" p="">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->datadata) 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)<="" p="">{if(B.elem[j]<="" p="">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)< p="">A.elem[m++]=A.elem[i++]; //需保留的元素移动到新位置while(i<a.length&&a.elem==same) i++;="" p="" 跳过相同的元素<="">}}//whilewhile(i<a.length)< p="">A.elem[m++]=A.elem[i++]; //A的剩余元素重新存储。
严蔚敏数据结构各章习题及答案数据结构习题及解答第1章概述【例1-1】分析以下程序段的时间复杂度。
for(i=0;i解:该程序段的时间复杂度为O (m*n )。
【例1-2】分析以下程序段的时间复杂度。
i=s=0; ① while(s<="" ②="" ③="">解:语句①为赋值语句,其执行次数为1次,所以其时间复杂度为O (1)。
语句②和语句③构成while 循环语句的循环体,它们的执行次数由循环控制条件中s 与n 的值确定。
假定循环重复执行x 次后结束,则语句②和语句③各重复执行了x 次。
其时间复杂度按线性累加规则为O (x )。
此时s 与n 满足关系式:s ≥n ,而s=1+2+3+…+x 。
所以有:1+2+3+…+x ≥n ,可以推出:x=nn 241212811+±-=+±-x 与n 之间满足x=f(n ),所以循环体的时间复杂度为O (n ),语句①与循环体由线性累加规则得到该程序段的时间复杂度为O (n )。
【例1-3】分析以下程序段的时间复杂度。
i=1; ① while(i<=n) i=2*i; ②解:其中语句①的执行次数是1,设语句②的执行次数为f (n ),则有:n n f ≤)(2。
log)得:T(n)=O(n2【例1-4】有如下递归函数fact(n),分析其时间复杂度。
fact(int n){ if(n<=1)return(1);①elsereturn(n*fact(n-1));②}解:设fact(n)的运行时间函数是T(n)。
该函数中语句①的运行时间是O(1),语句②的运行时间是T(n-1)+ O(1),其中O(1)为常量运行时间。
由此可得fact(n)的时间复杂度为O(n)。
习题1一、单项选择题1.数据结构是指(1. A )。
A.数据元素的组织形式B.数据类型C.数据存储结构D.数据定义2.数据在计算机存储器内表示时,物理地址与逻辑地址不相同的,称之为(2. C )。
数据结构c语言版严蔚敏课后习题答案数据结构是计算机科学中的一个重要领域,它涉及到数据的组织、管理和存储方式,以便可以高效地访问和修改数据。
C语言作为一种广泛使用的编程语言,提供了丰富的数据结构实现方法。
严蔚敏教授编写的《数据结构(C语言版)》是许多计算机专业学生的必读教材。
以下是对该书课后习题的一些参考答案,供学习者参考。
第一章:绪论1. 数据结构的定义:数据结构是计算机中存储、组织数据的方式,它不仅包括数据元素的类型和关系,还包括数据操作的函数。
2. 数据结构的重要性:数据结构对于提高程序的效率至关重要。
合理的数据结构可以减少算法的时间复杂度和空间复杂度。
第二章:线性表1. 线性表的定义:线性表是由n个元素组成的有限序列,其中n称为线性表的长度。
2. 线性表的顺序存储结构:使用数组来存储线性表的元素,元素的存储关系是连续的。
3. 线性表的链式存储结构:使用链表来存储线性表的元素,每个元素包含数据部分和指向下一个元素的指针。
第三章:栈和队列1. 栈的定义:栈是一种特殊的线性表,只能在一端(栈顶)进行插入和删除操作。
2. 队列的定义:队列是一种特殊的线性表,允许在一端(队尾)进行插入操作,在另一端(队首)进行删除操作。
第四章:串1. 串的定义:串是由零个或多个字符组成的有限序列。
2. 串的存储结构:串可以采用顺序存储结构或链式存储结构。
第五章:数组和广义表1. 数组的定义:数组是由具有相同类型的多个元素组成的集合,这些元素按照索引顺序排列。
2. 广义表的定义:广义表是线性表的推广,其中的元素可以是数据也可以是子表。
第六章:树和二叉树1. 树的定义:树是由节点组成的,其中有一个特定的节点称为根,其余每个节点有且仅有一个父节点。
2. 二叉树的定义:二叉树是每个节点最多有两个子节点的树。
第七章:图1. 图的定义:图是由顶点和边组成的数据结构,可以表示复杂的关系。
2. 图的存储结构:图可以用邻接矩阵或邻接表来存储。
第1章 绪论之巴公井开创作简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和笼统数据类型.解:数据是对客观事物的符号暗示.在计算机科学中是指所有能输入到计算机中并被计算机法式处置的符号的总称.数据元素是数据的基本单元,在计算机法式中通常作为一个整体进行考虑和处置.数据对象是性质相同的数据元素的集合,是数据的一个子集. 数据结构是相互之间存在一种或多种特定关系的数据元素的集合.存储结构是数据结构在计算机中的暗示.数据类型是一个值的集合和界说在这个值集上的一组把持的总称.笼统数据类型是指一个数学模型以及界说在该模型上的一组把持.是对一般数据类型的扩展.试描述数据结构和笼统数据类型的概念与法式设计语言中数据类型概念的区别.解:笼统数据类型包括一般数据类型的概念,但含义比一般数据类型更广、更笼统.一般数据类型由具体语言系统内部界说,直接提供给编程者界说用户数据,因此称它们为预界说数据类型.笼统数据类型通常由编程者界说,包括界说它所使用的数据和在这些数据上所进行的把持.在界说笼统数据类型中的数据部份和把持部份时,要求只界说到数据的逻辑结构和把持说明,不考虑数据的存储结构和把持的具体实现,这样笼统条理更高,更能为其他用户提供良好的使用接口.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和mDestroyRationalNumber(&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 试画出与下列法式段等价的框图.(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)=∑=+ nii i12)1(=∑∑∑∑====+=+=+ninininiiiiii i1121212121)(21)1(21=)32)(1(121)1(41)12)(1(121++=++++nnnnnnnn(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=n n=40 121010=n n=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)(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 n 22log 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) ()()()2223n n n f +=,()()52n n n g n +=解:(1)g(n)快 (2)g(n)快 (3)f(n)快 (4) f(n)快5 试用数学归纳法证明: (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) ()2112n i n i =-∑=()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 阶斐波那契序列的界说为0=f ,01=f ,…,02=-k f ,11=-k f ;kn 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];}1.18 假设有A,B,C,D,E五个高等院校进行田径对立赛,各院校的,并输出.解:typedef enum{A,B,C,D,E} SchoolName;typedef enum{Female,Male} SexType;typedef struct{char event[3]; //项目SexType sex;SchoolName school;int score;} Component;typedef struct{int MaleSum;//男团总分int FemaleSum;//女团总分int TotalSum;//团体总分} Sum;Sum SumScore(SchoolName sn,Component a[],int n){Sum temp;temp.MaleSum=0; temp.FemaleSum=0; temp.TotalSum=0; int i;for(i=0;i<n;i++){ if(a[i].school==sn){if(a[i].sex==Male) temp.MaleSum+=a[i].score;if(a[i].sex==Female) temp.FemaleSum+=a[i].score; } }temp.TotalSum=temp.MaleSum+temp.FemaleSum; return temp; }1.19 试编写算法,计算ii 2!*的值并存入数组a[0..arrsize-1]的第i-1个分量中(i=1,2,…,n).假设计算机中允许的整数最年夜值为maxint,则当n>arrsize 或对某个()n k k ≤≤1,使int max 2!>•kk 时,应按犯错处置.注意选择你认为较好的犯错处置方法.解:#include<iostream.h> #include<stdlib.h> #define MAXINT 65535 #define ArrSize 100 int fun(int i); int main() {int i,k;int a[ArrSize]; cout<<"Enter k:"; cin>>k;if(k>ArrSize-1) exit(0); for(i=0;i<=k;i++){ if(i==0) a[i]=1; else{if(2*i*a[i-1]>MAXINT) exit(0); else a[i]=2*i*a[i-1]; }}for(i=0;i<=k;i++){if(a[i]>MAXINT) exit(0); else cout<<a[i]<<" "; }return 0; }1.20 试编写算法求一元多项式的值()∑==ni ii n x a x P 0的值()0x P n ,并确定算法中每一语句的执行次数和整个算法的时间复杂度.注意选择你认为较好的输入和输出方法.本题的输入为()n i a i ,,1,0 =,0x 和n ,输出为()0x P n .解:#include<iostream.h> #include<stdlib.h> #define N 10double polynomail(int a[],int i,double x,int n); int main() {double x; int n,i; int a[N];cout<<"输入变量的值x:"; cin>>x;cout<<"输入多项式的阶次n:"; cin>>n;if(n>N-1) exit(0);cout<<"输入多项式的系数a[0]--a[n]:"; for(i=0;i<=n;i++) cin>>a[i]; cout<<"The polynomail value is"<<polynomail(a,n,x,n)<<endl; return 0; }double polynomail(int a[],int i,double x,int n) {if(i>0) return a[n-i]+polynomail(a,i-1,x,n)*x;else return a[n];}本算法的时间复杂度为o(n).第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结点的语句序列是__________________.b. 在P结点前拔出S结点的语句序列是__________________.c. 在表首拔出S结点的语句序列是__________________.d. 在表尾拔出S结点的语句序列是__________________.(1) P->next=S;(2) P->next=P->next->next;(3) P->next=S->next;(4) S->next=P->next;(5) S->next=L;(6) S->next=NULL;(7) Q=P;(8) while(P->next!=Q) P=P->next;(9) while(P->next!=NULL) P=P->next;(10) P=Q;(11) P=L;(12) L=S;(13) L=P;解:a. (4) (1)b. (7) (11) (8) (4) (1)c. (5) (12)d. (9) (1) (6)2.7 已知L是带表头结点的非空单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的谜底中选择合适的语句序列.a. 删除P结点的直接后继结点的语句序列是____________________.b. 删除P结点的直接前驱结点的语句序列是____________________.c. 删除P结点的语句序列是____________________.d. 删除首元结点的语句序列是____________________.e. 删除尾元结点的语句序列是____________________.(1) P=P->next;(2) P->next=P;(3) P->next=P->next->next;(4) P=P->next->next;(5) while(P!=NULL) P=P->next;(6) while(Q->next!=NULL) { P=Q; Q=Q->next; }(7) while(P->next!=Q) P=P->next;(8) while(P->next->next!=Q) P=P->next;(9) while(P->next->next!=NULL) P=P->next;(10) Q=P;(11) Q=P->next;(12) P=L;(13) L=L->next;(14) free(Q);解:a. (11) (3) (14)b. (10) (12) (8) (3) (14)c. (10) (12) (7) (3) (14)d. (12) (11) (3) (14)e. (9) (11) (3) (14)2.8 已知P结点是某双向链表的中间结点,试从下列提供的谜底中选择合适的语句序列.a. 在P结点后拔出S结点的语句序列是_______________________.b. 在P结点前拔出S结点的语句序列是_______________________.c. 删除P结点的直接后继结点的语句序列是_______________________.d. 删除P结点的直接前驱结点的语句序列是_______________________.e. 删除P结点的语句序列是_______________________.(1) P->next=P->next->next;(2) P->priou=P->priou->priou;(3) P->next=S;(4) P->priou=S;(5) S->next=P;(6) S->priou=P;(7) S->next=P->next;(8) S->priou=P->priou;(9) P->priou->next=P->next;(10) P->priou->next=P;(11) P->next->priou=P;(12) P->next->priou=S;(13) P->priou->next=S;(14) P->next->priou=P->priou;(15) Q=P->next;(16) Q=P->priou;(17) free(P);(18) free(Q);解:a. (7) (3) (6) (12)b. (8) (4) (5) (13)c. (15) (1) (11) (18)d. (16) (2) (10) (18)e. (14) (9) (17)2.9 简述以下算法的功能.(1) Status A(LinkedList L) { //L是无表头结点的单链表if(L && L->next) {Q=L;L=L->next;P=L;while(P->next) P=P->next;P->next=Q;Q->next=NULL;}return OK;}(2) void BB(LNode *s, LNode *q) {p=s;while(p->next!=q) p=p->next;p->next =s;}void AA(LNode *pa, LNode *pb) {//pa和pb分别指向单循环链表中的两个结点BB(pa,pb);BB(pb,pa);}解:(1) 如果L的长度不小于2,将L的首元结点酿成尾元结点.(2) 将单循环链表拆成两个单循环链表.2.10 指出以下算法中的毛病和低效之处,并将它改写为一个既正确又高效的算法.Status DeleteK(SqList &a,int i,int k){//本过程从顺序存储结构的线性表a中删除第i个元素起的k 个元素if(i<1||k<0||i+k>a.length) return INFEASIBLE;//参数分歧法else {for(count=1;count<k;count++){//删除第一个元素for(j=a.length;j>=i+1;j--) a.elem[j-i]=a.elem[j];a.length--;}return OK;}解:Status DeleteK(SqList &a,int i,int k){//从顺序存储结构的线性表a中删除第i个元素起的k个元素//注意i的编号从0开始int j;if(i<0||i>a.length-1||k<0||k>a.length-i) return INFEASIBLE;for(j=0;j<=k;j++)a.elem[j+i]=a.elem[j+i+k];a.length=a.length-k;return OK;}2.11 设顺序表va中的数据元素递增有序.试写一算法,将x拔出到顺序表的适当位置上,以坚持该表的有序性.解:Status InsertOrderList(SqList &va,ElemType x){//在非递加的顺序表va中拔出元素x并使其仍成为顺序表的算法int i;if(va.length==va.listsize)return(OVERFLOW);for(i=va.length;i>0,x<va.elem[i-1];i--)va.elem[i]=va.elem[i-1];va.elem[i]=x;va.length++;return OK;}2.12 设()m a a A ,,1 =和()n b b B ,,1 =均为顺序表,A '和B '分别为A 和B 中除去最年夜共同前缀后的子表.若='='B A 空表,则B A =;若A '=空表,而≠'B 空表,或者两者均不为空表,且A '的首元小于B '的首元,则B A <;否则B A >.试写一个比力A ,B 年夜小的算法.解:Status CompareOrderList(SqList &A,SqList &B){int i,k,j;k=A.length>B.length?A.length:B.length;for(i=0;i<k;i++){if(A.elem[i]>B.elem[i]) j=1;if(A.elem[i]<B.elem[i]) j=-1;}if(A.length>k) j=1;if(B.length>k) j=-1;if(A.length==B.length) j=0;return j;}2.13 试写一算法在带头结点的单链表结构上实现线性表把持Locate(L,x);解:int LocateElem_L(LinkList &L,ElemType x){int i=0;LinkList p=L;while(p&&p->data!=x){p=p->next;i++;}if(!p) return 0;else return i;}2.14 试写一算法在带头结点的单链表结构上实现线性表把持Length(L).解://返回单链表的长度int ListLength_L(LinkList &L) {int i=0;。
第一章绪论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 || m==k) f=1;else{for(i=0;i<=k-2;i++) temp=0;temp[k-1]=1;temp[k]=1; //初始化sum=1;j=0;for(i=k+1;i<=m;i++,j++) //求出序列第k至第m个元素的值temp=2*sum-temp[j];f=temp[m];}return OK;}//fib分析: k阶斐波那契序列的第m项的值f[m]=f[m-1]+f[m-2]+......+f[m-k]=f[m-1]+f[m-2]+......+f[m-k]+f[m-k-1]-f[m-k-1]=2*f[m-1]-f[m-k-1]所以上述算法的时间复杂度仅为O(m). 如果采用递归设计,将达到O(k^m). 即使采用暂存中间结果的方法,也将达到O(m^2).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[MAXSIZE];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[ 0 ].totalscore+=result.score;if(result.gender==0)score[ 0 ].malescore+=result.score;else score[ 0 ].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 temp;float *p=a;printf("Input number of terms:");scanf("%d",&n);printf("Input value of x:");scanf("%f",&x);printf("Input the %d coefficients from a0 to a%d:\n",n+1,n);p=a;xp=1;sum=0; //xp用于存放x的i次方for(i=0;i<=n;i++){scanf("%f",&temp);sum+=xp*(temp);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[i]>x&&i>=0;i--)va.elem[i+1]=va.elem[i];va.elem[i+1]=x;return OK;}//Insert_SqList2.12int ListComp(SqList A,SqList B)//比较字符表A和B,并用返回值表示结果,值为1,表示A>B;值为-1,表示A<B;值为0,表示A=B{for(i=1;i<=A.length&&i<=B.length;i++)if(A.elem[i]!=B.elem[i])return A.elem[i]>B.elem[i]?1:-1;if(A.length==B.length) return 0;return A.length>B.length?1:-1; //当两个字符表可以互相比较的部分完全相同时,哪个较长,哪个就较大}//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[i]<->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[i]&&B.elem[j]){if(A.elem[i]<B.elem[j]) i++;if(A.elem[i]>B.elem[j]) j++;if(A.elem[i]==B.elem[j]){C.elem[++k]=A.elem[i]; //当发现了一个在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));C=pc;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;}}//while}//LinkList_Intersect2.27void SqList_Intersect_True(SqList &A,SqList B)//求元素递增排列的线性表A和B的元素的交集并存回A中{i=1;j=1;k=0;while(A.elem[i]&&B.elem[j]){if(A.elem[i]<B.elem[j]) i++;else if(A.elem[i]>B.elem[j]) j++;else if(A.elem[i]!=A.elem[k]){A.elem[++k]=A.elem[i]; //当发现了一个在A,B中都存在的元素i++;j++; //且C中没有,就添加到C中}else {i++;j++;}}//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[i]<same)A.elem[m++]=A.elem[i++];//需保留的元素移动到新位置while(i<A.length&&A.elem[i]==same) i++; //跳过相同的元素}}//whilewhile(i<A.length)A.elem[m++]=A.elem[i++]; //A的剩余元素重新存储。