讨论小课堂和习题解答Word文档格式.docx
- 文档编号:18946846
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:63
- 大小:371.11KB
讨论小课堂和习题解答Word文档格式.docx
《讨论小课堂和习题解答Word文档格式.docx》由会员分享,可在线阅读,更多相关《讨论小课堂和习题解答Word文档格式.docx(63页珍藏版)》请在冰豆网上搜索。
i<
n;
i++)
for(j=0;
j<
m;
j++)
A[i][j]=0;
O(m*n)
(2)k=0;
for(i=1;
=n;
i++){
for(j=i;
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(k=j;
k<
k++)
x+=delta;
;
O(n3)
(5)for(i=0,j=n-1;
i<
j;
i++,j--)
{t=a[i];
a[i]=a[j];
a[i]=t;
基本语句共执行了n/2次,T(n)=O(n)
(6)x=0;
for(i=1;
for(j=1;
=n-i;
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++;
⑵方法二:
链式存储结构
{NodeType*p,*q,*s;
p=L;
q=q->
next;
while(q!
=NULL&
q->
data<
=x)
{p=q;
s=newNodeType;
s->
data=x;
p->
next=s;
next=q;
2.观察下面的算法,此算法完成如下功能:
在非递减有序表中删除所有值为X的元素。
问:
如何改进此算法,使得算法效率提高?
voidDeletaz(ElemTypex)
{inti=0,j;
while(i<
length&
elem[i]<
x)i++;
if(i==length)cout<
<
”X不存在”<
endl;
else{while(elem[i]==x)
{for(j=I;
j<
length;
j++)elem[j]=elem[j+1];
length--;
【答案】
voiddelete(ElemTypex)
{inti=0,j,n;
elem[i]<
“nox”<
else{
while(elem[i]==x)
{n++;
i++;
for(j=i;
length-1;
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}
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;
A.length;
i++,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&
m){//查询结点am
ta=ta->
i++;
}//while
if(ta&
ta->
next){//m<
表长
hb=ta->
tb=hb;
while(tb->
next)tb=tb->
//查询表尾bn修改指针
O(ListLength(L))
4.讨论线性表的逻辑结构和存储结构的关系,以及不同存储结构的比较。
【答案】存储结构分为:
⑴顺序存储结构:
借助元素在存储器中的相对位置来表示数据元素间的逻辑关系
链式存储结构:
借助指示元素存储地址的指针表示数据元素间的逻辑关系
⑵数据的逻辑结构—只抽象反映数据元素的逻辑关系
数据的存储(物理)结构—数据的逻辑结构在计算机存储器中的实现
⑶数据的逻辑结构与存储结构密切相关:
算法设计→逻辑结构
算法实现→存储结构
⑷顺序表:
可以实现随机存取:
(1)
插入和删除时需要移动元素:
(n)
需要预分配存储空间;
适用于“不常进行修改操作、表中元素相对稳定”的场合。
链表:
只能进行顺序存取:
插入和删除时只需修改指针:
不需要预分配存储空间;
适用于“修改操作频繁、事先无法估计最大表长”的场合。
——应用问题的算法时间复杂度的比较
例如,以线性表表示集合进行运算的时间复杂度为(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->
Returnn:
5.试设计实现在单链表中删去值相同的多余结点的算法。
(a)为删除前,(b)为删除后。
voidDeletaz(LinklistL)
{Lnode*p,*q,*r,*s;
P=l->
while(p){q=p;
r=q->
while(r){if(r->
data!
=p->
data){q=r;
r=r->
next};
else{s=r->
free(r);
r=s;
}
P=p->
6.有一个线性表(a1,a2,...,an),它存储在有附加表头结点的单链表中,写一个算法,求出该线性表中值为x的元素的序号。
如果x不存在,则输出序号为零。
intlinklist_x(linklistL,datatypex)
{inti=0;
Lnode*p;
P=L->
While(p&
p->
dada!
=x){i++;
If(!
p)return0;
ElsereturnI;
}
7.写一个算法将一单链表逆置。
要求操作在原链表上进行。
voidreverse(LinkListL)
{p=L->
L->
next=NULL;
while(p)
{q=p->
next=L->
next=p;
p=q;
8.在一个非递减有序线性表中,插入一个值为X的元素,使插入后的线性表仍为非递减有序。
分别用向量和单链表编写算法。
voidinsert_x(LinklistL,Datatypex)
/*在递增有序的单链表L中插入值为x的元素,使得插入后L仍然有序*/
{Lnode*p,*q,*r;
P=L;
q=p->
While(q&
dada<
{p=q;
R=(Lnode*)malloc(Lnode);
r->
dada=x;
p->
next=r;
9.写一算法将值为B的结点插在链表中值为a的结点之后。
如果值为a的结点不存在,则插在表尾。
答:
voidInsert_LinkList(LinkListL,DataTypea,DataTypeB)
{/*在值为a的结点后插入值为B的结点,表中若无a则B接在表尾*/
LinkListp,q,s;
s=(LinkList)malloc(sizeof(structnode));
data=B;
q=L;
p=L->
while(p!
=NULL&
=a){q=p;
p=p->
if(p){s->
next=p->
else{s->
next=q->
}
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++){p=q;
q=q->
}/*报数到第m个人*/
printf(“%6d”,q->
num);
/*输出第m个人的编号*/
free(q);
/*第m个人出列*/
q=p->
printf(“%6d\n”,q->
/*输出最后一个结点的编号值*/
}/*outs*/
11.设有两个单链表A、B,其中元素递增有序,编写算法将A、B归并成一个按元素值递减(允许有相同值)有序的链表C,要求用A、B中的原结点形成,不能重新申请结点。
voidunit(LinklistA,LinklistB,LinklistC)
{Lnode*p,*q,*r,*s;
P=A->
q=>
C=A;
r=C;
While(p&
q)
{if(p->
=q->
dada){r=p;
Else{s=q;
s->
next=r->
r->
If(!
p)r->
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放取:
++-++-+-
10111213
334-3……
++-……
v
vN=2
v先放后取:
6时刻,放了4次,3个为溢出
v放取同时:
8时刻,放了5次,3个为溢出
如果同一时刻先放后取:
intmain()
{
int
y=1,i=0,n,m,front=0,rear=1;
cin>
t1;
cin>
t2;
m=n+2;
if(t1>
=t2)cout<
"
error!
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<
"
cout<
y;
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文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 讨论 课堂 习题 解答