C语言版第二版机械工业出版社答案.docx
- 文档编号:24485516
- 上传时间:2023-05-28
- 格式:DOCX
- 页数:133
- 大小:75.60KB
C语言版第二版机械工业出版社答案.docx
《C语言版第二版机械工业出版社答案.docx》由会员分享,可在线阅读,更多相关《C语言版第二版机械工业出版社答案.docx(133页珍藏版)》请在冰豆网上搜索。
C语言版第二版机械工业出版社答案
C语言版第二版机械工业出版社答案
一、基础知识题
1. 简述下列概念
数据,数据元素,数据类型,数据结构,逻辑结构,储备结构,算法。
【解答】数据是信息的载体,是描述客观事物的数、字符,以及所有能输入到运算机中并被运算机程序识别和处理的符号的集合。
数据元素是数据的差不多单位。
在不同的条件下,数据元素又可称为元素、结点、顶点、记录等。
数据类型是对数据的取值范畴、数据元素之间的结构以及承诺施加操作的一种总体描述。
每一种运算机程序设计语言都定义有自己的数据类型。
“数据结构”这一术语有两种含义,一是作为一门课程的名称;二是作为一个科学的概念。
作为科学概念,目前尚无公认定义,一样认为,讨论数据结构要包括三个方面,一是数据的逻辑结构,二是数据的储备结构,三是对数据进行的操作(运算)。
而数据类型是值的集合和操作的集合,能够看作是已实现了的数据结构,后者是前者的一种简化情形。
数据的逻辑结构反映数据元素之间的逻辑关系(即数据元素之间的关联方式或“邻接关系”),数据的储备结构是数据结构在运算机中的表示,包括数据元素的表示及其关系的表示。
数据的运确实是对数据定义的一组操作,运确实是定义在逻辑结构上的,和储备结构无关,而运算的实现则依靠于储备结构。
数据结构在运算机中的表示称为物理结构,又称储备结构。
是逻辑结构在储备器中的映像,包括数据元素的表示和关系的表示。
逻辑结构与运算机无关。
算法是对特定问题求解步骤的一种描述,是指令的有限序列。
其中每一条指令表示一个或多个操作。
一个算法应该具有下列特性:
有穷性、确定性、可行性、输入和输出。
2. 数据的逻辑结构分哪几种,什么缘故说逻辑结构是数据组织的要紧方面?
【解答】数据的逻辑结构分为线性结构和非线性结构。
(也能够分为集合、线性结构、树形结构和图形即网状结构)。
逻辑结构是数据组织的某种“本质性”的东西:
(1)逻辑结构与数据元素本身的形式、内容无关。
(2)逻辑结构与数据元素的相对位置无关。
(3)逻辑结构与所含数据元素的个数无关。
3. 试举一个数据结构的例子,叙述其逻辑结构、储备结构、运算三方面的内容。
【解答】学生成绩表,逻辑结构是线性结构,能够顺序储备(也能够链式储备),运算能够有插入、删除、查询、等等。
4. 简述算法的五个特性,对算法设计的要求。
【解答】算法的五个特性是:
有穷性、确定性、可行性、零至多个输入和一至多个输出。
对算法设计的要求:
正确性,易读性,健壮性,和高的时空间效率(运算速度快,储备空间小)。
5. 设n是正整数,求下列程序段中带@记号的语句的执行次数。
(1)i=1;k=0;
(2)i=1;j=0;
while(i {k=k+50*i;i++;@{if(i>j)j++;@ }elsei++;}@ (3)x=y=0;(4)x=91;y=100; for(i=0;i for(j=0;j {x++;@{x=x-10;y--;@ for(k=0;i y++;@elsex++;@ } 【解答】 (1)n-1 (2)i=⎡n/2⎤j=⎣n/2⎦ (3)n+1,n(n+1),n2,(n+1)n2,n3 (4)100,1000 6. 有实现同一功能的两个算法A1和A2,其中A1的时刻复杂度为Tl=O(2n),A2的时刻复杂度为T2=O(n2),仅就时刻复杂度而言,请具体分析这两个算法哪一个好。 【解答】对算法A1和A2的时刻复杂度T1和T2取对数,得nlog2和2logn。 明显,当n<4时,算法A1好于A2;当n=4时,两个算法时刻复杂度相同;当n>4时,算法A2好于A1。 7. 选择题: 算法分析的目的是() A、找出数据结构的合理性B、研究算法中的输入和输出的关系 C、分析算法的效率以求改进D、分析算法的易明白性和文档特点 【解答】C 二、算法设计题 8. 已知输入x,y,z三个不相等的整数,设计一个“高效”算法,使得这三个数按从小到大输出。 “高效”的含义是用最少的元素比较次数、元素移动次数和输出次数。 voidBest() {//按序输出三个整数的优化算法 inta,b,c,t; scanf(“%d%d%d”,&a,&b,&c); if(a>b) {t=a;a=b;b=t: }//a和b已正序 if(b>c) {t=c;c=b;//c已到位 if(a>t){b=a;a=t;}//a和b已正序 elseb=t; } printf(“%d,%d,%d\n”,a,b,c); //最佳2次比较,无移动;最差3次比较,7个赋值 } 9. 在数组A[n]中查找值为k的元素,若找到则输出其位置i(1≤i≤n),否则输出0作为标志。 设运算法求解此问题,并分析在最坏情形下的时刻复杂度。 【题目分析】从后向前查找,若找到与k值相同的元素则返回其位置,否则返回0。 intSearch(ElemTypeA[n+1],ElemTypek) {i=n; wile(i>=1)&&(A[i]! =k))i--; if(i>=1)returni; elsereturn0; } 当查找不成功时,总的比较次数为n+1次,因此最坏情形下时刻复杂度为O(n)。 第2章线性表 一、基础知识题 2.1试述头指针、头结点、元素结点、首元结点的区别,说明头指针和头结点的作 【解答】指向链表第一个结点(或为头结点或为首元结点)的指针称为头指针。 “头指针”具有标识一个链表的作用,因此经常用头指针代表链表的名字,如链表L既是指链表的名字是L,也是指链表的第一个结点的地址储备在指针变量L中,头指针为“NULL”则表示一个空表。 有时,我们在整个线性链表的第一个元素结点之前加入一个结点,称为头结点,它的数据域能够不储备任何信息(也能够做监视哨或存放线性表的长度等附加信息),指针域中存放的是第一个数据结点的地址,空表时为空。 “头结点”的加入,使插入和删除等操作方便统一。 元素结点即是数据结点,至少包括元素自身信息和其后继元素的地址两个域。 首元结点是指链表中第一个数据元素的结点;为了操作方便,通常在链表的首元结点之前附设一个结点,称为头结点。 2.2分析顺序储备结构和链式储备结构的优缺点,说明何时应该利用何种结构。 【解答】①从空间上来看,当线性表的长度变化较大,难以估量其规模时,选用动态的链表作为储备结构比较合适,但链表除了需要设置数据域外,还要额外设置指针域,因此当线性表长度变化不大,易于事先确定规模时,为了节约储备空间,宜采纳顺序储备结构。 ②从时刻上看,顺序表具有按元素序号随机访问的特点,在顺序表中按序号访问数据元素的时刻复杂度为O (1);而链表中按序号访问的时刻复杂度为O(n)。 因此假如经常按序号访问数据元素,使用顺序表优于链表。 在顺序表中做插入删除操作时,平均移动大约表中一半的元素,因此n较大时顺序表的插入和删除效率低。 在链表中作插入、删除,尽管也要找插入位置,但操作要紧是比较操作。 从那个角度考虑明显链表优于顺序表。 总之,两种储备结构各有长短,选择那一种储备结构,由实际问题中的要紧因素决定。 2.3分析在顺序储备结构下插入和删除结点时平均需要移动多少个结点。 【解答】平均移动表中大约一半的结点,插入操作平均移动个结点,删除操作平均移动个结点。 具体移动的次数取决于表长和插入、删除的结点的位置。 2.4什么缘故在单循环链表中常使用尾指针,若只设头指针,插入元素的时刻复杂度如何? 【解答】单循环链表中不管设置尾指针依旧头指针都能够遍历表中任一个结点。 设置尾指针时,若在表尾进行插入元素或删除第一元素,操作可在O (1)时刻内完成;若只设置头指针,表尾进行插入或删除操作,需要遍历整个链表,时刻复杂度为O(n)。 2.5在单链表、双链表、单循环链表中,若明白指针p指向某结点,能否删除该结点,时刻复杂度如何? 【解答: 】以上三种链表中,若明白指针p指向某结点,都能删除该结点。 双链表删除p所指向的结点的时刻复杂度为O (1),而单链表和单循环链表上删除p所指向的结点的时刻复杂度均为O(n)。 2.6下面算法的功能是什么? LinkedListUnknown(LinkedListla) {LNode*q,*p; if(la&&la->next) {q=la;la=la->next;p=la; while(p->next)p=p->next; p->next=q;q->next=null; } returnla; } 【解答】将首元结点删除并插入到表尾(设链表长度大于1)。 2.7选择题: 在循环双链表的*p结点之后插入*s结点的操作是() la、p->next=s;s->prior=p;p->next->prior=s;s->next=p->next; B、p->next=s;p->next->prior=s;s->prior=p;s->next=p->next; lc、s->prior=p;s->next=p->next;p->next: =s;p->next->prior=s; D、s->prior=p;s>next=p>next;p>next->prior=s;p->next=s; 【解答】D 2.8选择题: 若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用()储备方式最节约时刻。 la.顺序表B.双链表lc.带头结点的双循环链表D.单循环链表 【解答】la 二、算法设计题 2.9设ha和hb分别是两个带头结点的非递减有序单链表的头指针,试设运算法,将这两个有序链表合并成一个非递增有序的单链表。 要求使用原链表空间,表中无重复数据。 【题目分析】因为两链表已按元素值非递减次序排列,将其合并时,均从第一个结点起进行比较,将小的链入链表中,同时后移链表工作指针,若遇值相同的元素,则删除之。 该问题要求结果链表按元素值非递增次序排列,故在合并的同时,将链表结点逆置。 LinkedListUnion(LinkedListha,hb) ∥ha,hb分别是带头结点的两个单链表的头指针,链表中的元素值按递增序排列 ∥本算法将两链表合并成一个按元素值递减次序排列的单链表,并删除重复元素 {pa=ha->next;∥pa是链表ha的工作指针 pb=hb->next;∥pb是链表hb的工作指针 ha->next=null;∥ha作结果链表的头指针,先将结果链表初始化为空 while(pa! =null&&pb! =null)∥当两链表均不为空时作 {while(pa->next&&pa->data==pa->next->data) {u=pa->next;pa->next=u->next;free(u)}∥删除pa链表中的重复元素 while(pb->next&&pb->data==pb->next->data) {u=pb->next;pb->next=u->next;free(u)}∥删除pb链表中的重复元素 if(pa->data {r=pa->next;∥将pa的后继结点暂存于r pa->next=ha->next;∥将pa结点链于结果表中,同时逆置 ha->next=pa; pa=r;∥复原pa为当前待比较结点 } elseif(pb->data {r=pb->next;∥将pb的后继结点暂存于r pb->next=ha->next;∥将pb结点链于结果表中,同时逆置 ha->next=pb; pb=r;∥复原pb为当前待比较结点 } else{u=pb;pb=pb->next;free(u)}∥删除链表pb和pa中的重复元素 }//while(pa! =null&&pb! =null) if(pa)pb=pa;∥幸免再对pa写下面的while语句 while(pb! =null)∥将尚未到尾的表逆置到结果表中 {r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;} returnha }∥算法Union终止 2.10 设la是一个双向循环链表,其表中元素递增有序。 试写一算法插入元素x,使表中元素依旧递增有序。 【问题分析】双向链表的插入与单链表类似,但需修改双向指针。 DLinkedListDInsert(DLinkedListla,ElemTypex) ∥在递增有序的双向循环链表la中插入元素x,使表中元素依旧递增有序 {p=la->next;∥p指向第一元素 la->data=MaxElemType;∥MaxElemType是和x同类型的机器最大值,用做监视哨 while(p->data p=p->next ; s=(DLNode*)malloc(sizeof(DLNode));∥申请结点空间 s->data=x; s->prior=p->prior;s->next=p;∥将插入结点链入链表 p->prior->next=s;p->prior=s; } 2.11 设p指向头指针为la的单链表中某结点,试编写算法,删除结点*p的直截了当前驱结点。 【题目分析】设*p是单链表中某结点,删除结点*p的直截了当前驱结点,要找到*p的前驱结点的前驱*pre。 进行如下操作: u=pre->next;pre->next=u->next;free(u); LinkedListLinkedListDel(LinkedListla,LNode*p) {∥删除单链表la上的结点*p的直截了当前驱结点,假定*p存在 pre=la; if(pre-next==p) printf(“*p是链表第一结点,无前驱\n”) ;exit(0) ;} while(pre->next->next! =p) pre=pre->next; u=pre->next;pre->next=u->next;free(u); return(la); } 2.12 设计一算法,将一个用循环链表表示的稀疏多项式分解成两个多项式,使这两个多项式各自仅有奇次幂或偶次幂项,并要求利用原链表中的结点空间来构造这两个链表。 【题目分析】设循环链表表示的多项式的结点结构为: typedefstructnode {intpower;∥幂 floatcoef;∥系数 ElemTypeother;∥其他信息 structnode*next;∥指向后继的指针 }PNode,*PolyLinkedList; 则能够从第一个结点开始,依照结点的幂是奇数或偶数而将其插入到奇次幂或偶次幂项的链表中。 假定用原链表储存偶次幂,要为奇次幂的链表生成一个表头,为了保持链表中结点的原先顺序,用一个指针指向奇次幂链表的表尾,注意链表分解时不能“断链”。 voidPolyDis(PolyLinkedListpoly) ∥将poly表示的多项式链表分解为各含奇次幂或偶次幂项的两个循环链表 {PolyLinkedListpoly2=(PolyLinkedList)malloc(sizeof(PNode)); ∥poly2表示只含奇次幂的多项式 r2=poly2;∥r2是只含奇次幂的多项式链表的尾指针 r1=poly;∥r1是只含偶次幂的多项式链表当前结点的前驱结点的指针 p=poly->next;∥链表带头结点,p指向第一个元素 while(p! =poly) if(p->power%2)∥处理奇次幂 {r=p->next;∥暂存后继 r2->next=p;∥结点链入奇次幂链表 r2=p;∥尾指针后移 p=r;∥复原当前待处理结点 } else∥处理偶次幂 {r1->next=p;r1=p;p=p->next;} } r->next=poly2;r1->next=poly;∥构成循环链表 }∥PolyDis 2.13 以带头结点的双向链表表示的线性表L=(a1,a2,…,an),试写一时刻复杂度为O(n)的算法,将L改造为L=(a1,a3,…,an,…,a4,a2)。 【题目分析】分析结果链表,易见链表中位置是奇数的结点保持原顺序,而位置是偶数的结点移到奇数结点之后,且以与原先相反的顺序存放。 因此,可从链表第一个结点开始处理,位置是奇数的结点保留不动,位置是偶数的结点插入到链表尾部,并用一指针指向链表尾,以便对偶数结点“尾插入”。 DLinkedListDInvert(DLinkedListL) ∥将双向循环链表L位置是偶数的结点逆置插入到链表尾部 {p=L->next;∥p指向第一元素 Q=p->prior;∥Q指向最后一个元素 pre=L ;∥pre指向链表中位置为奇数的结点的前驱 r=L ;∥r指向链表中偶数结点的尾结点 i=0 ;∥i记录结点序号 while(p ! =Q)∥查找插入位置 {i++ ; if(i%2)∥处理序号为奇数的结点 {p->prior=pre ;pre->next=p ;pre=p;p=p->next;} else∥处理序号为偶数的结点 {u=p ;∥记住当前结点 p=p->next ;∥p指向下个待处理结点 u->prior=r->prior; ∥以下4个语句将结点插入链表尾 u->next=r; r->prior->next=u; r->prior=u; r=u;∥指向新的表尾 } } 2.14 设单向链表的头指针为head,试设运算法,将链表按递增的顺序就地排序。 【题目分析】本题中的“就地排序”,可明白得为不另辟空间,那个地点利用直截了当插入原则把链表整理成递增有序链表。 LinkedListLinkListInsertSort(LinkedListhead) ∥head是带头结点的单链表,本算法利用直截了当插入原则将链表整理成递增的有序链表 {if(head->next! =null)∥链表不为空表 {p=head->next->next;∥p指向第一结点的后继 head->next->next=null; ∥直截了当插入原则认为第一元素有序,然后从第二元素起依次插入 while(p! =null) {r=p->next;∥暂存p的后继 q=head; while(q->next&&q->next->data q=q->next;∥查找插入位置 p->next=q->next;∥将p结点链入链表 q->next=p; p=r; } }} 2.15 已知递增有序的三个单链表分别代表集合A,B和C,设运算法实现A=A∪(B∩C),并使结果链表仍保持递增。 要求算法的时刻复杂度为O(|A|+|B|+|C|)。 其中,|A|为集合A的元素个数。 【题目分析】本题第一求B和C的交集,即求B和C中共有元素,再与A求并集,同时删除重复元素,以保持结果A递增。 LinkedListunion(LinkedListA,B,C) ∥A、B和C均是带头结点的递增有序的单链表,本算法实现A=A∪(B∩C) ∥使结果表A保持递增有序 {pa=A->next;pb=B->next;pc=C->next;∥设置三个工作指针 pre=A;∥pre指向结果链表中当前待合并结点的前驱 A->data=MaxElemType;∥同类型元素最大值,起监视哨作用 while(pa||pb&&pc) {while(pb&&pc) if(pb->data elseif(pb->data>pc->data)pc=pc->next; elsebreak;∥B表和C表有公共元素 if(pb&&pc) {while(pa&&pa->data {pre->next=pa;pre=pa;pa=pa->next;} if(pre->data! =pb->data) {pre->next=pb;pre=pb;pb=pb->next;pc=pc->next;} else{pb=pb->next;pc=pc->next;} ∥若A中已有B,C公共元素,则不再存入结果表 } }∥while(pa||pb&&pc) if(pa)pre->next=pa; elsepre->next=null;∥当B,C无公共元素,将A中剩余链入 }∥算法Union终止 2.16 顺序表la与lb非递减有序,顺序表空间足够大。 试设计一种高效算法,将lb中元素合到la中,使新的la的元素仍保持非递减有序。 高效指最大限度地幸免移动元素。 【题目分析】顺序储备结构的线性表的插入,其时刻复杂度为O(n),平均移动近一半的元素。 线性表la和lb合并时,若从第一个元素开始,一定会造成元素后移,这不符合本题“高效算法”的要求。 应从线性表的最后一个元素开始比较,大者放到最终位置上。 设两线性表的长度各为m和n,则结果表的最后一个元素应在m+n位置上。 如此从后向前,直到第一个元素为止。 SeqListUnion(SeqListla,SeqListlb) ∥la和lb是顺序储备的非递减有序线性表,本算法将lb合并到la中,元素仍非递减有序 {m=la.last;n=lb.last;∥m,n分别为线性表la和lb的长度 k=m+n-1;∥k为结果线性表的工作指针(下标) i=m-1;j=n-1;∥i,j分别为线性表la和lb的工作指针(下标) while(i>=0&&j>=0) if(la.data[i]>=lb.data[j])la.data[k--]=la.data[i--]; elsela.data[k--]=lb.data[j--]; while(j>=0)la.data[k--]=lb.data[j--]; la.last=m+n; returnla; } 【算法讨论】算法中数据移动是要紧操作。 在最佳情形下(lb的最小元素大于la的最大元素),仅将lb的n个元素移(拷贝)到la中,时刻复杂度为O(n),最差情形,la的所有元素都要移动,时刻复杂度为O(m+n)。 因数据合并到la中,因此在退出第一个while循环后,只需要一个while循环,处理lb中剩余元素。 第二个循环只有在lb有剩余元素时才执行,而在la有
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言版 第二 机械工业 出版社 答案
![提示](https://static.bdocx.com/images/bang_tan.gif)