ImageVerifierCode 换一换
格式:DOCX , 页数:30 ,大小:48.32KB ,
资源ID:3480746      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3480746.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第三章栈和队列.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第三章栈和队列.docx

1、第三章栈和队列第三章栈和队列教学目的与要求本章的目的是介绍栈和队列的逻辑结构定义及在两种结构上如何实现栈和队列的基本运算。要求在掌握上和队列的特点的基础上,懂得在什么样的情况下能够使用栈和队列。重点与难点本章重点是掌握计算和队列的两种存储结构上实现的基本运算,难点是循环队列中对边界条件的处理。教学内容31栈3.1.1 栈的定义及其运算(1) 栈:是限制仅在表的一端进行插入和删除运算的线性表。允许进行插入和删除的这一端称为栈顶,另一端称为栈底。当表中没有元素时称为空栈。(2) 栈的特点:从定义不难看出栈具有后进先出(Last in first out)的特点,简称为LIFO表。(3) 栈的基本运

2、算:Initstack(S) 构造一个空栈。Stackempty(S) 判定栈是否为空,若为空返回true,否则,返回false。Stackfull(S) 判定栈是否已满,若已满返回true,否则,返回false。该函数只适合于顺序栈。Push(S,x) 进栈操作。若栈不满,则将元素x压入栈顶。Pop(S) 出栈操作。若栈非空,则删除栈顶元素并将该元素返回。Stacktop(S) 读取栈顶元素。若栈S非空,则返回栈顶元素。3.1.2顺序栈1栈的顺序表示与实现由于栈是操作受限制的线性表,所以,线性表的存储结构对栈的也适合。顺序栈类型定义如下:# define Stacksize 100 /假定预

3、分配的栈空间最多为100个元素typedef char datatype; /假定栈元素的数据类型为chartef struct datatype dataStacksize; /用一维向量data作为栈的存储空间 int top; /top为栈顶指针 Seqstack; 可以看出栈被定义为结构类型。在实际应用中,可根据具体情况使用结构型变量或指向结构型变量的指针变量来表示栈。2栈操作中应注意的问题:(设S是指向栈的指针)栈顶指针:S-top;栈顶元素:S-dataS-top;栈空的判定条件:S-top-1;栈满的判定条件:S-topStacksize-1;栈中的元素个数:S-top+1;若S

4、是结构型变量则所涉及操作中的S-应改为S. ;3栈的基本运算在顺序栈上的实现(1)进栈操作(push(Seqstack *S, datatype x))基本步骤:若栈不满,则栈顶指针加1:S-top+; 元素入栈:S-dataS-topx;(2)出栈操作(pop(Seqstack *S)基本步骤:若栈非空,则 读取栈顶元素:xS-dataS-top; 栈顶指针减1:S-top-;返回栈顶元素:return(x);【分析】出栈操作和入栈操作是栈的两种重要操作,应注意操作的判定条件。栈的有效使用空间是0到 Stacksize-1,所以,当S-top-1 时,表示栈空;当S-topStacksize

5、-1时,表示栈满。时间复杂度均为O(1)。3.1.3链栈1链栈及类型定义栈以链式存储方式存储所形成的存储结构,称为链栈。就是单链表。其数据类型定义如下:typedef struct stacknode datatype data; struct stacknode *next; Stacknode;typedef struct Stacknode *stop; Linkstack;Linkstack *s;2链栈操作应注意的问题与链表不同,链栈的插入和删除操作仅限定在表头位置进行,所以,链栈不需要附加头结点。链表的头指针就是链栈的栈顶指针:S-top;栈顶元素为:S-top-data。空栈的判

6、定条件是:S-top=null.;只要系统的备用空间能够分配出存储结点就不会发生上溢。所以,程序员不必考虑链栈栈满的问题。链栈的操作就是单链表的操作,只需注意栈本身的操作要求即可。如:进栈、出栈操作就是在表头进行插入和删除;求栈中的元素个数就是求链表中的结点个数。3.1.4栈的应用举例1设计算法判断一个算术表达式的圆括号是否正确配对 。 (提示:凡遇(就进栈,遇)就退掉栈顶的(,表达式扫描完毕,栈应为空)算法 int bracketsmatch(char a ) /设算术表达式以字符串形式存储在数组中 Seqstack *S;Initstack(S);int k0;while(ak!0) if

7、 (ak() Push(S,(); else if (ak) if (Stackempty(S) return 0; else Pop(S); if (Stackempty(S) return 1;else return 0;2一个双向栈S是在同一向量空间里实现的两个栈,它们的栈底分别设在向量空间的两端。试为此双向栈设计初始化Initstack(S)、入栈push(S,x,i)和出栈pop(i)算法,其中,i为0或1用于指示栈号。算法 #defin maxsize 100 typedef struct node datatype datamaxsize;int top1,top2;Seqsta

8、ck; (1)双向栈的初始化viod Initstack(Seqstack *S) S-top1-1;S-top2maxsize;(2)双向栈入栈算法viod push(Seqstack *S,datatype x,int i) if (S-top1+1S-top2) erroe(overflow); else if(i0) S-top1+; S-dataS-top1x; else S-top2-; S-dataS-top2x; (3)双向栈出栈算法 datatype pop(Seqstack *S,int i)if (i0) if(S-top1-1) error(downflow); els

9、e return S-dataS-top1 elseif (S-top2maxsize)error(downflow );elsereturn S-dataS-top2; 3Ackerman函数的定义如下: n+1 当m0 时 AKM(m,n) AKM(m-1,1) 当m0,n0时 AKM(m-1,AKM(m,n-1) 当m0, n0时请写出递归算法。 算法如下:int akm(int n,int m)if(m0) return n+1; else if (n0&m!0) return akm(m-1,1); else return akm(m-1,akm(m,n-1);32 队列3.2.1

10、队列的定义及其基本运算1队列的概念队列:是一种操作受限的线性表。它只允许在表的一端进行插入,在表的另一端进行删除。允许删除的一端称为的队头(front),允许插入的一端称为队尾(rear)。当队列中没有元素时称为空队列。队列中包含的元素数称为队列的长度。空队列的长度为。2队列的特点:从定义不难看出队列具有先进先出(first in first out)的特点,简称为FIFO表。3队列的基本运算:Initqueue(Q):置空队。构造一个供空队列;Queueempty(Q):判定队列是否为空,为空返回真值,否则返回价假值;Queuefull(Q):判定队列是否已满,若已满返回真值,否则返回价假值

11、;Enqueue(Q,x):入对操作。如果队列不满,则将元素x插入队列;Dequeue(Q):出队操作。若队列非空,则删除队头元素并将其返回;Queuefront(Q):读取队头元素。若队列非空,则返回队头元素。3.2.2顺序队列1顺序队列与循环队列队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表。由于队列的操作总是在表的两端进行,所以设置两个指针分别指向对头和队尾位置。顺序队列存在的“假溢出”现象,使得被删除元素的存储空间永远无法被重新利用,所以顺序队列不能充分利用存储空间。为解决假溢出现象,我们可以将向量空间想象为一个首尾相接的环形结构,并称这种向量为循环向量,存储在其中的

12、队列称为循环队列。通常,我们总是在循环队列上完成队列的操作。2循环队列的类型定义:# define Queuesize 100typedef char datatype;typedef struct datatype dataQueuesize; int front,rear; Cirqueue;这里我们将循环队列的存储结构定义为结构类型Cirqueue。应用时,可根据具体需要将队列定义为结构体变量或指向结构的指针变量。例如:Cirqueue *Q,Q1;其中,Q为指针变量,Q1为结构体变量注意二者访问成员的方法不同。3循环队列应注意的几个问题队头指针和队尾指针在循环意义下加1操作的实现:(向

13、量下标的有效范围下界是0,上界是Queuesize-1) Q-front(Q-front+1)%Queuesize; Q-rear(Q-rear+1)%Queuesize;循环队列队满、队空的判定:为了区别队满和队空,有三种方法可供采用,分别为:方法1:引入一个布尔变量以区别队列的空和满两种状态;方法2:采用少用一个元素的空间的策略,例如:队头指针指向队头元素,队尾指针指向队尾元素下一个位置,则队空的判定条件为:Q-frontQ-rear队满的判定条件为:Q-front(Q-rear+1)%Queuesize;但方法3:引入一个计数器记录队列元素的总数。在众多的参考书中更多地采用的方法2,应对

14、方法2给予足够的重视。4基本运算在循环队列上的实现(队满、队空的判定采用方法2)()入队操作void Enqueue(Cirqueue *Q,datatype x) if (Q-front(Q-rear+1)%Queuesize) error (Queue overflow); else Q-dataQ-rearx; Q-rear(Q-rear+1)%Queuesize; ()出队操作datatype Dequeue(Cirqueue *Q) if (Q-frontQ-rear) error (Queue downflow); else xQ-dataQ-front; Q-front(Q-fr

15、ont+1)%Queuesize;return(x); 【分析】入队、出队操作是队列的两种重要操作。算法采用方法2区别队满和队空,应注意队满和队空的判定条件,以及入队和出队后队尾指针和队头指针在循环队列中的修改(即加1后进行取模运算)。两算法的时间复杂度均为O(1)。3.2.3链队列1链队队列及类型定义队列的链式存储结构简称为链队列。其是限制仅在表头删除和表尾插入的单链表。为了操作方便,一个链队列即设置头指针又设置尾指针。链队列类型描述如下:typedef struct queuenode datatype data; struct queuenode *next;Queuenode; /链队

16、列中的结点结构typedef struct Queuenode *front; /队头指针 Queuenode *rear; /队尾指针 Linkqueue; /将队头指针、队尾指针封装在一个结构类型之中2链队列操作应注意的几个问题链队列可以定义为指针类型,也可以定义为结构类型。例如:Linkqueue *Q, Q1;其中,Q是指针型,Q1是结构类型。应注意二者使用时的区别,作为函数参数,若为加工型操作,则选择指针型,作为引用型操作,则选择结构型。与单链表一样为了操作方便,链队列通常也带头结点。教材中的上算法没有考虑头结点。链队列为空的判定条件:当链队列不带头结点时为:Q-frontNULL;

17、当链队列带头结点时为:Q-rearQ-front 。3队列的基本操作带头结点的链队列上的实现(1)入队操作C语言算法:void enqueue(Linkqueue *Q,datatype x) /将元素x插入队列Q(Q指针型) Queuenode *p; p(Queuenode *)malloc(sizeof(Queuenode);/动态分配新结点 p-datax; p-nextnull; /构造新结点 Q-rear-nextp; Q-rearp; /完成插入操作 ()出队操作C语言算法datatype Dequeue(Linkqueue *Q)/删除队头元素并将其值返回 datatype x

18、; Queuenode *p; If (Q-frontQ-rear) error (queue downflow); /队列若为空,则出错返回pQ-front-next; /工作指针p指向队头元素xp-data;/保存队头元素值 Q-front-nextp-next; / if (Q-rearp) Q-rearQ-front; /删除队头元素后若队列有空,则修改队尾指针free(p);/释放删除结点return(x);/插入和删除算法的时间复杂度均为O(1)。4应用举例算法阅读题如图所示,利用同一循环向量空间实现两个队列,其类型Queue2定义如下:(2003)typedef struct D

19、ataType dataMaxSize;int front2,length2; Queue2;对于i0或1,fronti和lengthi分别为第i个队列的头指针和长度域。请在空缺处填入合适的内容,实现第i个循环队列的入队操作。int EnQueue(Queue2*Q,int i,DataType x)/若第i个队列不满,则元素x入队列,并返回1,否则返回0 if(i1)return 0; if( (1) ) return 0; Q-data (2) x; Q-length (3) +;return 1;【分析】利用同一循环向量空间实现两个循环队列,每个队列分别设置头指针和长度域。以下标i为0或

20、1区分两个队列。若当前队列为第i个,则另一个可表示为(i+1)%2;要实现循环队列的循环机制,在入队、出队确定队头、队尾位置时应以向量长度为模取模,即出队时队头指针为:fronti(fronti+1)%MaxSize入队时队尾位置为:(Q-fronti+Q-lengthi)%MaxSize。算法功能是第i个队列的入队操作,所以算法中(1)处为判断队列是否为满队列;(2)处为第i个队列的队尾位置;(3)指定修改第i个队列的队长。【答案】(1) Q-front(i+1)%2(Q-fronti+Q-lengthi)%MaxSize(2) (Q-fronti+Q-lengthi)%MaxSize(3)

21、 i试题分析与习题1历届试题分析一、选择题:1由两个栈共享一个向量空间的好处是()(2001)A减少存取时间,降低下溢发生的机率B节省存储空间,降低上溢发生的机率C减少存取时间,降低上溢发生的机率D节省存储空间,降低下溢发生的机率【分析】由两个栈共享一个向量空间,使得两个栈的剩余空间可共享,从而节省存储空间,降低上溢发生的机率。【答案】B2设数组datam作为循环队列SQ的存储空间,front为队头指针,rear为队尾指针,则执行出队操作后头指针的值为(2001)Afrontfront+1 Bfront(front+1)%(m-1)Cfront(front-1)%m Dfront(front+

22、1)%m【分析】该题的考核点是循环队列(同类型的题还可以是入队操作时,队尾指针的变化)。模长(数组长度)为m,队头指针后移通过加1实现。所以,正确答案为D。【答案】D3.判定“带头结点的链队列为空”的条件是( )(2003)AQ.frontNULLBQ.rearNULLCQ.frontQ.rearDQ.front!Q.rear【分析】带头结点的链队列为空,即链队列中只有一个头结点,这时头指针和尾指针均指向了头结点。所以,正确答案为C。【答案】C4若进栈序列为a,b,c,则通过入出栈操作可能得到的a,b,c的不同排列个数为( )(2002) A4 B5 C6 D7【分析】若入栈先后次序为a,b,

23、c,则不能得到c,a,b的出栈序列,可得到的序列为:abc,acb,bac,bca,cba。【答案】B二、填空题5栈顶的位置是随着操作而变化(2001)【分析】该题考核点是栈的概念。【答案】入栈和出栈。6假设以S和X分别表示进栈和退栈操作,则对输入序列a,b,c,d,e进行一系列栈操作SSXSXSSXXX之后,得到的输出序列为_。(2002)【分析】该题考核点是栈的特点:先进后出。在入栈序列确定的情况下,入栈、出栈操作的交替次序不同,将会得到不同的出栈序列。【答案】BCEDA7在队列中,允许进行插入操作的一端称为_,允许进行删除操作的一端称为_。(2003)【分析】该题考核点是队列的概念。【答

24、案】队尾、队头8如图两个栈共享一个向量空间,top1和top分别为指向两个栈顶元素的指针,则“栈满”的判定条件是_。(2003)【分析】两个栈共享一个向量空间,两个栈底分别处于向量的两端,而栈顶处于中间,随着入栈操作的进行,当两个栈顶指针相邻时为栈满。【答案】top1+1top2(或top1top2-1)三、算法阅读题9如图所示,利用同一循环向量空间实现两个队列,其类型Queue2定义如下:(2003)typedef struct DataType dataMaxSize; int front2,length2; Queue2;对于i0或1,fronti和lengthi分别为第i个队列的头指针

25、和长度域。请在空缺处填入合适的内容,实现第i个循环队列的入队操作。int EnQueue(Queue2*Q,int i,DataType x)/若第i个队列不满,则元素x入队列,并返回1,否则返回0 if(i1)return 0; if( (1) ) return 0; Q-data (2) x; Q-length (3) +; return 1;【分析】利用同一循环向量空间实现两个循环队列,每个队列分别设置头指针和长度域。以下标i为0或1区分两个队列。若当前队列为第i个,则另一个可表示为(i+1)%2;要实现循环队列的循环机制,在入队、出队确定队头、队尾位置时应以向量长度为模取模,即出队时队

26、头指针为:fronti(fronti+1)%MaxSize入队时队尾位置为:(Q-fronti+Q-lengthi)%MaxSize。算法功能是第i个队列的入队操作,所以算法中(1)处为判断队列是否为满队列;(2)处为第i个队列的队尾位置;(3)指定修改第i个队列的队长。【答案】(1) Q-front(i+1)%2(Q-fronti+Q-lengthi)%MaxSize(2) (Q-fronti+Q-lengthi)%MaxSize(3) i10设栈S(1,2,3,4,5,6,7),其中7为栈顶元素。请写出调用algo(&s)后栈S的状态。(2002) void algo(Stack *S)

27、int i0; Queue Q; Stack T; InitQueue(&Q);InitStack(&T); while (!StackEmpty(S) if(i!i)!0)Push(&T,Pop(&S); else EnQueue(&Q,Pop(&S); while(!QueueEmpty(Q) Push(&S,DeQueue(&Q); while(!StackEmpty(T) Push(&S,Pop(&T); 【分析】该题是栈和队列的综合应用题,其功能是通过工作栈T和队列Q对栈中内容重新排放。算法中第一个循环是将栈S中元素依次出栈,并交替入栈T和入队Q(算法中判断条件(i!i)!0当i为0

28、时成立,当i为1时不成立,i值交替为0和1)。循环结束后T中值为:(7,5,3,1),Q中值为:(6,4,2);第二个循环是将队列Q中的元素依次出队并入栈S,循环结束后S中值为:(6,4,2);第三个循环是将栈T中的元素依次出栈并入栈S,循环结束后S中值为:(6,4,2,1,3,5,7)。【答案】算法结束后S中值为:(6,4,2,1,3,5,7)。11假设两个队列共享一个循环向量空间(参见右下图),其类型 Queue2定义如下:typedef struct Datatype datamaxsizi;int front2, rear2; Queue21;对于i0或1,fronti和reari分别为第i个队列的头指针和尾指针。请对以下算法填空,实现第i个队列的入队操作。(2001)int Enqueue(Queue2 *Q,int i,datatype x) / if (i1)return 0; if(Q-reariQ-front retu

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

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