第三章栈和队列Word文档格式.docx

上传人:b****6 文档编号:16386160 上传时间:2022-11-23 格式:DOCX 页数:30 大小:48.32KB
下载 相关 举报
第三章栈和队列Word文档格式.docx_第1页
第1页 / 共30页
第三章栈和队列Word文档格式.docx_第2页
第2页 / 共30页
第三章栈和队列Word文档格式.docx_第3页
第3页 / 共30页
第三章栈和队列Word文档格式.docx_第4页
第4页 / 共30页
第三章栈和队列Word文档格式.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

第三章栈和队列Word文档格式.docx

《第三章栈和队列Word文档格式.docx》由会员分享,可在线阅读,更多相关《第三章栈和队列Word文档格式.docx(30页珍藏版)》请在冰豆网上搜索。

第三章栈和队列Word文档格式.docx

②栈空的判定条件:

top==-1;

栈满的判定条件:

S-top==Stacksize-1;

③栈中的元素个数:

top+1;

④若S是结构型变量则所涉及操作中的S->

应改为S.;

3.栈的基本运算在顺序栈上的实现

(1)进栈操作(push(Seqstack*S,datatypex))

基本步骤:

若栈不满,则

栈顶指针加1:

top++;

元素入栈:

data[S-top]=x;

(2)出栈操作(pop(Seqstack*S))

若栈非空,则

读取栈顶元素:

x=S->

栈顶指针减1:

top--;

返回栈顶元素:

return(x);

【分析】出栈操作和入栈操作是栈的两种重要操作,应注意操作的判定条件。

栈的有效使用空间是0到Stacksize-1,所以,当S->

top==-1时,表示栈空;

当S->

top==Stacksize-1时,表示栈满。

时间复杂度均为O

(1)。

3.1.3链栈

1.链栈及类型定义

栈以链式存储方式存储所形成的存储结构,称为链栈。

就是单链表。

其数据类型定义如下:

typedefstructstacknode{

datatypedata;

structstacknode*next;

}Stacknode;

typedefstruct{

Stacknode*stop;

}Linkstack;

Linkstack*s;

2.链栈操作应注意的问题

与链表不同,链栈的插入和删除操作仅限定在表头位置进行,所以,链栈不需要附加头结点。

链表的头指针就是链栈的栈顶指针:

top;

栈顶元素为:

top->

data。

空栈的判定条件是:

top==null.;

只要系统的备用空间能够分配出存储结点就不会发生上溢。

所以,程序员不必考虑链栈栈满的问题。

链栈的操作就是单链表的操作,只需注意栈本身的操作要求即可。

如:

进栈、出栈操作就是在表头进行插入和删除;

求栈中的元素个数就是求链表中的结点个数。

3.1.4栈的应用举例

1.设计算法判断一个算术表达式的圆括号是否正确配对。

(提示:

凡遇‘(‘就进栈,遇‘)’就退掉栈顶的‘(‘,表达式扫描完毕,栈应为空)

算法

intbracketsmatch(chara[])

{//设算术表达式以字符串形式存储在数组中

Seqstack*S;

Initstack(S);

intk=0;

while(a[k]!

=’\0’)

if(a[k]=='(')Push(S,'(');

elseif(a[k]==')')

if(Stackempty(S))return0;

elsePop(S);

if(Stackempty(S))return1;

elsereturn0;

}

2.一个双向栈S是在同一向量空间里实现的两个栈,它们的栈底分别设在向量空间的两端。

试为此双向栈设计初始化Initstack(S)、入栈push(S,x,i)和出栈pop(i)算法,其中,i为0或1用于指示栈号。

#definmaxsize100

typedefstructnode{

datatypedata[maxsize];

inttop1,top2;

}Seqstack;

(1)双向栈的初始化

viodInitstack(Seqstack*S)

{

S->

top1=-1;

top2=maxsize;

(2)双向栈入栈算法

viodpush(Seqstack*S,datatypex,inti)

{if(S->

top1+1==S->

top2)

erroe(overflow);

else

if(i==0)

{S->

top1++;

top1]=x;

top2--;

top2]=x;

}

(3)双向栈出栈算法

datatypepop(Seqstack*S,inti)

{if(i==0)

if(S->

top1==-1)

error(downflow);

{returnS->

top1]}

if(S->

top2==maxsize)

error(downflow);

else

returnS->

top2];

3.Ackerman函数的定义如下:

n+1当m=0时

AKM(m,n)=AKM(m-1,1)当m≠0,n=0时

AKM(m-1,AKM(m,n-1)) 当m≠0,n≠0时

请写出递归算法。

算法如下:

intakm(intn,intm)

{if(m==0)

returnn+1;

elseif(n==0&

&

m!

=0)

returnakm(m-1,1);

returnakm(m-1,akm(m,n-1));

3.2队列

3.2.1队列的定义及其基本运算

1.队列的概念

队列:

是一种操作受限的线性表。

它只允许在表的一端进行插入,在表的另一端进行删除。

允许删除的一端称为的队头(front),允许插入的一端称为队尾(rear)。

当队列中没有元素时称为空队列。

队列中包含的元素数称为队列的长度。

空队列的长度为0。

2.队列的特点:

从定义不难看出队列具有先进先出(firstinfirstout)的特点,简称为FIFO表。

3.队列的基本运算:

Initqueue(Q):

置空队。

构造一个供空队列;

Queueempty(Q):

判定队列Q是否为空,为空返回真值,否则返回价假值;

Queuefull(Q):

判定队列Q是否已满,若已满返回真值,否则返回价假值;

Enqueue(Q,x):

入对操作。

如果队列不满,则将元素x插入队列Q;

Dequeue(Q):

出队操作。

若队列非空,则删除队头元素并将其返回;

Queuefront(Q):

读取队头元素。

若队列非空,则返回队头元素。

3.2.2顺序队列

1.顺序队列与循环队列

队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表。

由于队列的操作总是在表的两端进行,所以设置两个指针分别指向对头和队尾位置。

顺序队列存在的“假溢出”现象,使得被删除元素的存储空间永远无法被重新利用,所以顺序队列不能充分利用存储空间。

为解决假溢出现象,我们可以将向量空间想象为一个首尾相接的环形结构,并称这种向量为循环向量,存储在其中的队列称为循环队列。

通常,我们总是在循环队列上完成队列的操作。

2.循环队列的类型定义:

#defineQueuesize100

datatypedata[Queuesize];

intfront,rear;

}Cirqueue;

这里我们将循环队列的存储结构定义为结构类型Cirqueue。

应用时,可根据具体需要将队列定义为结构体变量或指向结构的指针变量。

例如:

Cirqueue*Q,Q1;

其中,Q为指针变量,Q1为结构体变量注意二者访问成员的方法不同。

3.循环队列应注意的几个问题

①队头指针和队尾指针在循环意义下加1操作的实现:

(向量下标的有效范围下界是0,上界是Queuesize-1)

Q->

front=(Q->

front+1)%Queuesize;

rear=(Q->

rear+1)%Queuesize;

②循环队列队满、队空的判定:

为了区别队满和队空,有三种方法可供采用,分别为:

方法1:

引入一个布尔变量以区别队列的空和满两种状态;

方法2:

采用少用一个元素的空间的策略,例如:

队头指针指向队头元素,队尾指针指向队尾元素下一个位置,则

队空的判定条件为:

Q-front==Q->

rear

队满的判定条件为:

Q->

front==(Q->

rear+1)%Queuesize;

但方法3:

引入一个计数器记录队列元素的总数。

在众多的参考书中更多地采用的方法2,应对方法2给予足够的重视。

4.基本运算在循环队列上的实现(队满、队空的判定采用方法2)

(1)入队操作

voidEnqueue(Cirqueue*Q,datatypex){

if(Q->

rear+1)%Queuesize)

error("Queueoverflow");

{Q->

data[Q->

rear]=x;

}

(2)出队操作

datatypeDequeue(Cirqueue*Q){

front==Q->

rear)

error("Queuedownflow");

{x=Q->

front];

return(x);

【分析】入队、出队操作是队列的两种重要操作。

算法采用方法2区别队满和队空,应注意队满和队空的判定条件,以及入队和出队后队尾指针和队头指针在循环队列中的修改(即加1后进行取模运算)。

两算法的时间复杂度均为O

(1)。

3.2.3链队列

1.链队队列及类型定义

队列的链式存储结构简称为链队列。

其是限制仅在表头删除和表尾插入的单链表。

为了操作方便,一个链队列即设置头指针又设置尾指针。

链队列类型描述如下:

typedefstructqueuenode{

structqueuenode*next;

}Queuenode;

//链队列中的结点结构

Queuenode*front;

//队头指针

Queuenode*rear;

//队尾指针

}Linkqueue;

//将队头指针、队尾指针封装在一个结构类型之中

2.链队列操作应注意的几个问题

①链队列可以定义为指针类型,也可以定义为结构类型。

Linkqueue*Q,Q1;

其中,Q是指针型,Q1是结构类型。

应注意二者使用时的区别,作为函数参数,若为加工型操作,则选择指针型,作为引用型操作,则选择结构型。

②与单链表一样为了操作方便,链队列通常也带头结点。

教材中的上算法没有考虑头结点。

③链队列为空的判定条件:

当链队列不带头结点时为:

front==NULL;

当链队列带头结点时为:

rear==Q->

front。

3.队列的基本操作带头结点的链队列上的实现

(1)入队操作

C语言算法:

voidenqueue(Linkqueue*Q,datatypex)

{//将元素x插入队列Q(Q指针型)

Queuenode*p;

p=(Queuenode*)malloc(sizeof(Queuenode));

//动态分配新结点

p->

data=x;

next=null;

//构造新结点

rear->

next=p;

rear=p;

//完成插入操作

C语言算法

datatypeDequeue(Linkqueue*Q)

{//删除队头元素并将其值返回

datatypex;

If(Q->

error("queuedownflow");

//队列若为空,则出错返回

p=Q->

front->

next;

//工作指针p指向队头元素

x=p->

data;

//保存队头元素值

next=p->

//

if(Q->

rear==p)

rear=Q->

front;

//删除队头元素后若队列有空,则修改队尾指针

free(p);

//释放删除结点

//

插入和删除算法的时间复杂度均为O

(1)。

4.应用举例

1.算法阅读题

如图所示,利用同一循环向量空间实现两个队列,其类型Queue2定义如下:

(2003)

DataTypedata[MaxSize];

intfront[2],length[2];

}Queue2;

对于i=0或1,front[i]和length[i]分别为第i个队列的头指针和长度域。

请在空缺处填入合适的内容,实现第i个循环队列的入队操作。

intEnQueue(Queue2*Q,inti,DataTypex)

{//若第i个队列不满,则元素x入队列,并返回1,否则返回0

if(i<

0||i>

1)return0;

if(

(1))

return0;

data[

(2)]=x;

length[(3)]++;

return1;

【分析】利用同一循环向量空间实现两个循环队列,每个队列分别设置头指针和长度域。

以下标i为0或1区分两个队列。

若当前队列为第i个,则另一个可表示为(i+1)%2;

要实现循环队列的循环机制,在入队、出队确定队头、队尾位置时应以向量长度为模取模,即出队时队头指针为:

front[i]=(front[i]+1)%MaxSize入队时队尾位置为:

(Q->

front[i]+Q->

length[i])%MaxSize。

算法功能是第i个队列的入队操作,所以算法中

(1)处为判断队列是否为满队列;

(2)处为第i个队列的队尾位置;

(3)指定修改第i个队列的队长。

【答案】

(1)Q->

front[(i+1)%2]==(Q->

length[i])%MaxSize

(2)(Q->

(3)i

试题分析与习题

1.历届试题分析

一、选择题:

1.由两个栈共享一个向量空间的好处是(   )(2001)

A.减少存取时间,降低下溢发生的机率   B.节省存储空间,降低上溢发生的机率

C.减少存取时间,降低上溢发生的机率   D.节省存储空间,降低下溢发生的机率

【分析】由两个栈共享一个向量空间,使得两个栈的剩余空间可共享,从而节省存储空间,降低上溢发生的机率。

【答案】B

2设数组data[m]作为循环队列SQ的存储空间,front为队头指针,rear为队尾指针,则执行出队操作后头指针的值为(2001)

A.front=front+1B.front=(front+1)%(m-1)

C.front=(front-1)%mD.front=(front+1)%m

【分析】该题的考核点是循环队列(同类型的题还可以是入队操作时,队尾指针的变化)。

模长(数组长度)为m,队头指针后移通过加1实现。

所以,正确答案为D。

【答案】D

3..判定“带头结点的链队列为空”的条件是( 

 

)(2003)

A.Q.front==NULL 

           

B.Q.rear==NULL

C.Q.front==Q.rear            

D.Q.front!

=Q.rear

【分析】带头结点的链队列为空,即链队列中只有一个头结点,这时头指针和尾指针均指向了头结点。

所以,正确答案为C。

【答案】C

4.若进栈序列为a,b,c,则通过入出栈操作可能得到的a,b,c的不同排列个数为( 

)(2002)

A.4 

         

B.5 

      

C.6      

D.7

【分析】

若入栈先后次序为a,b,c,则不能得到c,a,b的出栈序列,可得到的序列为:

abc,acb,bac,bca,cba。

二、填空题

5.栈顶的位置是随着     操作而变化(2001)

【分析】该题考核点是栈的概念。

【答案】入栈和出栈。

6.假设以S和X分别表示进栈和退栈操作,则对输入序列a,b,c,d,e进行一系列栈操作SSXSXSSXXX之后,得到的输出序列为________。

(2002)

【分析】该题考核点是栈的特点:

先进后出。

在入栈序列确定的情况下,入栈、出栈操作的交替次序不同,将会得到不同的出栈序列。

【答案】BCEDA

7.在队列中,允许进行插入操作的一端称为____________,允许进行删除操作的一端称为____________。

【分析】该题考核点是队列的概念。

【答案】队尾、队头

8.如图两个栈共享一个向量空间,top1和top分别为指向两个栈顶元素的指针,则“栈满”的判定条件是____________。

【分析】两个栈共享一个向量空间,两个栈底分别处于向量的两端,而栈顶处于中间,随着入栈操作的进行,当两个栈顶指针相邻时为栈满。

【答案】top1+1==top2(或top1==top2-1)

三、算法阅读题

9.如图所示,利用同一循环向量空间实现两个队列,其类型Queue2定义如下:

DataTypedata[MaxSize];

intfront[2],length[2];

if( 

(1) 

data[ 

(2) 

]=x;

length[ 

(3) 

]++;

return1;

10.设栈S=(1,2,3,4,5,6,7),其中7为栈顶元素。

请写出调用algo(&

s)后栈S的状态。

voidalgo(Stack*S)

{

inti=0;

QueueQ;

StackT;

InitQueue(&

Q);

InitStack(&

T);

while(!

StackEmpty(S))

if((i=!

i)!

=0)Push(&

T,Pop(&

S));

elseEnQueue(&

Q,Pop(&

 

while(!

QueueEmpty(Q))

Push(&

S,DeQueue(&

Q));

StackEmpty(T))

S,Pop(&

T));

【分析】该题是栈和队列的综合应用题,其功能是通过工作栈T和队列Q对栈中内容重新排放。

算法中第一个循环是将栈S中元素依次出栈,并交替入栈T和入队Q(算法中判断条件(i=!

=0当i为0时成立,当i为1时不成立,i值交替为0和1)。

循环结束后T中值为:

(7,5,3,1),Q中值为:

(6,4,2);

第二个循环是将队列Q中的元素依次出队并入栈S,循环结束后S中值为:

第三个循环是将栈T中的元素依次出栈并入栈S,循环结束后S中值为:

(6,4,2,1,3,5,7)。

【答案】算法结束后S中值为:

11.假设两个队列共享一个循环向量空间(参见右下图),其类型Queue2定义如下:

Datatypedata[maxsizi];

intfront[2],rear[2];

}Queue21;

对于i=0或1,front[i]和rear[i]分别为第i个队列的头指针和尾指针。

请对以下算法填空,实现第i个队列的入队操作。

(2001)

intEnqueue(Queue2*Q,inti,datatypex)

{//

if(i<

1) return0;

if(Q->

rear[i]==Q->

front[ ①]retu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1