讨论小课堂和习题解答.docx
- 文档编号:5955232
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:63
- 大小:371.11KB
讨论小课堂和习题解答.docx
《讨论小课堂和习题解答.docx》由会员分享,可在线阅读,更多相关《讨论小课堂和习题解答.docx(63页珍藏版)》请在冰豆网上搜索。
讨论小课堂和习题解答
讨论小课堂1
1.算法和程序的区别是什么呢?
【参考答案】:
算法的含义与程序十分相似,但又有区别。
一个程序不一定满足有穷性。
例如,操作系统,只要整个系统不遭破坏,它将永远不会停止,即使没有作业需要处理,它仍处于动态等待中。
因此,操作系统不是一个算法。
另一方面,程序中的指令必须是机器可执行的,而算法中的指令则无此限制。
算法代表了对问题的解,而程序则是算法在计算机上的特定的实现。
一个算法若用程序设计语言来描述,则它就是一个程序。
算法与数据结构是相辅相承的。
解决某一特定类型问题的算法可以选定不同的数据结构,而且选择恰当与否直接影响算法的效率。
反之,一种数据结构的优劣由各种算法的执行来体现。
要设计一个好的算法通常要考虑以下的要求。
⑴正确。
算法的执行结果应当满足预先规定的功能和性能要求。
⑵可读。
一个算法应当思路清晰、层次分明、简单明了、易读易懂。
⑶健壮。
当输入不合法数据时,应能作适当处理,不至引起严重后果。
⑷高效。
有效使用存储空间和有较高的时间效率。
2,你认为应该如何评估一个数据结构或算法的有效性。
【参考答案】:
前提之一是算法的正确性;其二还必须考虑执行算法所耗费的时间和执行算法所耗费的空间(主要是只指辅助空间),以及算法是否易读、易编码和易于调试。
习题1
1.抽象数据类型的定义由哪几部分组成?
【参考答案】:
数据对象、数据关系和基本操作三部分。
2.按数据元素之间的逻辑关系不同,数据结构有哪几类?
【参考答案】:
线性结构、树型结构、图状结构和集合四类。
5.数据结构和数据类型两个概念之间有区别吗?
【参考答案】:
简单地说,数据结构定义了一组按某些关系结合在一起的数组元素。
数据类型不仅定义了一组带结构的数据元素,而且还在其上定义了一组操作。
6.简述线性结构与非线性结构的不同点。
【参考答案】:
线性结构反映结点间的逻辑关系是一对一的,非线性结构反映结点间的逻辑关系是多对多的。
7.
有下列两段描述:
(1)voidpro1()
(2)voidpro2()
{{
n=2;y=0;
While(n%2==0)x=5/y;
n=n+2;printf(“%d,%d\n,x,y);
printf(“%d\n”,n);}
}
这两段描述均不能满足算法的特征,试问它们违反了算法的那些特征?
【参考答案】:
(1)是一个死循环,违反了算法的有穷性特征。
(2)出现除零错误,违反了算法的可行性特征。
8.分析并写出下面的各语句组所代表的算法的时间复杂度。
(1)for(i=0;i for(j=0;j A[i][j]=0; 【参考答案】: O(m*n) (2)k=0; for(i=1;i<=n;i++){ for(j=i;j<=n;j++) k++; } 【参考答案】: O(n2) (3)i=1; while(i<=n) i=i*3; 【参考答案】: 3T(n)≤n即: T(n)≤log3n=O(log3n)所以: T(n)=O(log3n) (4)k=0; for(i=1;i<=n;i++){ for(j=i;j<=n;j++) for(k=j;k<=n;k++) x+=delta;; } 【参考答案】: O(n3) (5)for(i=0,j=n-1;i {t=a[i];a[i]=a[j];a[i]=t;} 【参考答案】: 基本语句共执行了n/2次,T(n)=O(n) (6)x=0; for(i=1;i for(j=1;j<=n-i;j++) x++; 【参考答案】: 因为x++共执行了n-1+n-2+……+1=n(n-1)/2,所以执行时间为O(n2) 讨论小课堂2 1.在一个非递减有序线性表中,插入一个值为X的元素,使插入后的线性表仍为非递减有序。 (注意: 对比顺序存储结构和链式存储结构表示。 ) 【参考答案】 ⑴方法一: 顺序存储结构 voidinsert(ElemTypex) {i=length-1; while(i>=0&&elem[i]>x) {elem[i+1]=elem[i]; i--; } elem[i+1]=x;length++; } ⑵方法二: 链式存储结构 voidinsert(ElemTypex) {NodeType*p,*q,*s; p=L;q=q->next; while(q! =NULL&&q->data<=x) {p=q;q=q->next;} s=newNodeType; s->data=x; p->next=s;s->next=q; } 2.观察下面的算法,此算法完成如下功能: 在非递减有序表中删除所有值为X的元素。 问: 如何改进此算法,使得算法效率提高? voidDeletaz(ElemTypex) {inti=0,j; while(i if(i==length)cout<<”X不存在”< else{while(elem[i]==x) {for(j=I;j length--;} } } 【答案】 voiddelete(ElemTypex) {inti=0,j,n; while(i if(i==length)cout<<“nox”< else{ while(elem[i]==x) {n++;i++;} for(j=i;j elem[j-n]=elem[j]; length=length-n; } } 3.试设计一个算法,将线性表中前m个元素和后n个元素进行互换,即将线性表 (a1,,…,am,b1,b2,…,bn)改变成 (b1,b2,…,bn,a1,a2,…,am) 要求采用顺序存储结构及链式存储结构分别完成,并比较采用这两种存储结构,其算法效率哪种存储结构更好? 【答案】试设计一个算法,顺序表中前m个元素和后n个元素进行互换,即将线性表 (a1,a2,…,am,b1,b2,…,bn)改变成 (b1,b2,…,bn,a1,a2,…,am)。 算法1: 进行三次“逆转顺序表”的操作。 算法2: 从b1开始,从原地删除之后插入到a1之前直至bn。 例如: 具体实例: {a,b,c,d,e,f,g,1,2,3,4,5}改变成{1,2,3,4,5,a,b,c,d,e,f,g} 算法1: voidinvert(ElemTypeR[],ints,intt) /*本算法将数组R中下标自s到t的元素逆置,即将(Rs,Rs+1,…,Rt-1,Rt)改变为(Rt,Rt-1,…,Rs+1,Rs)*/ voidexchange(SqListA;intm){ /*本算法实现顺序表中前m个元素和后n个元素的互换*/ n=A.length–m; invert(A.elem,0,A.length); invert(A.elem,0,n-1); invert(A.elem,n,m+n-1); } 算法2: voidexchange(SqListA,intm){ /*实现顺序表A中前m个元素和后n个元素互换*/ for(i=0;j=m;j x=A.elem[j]; for(k=j;k>i;k--) A.elem[j]=A.elem[j-1]; A.elem[i]=x; } 算法的时间复杂度: 为: O(mn) 算法设计: 将(b1,b2,…,bn)从链表的当前位置上删除之后再插入a1到之前,并将am设为表尾。 voidexchange(SLink&L,intm){ //互换链表中前m个和后n个结点 ta=L;i=0; while(ta&&i ta=ta->next;i++; }//while if(ta&&ta->next){//m<表长 hb=ta->next;tb=hb; while(tb->next)tb=tb->next;//查询表尾bn修改指针 } 算法的时间复杂度: 为: O(ListLength(L)) 4.讨论线性表的逻辑结构和存储结构的关系,以及不同存储结构的比较。 【答案】存储结构分为: ⑴顺序存储结构: 借助元素在存储器中的相对位置来表示数据元素间的逻辑关系 链式存储结构: 借助指示元素存储地址的指针表示数据元素间的逻辑关系 ⑵数据的逻辑结构—只抽象反映数据元素的逻辑关系 数据的存储(物理)结构—数据的逻辑结构在计算机存储器中的实现 ⑶数据的逻辑结构与存储结构密切相关: 算法设计→逻辑结构 算法实现→存储结构 ⑷顺序表: 可以实现随机存取: (1) 插入和删除时需要移动元素: (n) 需要预分配存储空间; 适用于“不常进行修改操作、表中元素相对稳定”的场合。 链表: 只能进行顺序存取: (n) 插入和删除时只需修改指针: (1) 不需要预分配存储空间; 适用于“修改操作频繁、事先无法估计最大表长”的场合。 ——应用问题的算法时间复杂度的比较 例如,以线性表表示集合进行运算的时间复杂度为(n2), 而以有序表表示集合进行运算的时间复杂度为(n) 习题2 1.判断下列概念的正确性 (1)线性表在物理存储空间中也一定是连续的。 (2)链表的物理存储结构具有同链表一样的顺序。 (3)链表的删除算法很简单,因为当删去链表中某个结点后,计算机会自动地将后继的各个单元向前移动。 答: (1) (2)(3)都不正确。 2.有如下图所示线性表,经过daorder算法处理后,线性表发生了什么变化? 画出处理后的线性表。 voiddaorder() {inti,j,n;ElemTypex; n=length/2; for(i=0;i {j=length-i-1; x=elem[i];elem[i]=elem[j];elem[j]=x; } } elem[0]……elem[7]假设length=8 答: 经过daorder算法处理后,线性表发生了逆置。 处理后的线性表为: 3.试比较顺序存储结构和链式存储结构的优缺点。 答: 顺序结构存储时,相邻数据元素的存放地址也相邻,即逻辑结构和存储结构是统一的,,要求内存中存储单元的地址必须是连续的。 优点: 一般情况下,存储密度大,存储空间利用率高。 缺点: (1)在做插入和删除操作时,需移动大量元素; (2)由于难以估计,必须预先分配较大的空间,往往使存储空间不能得到充分利用;(3)表的容量难以扩充。 链式结构存储时,相邻数据元素可随意存放,所占空间分为两部分,一部分存放结点值,另一部分存放表示结点间关系的指针。 优点: 插入和删除元素时很方便,使用灵活。 缺点: 存储密度小,存储空间利用率低。 4.试写出一个计算链表中结点个数的算法,其中指针p指向该链表的第一个结点。 答: intlinklist_num(linklistL,Lnode*p) {intn=0; While(p){n++;p=p->next;} Returnn: } 5.试设计实现在单链表中删去值相同的多余结点的算法。 (a)为删除前,(b)为删除后。 答: voidDeletaz(LinklistL) {Lnode*p,*q,*r,*s; P=l->next; while(p){q=p;r=q->next; while(r){if(r->data! =p->data){q=r;r=r->next}; else{s=r->next;q->next=s;free(r);r=s;} } P=p->next; } } 6.有一个线性表(a1,a2,...,an),它存储在有附加表头结点的单链表中,写一个算法,求出该线性表中值为x的元素的序号。 如果x不存在,则输出序号为零。 答: intlinklist_x(linklistL,datatypex) {inti=0;Lnode*p; P=L->next; While(p&&p->dada! =x){i++;p=p->next;} If(! p)return0; ElsereturnI; } 7.写一个算法将一单链表逆置。 要求操作在原链表上进行。 答: voidreverse(LinkListL) {p=L->next; L->next=NULL; while(p) {q=p->next; p->next=L->next; L->next=p; p=q; } } 8.在一个非递减有序线性表中,插入一个值为X的元素,使插入后的线性表仍为非递减有序。 分别用向量和单链表编写算法。 答: voidinsert_x(LinklistL,Datatypex) /*在递增有序的单链表L中插入值为x的元素,使得插入后L仍然有序*/ {Lnode*p,*q,*r; P=L;q=p->next; While(q&&q->dada<=x) {p=q;q=q->next;} R=(Lnode*)malloc(Lnode); r->dada=x; r->next=q; p->next=r; } 9.写一算法将值为B的结点插在链表中值为a的结点之后。 如果值为a的结点不存在,则插在表尾。 答: voidInsert_LinkList(LinkListL,DataTypea,DataTypeB) {/*在值为a的结点后插入值为B的结点,表中若无a则B接在表尾*/ LinkListp,q,s; s=(LinkList)malloc(sizeof(structnode)); s->data=B;s->next=NULL; q=L;p=L->next; while(p! =NULL&&p->data! =a){q=p;p=p->next;} if(p){s->next=p->next;p->next=s;} else{s->next=q->next;q->next=s;} } 10.试用循环链表为存储结构,写一个约瑟夫(Josephu)问题的算法。 约瑟夫问题是: 有N个人围成一圈,从第i个人开始从1报数,数到m时,此人就出列。 下一个人重新从1开始报数,再数到m时,以一个人出列。 直到所有的人全部出列。 按出列的先后得到一个新的序列。 例如,N=5,i=1,m=3时新的序列应为: 3,1,5,2,4。 答: typedefstructnode/*结点的结构定义*/ {intnum;/*编号子域*/ structnode*next;/*指针域*/ }JOS; voidouts(JOS*h,intm) {inti;JOS*q=h,*p; printf(“\n“); while(q->next! =q) {for(i=1;i printf(“%6d”,q->num);/*输出第m个人的编号*/ p->next=q->next;free(q);/*第m个人出列*/ q=p->next; } printf(“%6d\n”,q->num);/*输出最后一个结点的编号值*/ free(q); }/*outs*/ 11.设有两个单链表A、B,其中元素递增有序,编写算法将A、B归并成一个按元素值递减(允许有相同值)有序的链表C,要求用A、B中的原结点形成,不能重新申请结点。 答: voidunit(LinklistA,LinklistB,LinklistC) {Lnode*p,*q,*r,*s; P=A->next;q=>next;C=A;r=C; While(p&&q) {if(p->dada<=q->dada){r=p;p=p->next;} Else{s=q;q=q->next;s->next=r->next;r->next=s;r=s;} } If(! p)r->next=q;free(B) } 讨论小课堂3 【参考内容】 1.如果输入序列为123456,试问能否通过栈结构得到以下两个序列: 435612和135426;请说明为什么不能实现或如何才能得到。 2.设输入序列为2,3,4,5,6,利用一个栈能得到序列2,5,3,4,6吗? 栈可以用单链表实现吗? 【答案】 1、输入序列为123456,不能得出435612,其理由是,输出序列最后两元素是12,前面4个元素(4356)得到后,栈中元素剩12,且2在栈顶,不可能栈底元素1在栈顶元素2之前出栈。 得到135426的过程如下: 1入栈并出栈,得到部分输出序列1;然后2和3入栈,3出栈,部分输出序列变为: 13;接着4和5入栈,5,4和2依次出栈,部分输出序列变为13542;最后6入栈并退栈,得最终结果135426。 2、不能得到序列2,5,3,4,6。 栈可以用单链表实现,这就是链栈。 由于栈只在栈顶操作,所以链栈通常不设头结点。 3.简述顺序存储队列的“假溢出”现象的避免方法及怎样判定队列满和空的条件。 【答案】: 3、设顺序存储队列用一维数组q[m]表示,其中m为队列中元素个数,队列中元素在向量中的下标从0到m-1。 设队头指针为front,队尾指针是rear,约定front指向队头元素的前一位置,rear指向队尾元素。 当front等于-1时队空,rear等于m-1时为队满。 由于队列的性质(“删除”在队头而“插入”在队尾),所以当队尾指针rear等于m-1时,若front不等于-1,则队列中仍有空闲单元,所以队列并不是真满。 这时若再有入队操作,会造成假“溢出”。 其解决办法有二,一是将队列元素向前“平移”(占用0至rear-front-1);二是将队列看成首尾相连,即循环队列(0..m-1)。 在循环队列下,仍定义front=rear时为队空,而判断队满则用两种办法,一是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满。 另一种解法是“设标记”方法,如设标记tag,tag等于0情况下,若删除时导致front=rear为队空;tag=1情况下,若因插入导致front=rear则为队满。 4.假设有如下图所示的列车调度系统,约定两侧铁道均为单向行驶,入口处有N节硬席或软席车厢(程序中可分别用H和S表示)等待调度,试编写算法,输出对这N节车厢进行调度的操作序列,要求所有的软席车厢被调整到硬席车厢之前。 v【参考答案】: vvoidtrains(char*elem) v{inti,k; vk=0; vfor(i=0;i vif(elem[i]==‘S’)//软席车厢S v{push(); vpop(); v} velse v{push(); vk++} vwhile(k>0){pop();k--;} v} 5.对于一个具有N个单元(N>>2)的循环队列,若从进入第一个元素开始每隔T1个时间单位进入下一个元素,同时从进入第一个元素开始,每隔T2(T2>T1)个时间单位处理完一个元素并令其出队,试编写一个算法,求出在第几个元素进队时将发生溢出。 v【分析】 v时刻t: 0123456789 v个数: 1121223-2232 v放取: ++-++-+- v时刻t: 10111213 v个数: 334-3…… v放取: ++-…… v vN=2 v先放后取: 6时刻,放了4次,3个为溢出 v放取同时: 8时刻,放了5次,3个为溢出 如果同一时刻先放后取: intmain() { int y=1,i=0,n,m,front=0,rear=1; cin>>n;cin>>t1;cin>>t2;m=n+2; if(t1>=t2)cout<<"error! "; else{ while((rear+1)%m! =front) {i++; if(i%t1==0){rear=(rear+1)%m;y++;} if(i%t1==0&&(rear+1)%m==front)break; if(i%t2==0){front=(front+1)%m;} } cout< return0; }} 习题3 1.假定有编号为A、B、C、D的四辆列车,自右向左顺序开进一个栈式结构的站台,如图3.16所示。 可以通过栈来编组然后开出站台。 请写出列车开出站台的顺序有几种? 写出每一种可能的序列。 如果有n辆列车进行编组呢? 如何编程? 注: 每一辆列车由站台向左开出时,均可进栈、出栈开出站台,但不允许出栈后回退。 图3.16火车编组栈 2.已知栈采用链式存储结构,初始时为空,试画出a,b,c,d四个元素依次进栈以后栈的状态,然后再画出此时的栈顶元素出栈后的状态。 3.写出链表栈的取栈顶元素和置栈空的算法。 4.写出计算表达式3+4/25*8-6时,操作数栈和运算符栈的变化情况表。 5.对于给定的十进制正整数N,转换成对应的八进制正整数。 (1)写出递归算法。 (2)写出非递归算法。 6.已知n为大于等于零的整数,试写出计算下列递归函数f(n)的递归和非递归算法。 f(n)= 7.假设如题3.1所述火车调度站的入口处有n节硬席或软席车厢(分别以H和S表示)等待调度。 试编写算法,输出对
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 讨论 课堂 习题 解答
![提示](https://static.bdocx.com/images/bang_tan.gif)