第三章 栈和队列.ppt
《第三章 栈和队列.ppt》由会员分享,可在线阅读,更多相关《第三章 栈和队列.ppt(86页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第三章第三章 栈和队列栈和队列 3.1 栈 3.2 栈的应用举例 3.3 递归 3.4 队列 3.5 队列应用举例【教学目的教学目的】掌握特殊的线性表桟与队列的工作原理,桟与掌握特殊的线性表桟与队列的工作原理,桟与队列的顺序、链式存储结构下操作的实现,理解计算机系队列的顺序、链式存储结构下操作的实现,理解计算机系统中桟和队列的重要作用和应用统中桟和队列的重要作用和应用【教学重点教学重点】桟与队列的工作原理及其操作实现桟与队列的工作原理及其操作实现【教学难点教学难点】入栈和出栈时的栈空和栈满,进栈和出栈时栈入栈和出栈时的栈空和栈满,进栈和出栈时栈顶指针修改的先后顺序,理解多栈,应用栈和利用栈来理
2、顶指针修改的先后顺序,理解多栈,应用栈和利用栈来理解递归,处理循环队列的队空和队满的确定,队列应用。解递归,处理循环队列的队空和队满的确定,队列应用。3.1 栈栈一一 栈的定义及基本操作栈的定义及基本操作栈栈:限定仅在表的一端进行插入和删除操作的线性表:限定仅在表的一端进行插入和删除操作的线性表栈顶栈顶:允许允许进行插入和删除的一端进行插入和删除的一端栈底栈底:不不允许进行插入和删除的一端允许进行插入和删除的一端空栈:不含元素的空表空栈:不含元素的空表入入/压压/进栈进栈:栈的:栈的插入插入操作操作退退/出栈出栈:栈的:栈的删除删除操作操作 例:栈例:栈s=(a1,a2,a3an)即:元素按即
3、:元素按a1 an顺序依次进栈,则第一个出栈的元素?顺序依次进栈,则第一个出栈的元素?栈的特点栈的特点:先进后出先进后出/后进先出后进先出(First In Last Out)又称为又称为FILO/LIFO线性表线性表ADT Stack 数据对象:数据对象:D ai|aiElemSet,i=1,2,.,n,n0 数据关系:数据关系:R1|ai1,aiD,i=2,.,n 约定约定an 端为栈顶,端为栈顶,a1 端为栈底。端为栈底。基本操作:基本操作:InitStack(&S)操作结果:构造一个空栈操作结果:构造一个空栈S。DestroyStack(&S)初始条件:栈初始条件:栈S已存在。已存在。
4、操作结果:栈操作结果:栈S被销毁。被销毁。ClearStack(&S)初始条件:栈初始条件:栈S已存在。已存在。操作结果:将操作结果:将S清为空栈。清为空栈。StackEmpty(S)初始条件:栈初始条件:栈S已存在。已存在。操作结果:若栈操作结果:若栈S为空栈,则返回为空栈,则返回TRUE,否则,否则FALE。StackLength(S)初始条件:栈初始条件:栈S已存在。已存在。操作结果:返回操作结果:返回S的元素个数,即栈的长度。的元素个数,即栈的长度。GetTop(S,&e)初始条件:栈初始条件:栈S已存在且非空。已存在且非空。操作结果:用操作结果:用e返回返回S的栈顶元素。的栈顶元素。
5、Pop(&S,&e)初始条件:栈初始条件:栈S已存在且非空。已存在且非空。操作结果:删除操作结果:删除S的栈顶元素,并用的栈顶元素,并用e返回其值。返回其值。Push(&S,e)初始条件:栈初始条件:栈S已存在。已存在。操作结果:插入元素操作结果:插入元素e为新的栈顶元素。为新的栈顶元素。StackTraverse(S,visit()初始条件:栈初始条件:栈 S 已存在且非空,已存在且非空,visit()为元素的访问函数。为元素的访问函数。操作结果:从栈底到栈顶依次对操作结果:从栈底到栈顶依次对S的每个元素调用函数的每个元素调用函数visit(),一旦一旦visit()失败,则操作失败。失败,
6、则操作失败。ADT Stack栈结构的基本操作:栈结构的基本操作:1、栈初始化:、栈初始化:Init_Stack(S)初始条件:栈初始条件:栈S不存在不存在 操作结果:构造了一个空栈。操作结果:构造了一个空栈。2、销毁栈:、销毁栈:Destroy_Stack(S)初始条件:栈初始条件:栈S已存在已存在 操作结果:销毁一个已存在的栈。操作结果:销毁一个已存在的栈。3、判栈空:、判栈空:Empty_Stack(S)操作结果:若操作结果:若S为空栈返回为为空栈返回为1,否则返回为,否则返回为0。4、入栈:、入栈:Push_Stack(S,x)初始条件:栈初始条件:栈S已存在已存在 操作结果:在栈操作
7、结果:在栈s的顶部插入一个新元素的顶部插入一个新元素x,x成为新的栈顶元素。栈发生成为新的栈顶元素。栈发生 变化变化5、出栈:、出栈:Pop_Stack(S)初始条件:栈初始条件:栈S存在且非空存在且非空 操作结果:栈操作结果:栈S的顶部元素从栈中删除,栈中少了一个元素。栈发生变化的顶部元素从栈中删除,栈中少了一个元素。栈发生变化6、取栈顶元素:、取栈顶元素:GetTop_Stack(S)初始条件:栈初始条件:栈S存在且非空存在且非空 操作结果:栈顶元素作为结果返回,栈不变化操作结果:栈顶元素作为结果返回,栈不变化二、二、栈的顺序存储及操作的实现栈的顺序存储及操作的实现 用一组连续的存储单元依
8、次存放栈中的每个数据元素,并用用一组连续的存储单元依次存放栈中的每个数据元素,并用起始端作为栈底。起始端作为栈底。(顺序栈)(顺序栈)类型定义如下所示:类型定义如下所示:#define MAXSIZE 100typedef struct DataType dataMAXSIZE;int top;SeqStack,*PSeqStack;1、初始化栈:、初始化栈:PSeqStack Init_SeqStack(void)/创建一顺序栈,入口参数无,返回一个指向顺序栈的指针,为零表示创建一顺序栈,入口参数无,返回一个指向顺序栈的指针,为零表示分配空间失败分配空间失败 PSeqStack S;S=(P
9、SeqStack)malloc(sizeof(SeqStack);if(S)Stop=1;return S;2、销毁栈:、销毁栈:顺序栈的销毁操作是初始化操作的逆运算。由于要修改栈顺序栈的销毁操作是初始化操作的逆运算。由于要修改栈的指针变量,所以要将指针地址传给该函数。的指针变量,所以要将指针地址传给该函数。void Destroy_ SeqStack(PSeqStack*S)/销毁顺序栈,入口参数:为要销毁的顺序栈指针地址销毁顺序栈,入口参数:为要销毁的顺序栈指针地址 if(*S)free(*S);*S=NULL;/return;主程序中如何调用主程序中如何调用main()PSeqStack
10、 S;S=Init_SeqStack();Destroy_ SeqStack(&S);3、判栈空:、判栈空:判断栈中是否有元素,只需判断判断栈中是否有元素,只需判断top是否等于是否等于1int Empty_SeqStack(PSeqStack S)/判断栈是否为空,入口参数:顺序栈,返回值:判断栈是否为空,入口参数:顺序栈,返回值:1表示为空,表示为空,0表示非空表示非空 if(Stop=1)return 1;else return 0;清空:清空:stop=1求栈的长度:求栈的长度:stop+14、入栈、入栈 入栈操作是在栈的顶部进行插入一个元素。首先判断栈入栈操作是在栈的顶部进行插入一个
11、元素。首先判断栈是否已满,若满退出,否则,由于栈的是否已满,若满退出,否则,由于栈的top指向栈顶,只要指向栈顶,只要将入栈元素赋到将入栈元素赋到top+1的位置同时的位置同时top+即可即可int Push_SeqStack(PSeqStack S,DataType x)/入口参数:顺序栈,返回值:入口参数:顺序栈,返回值:1表示入栈成功,表示入栈成功,0表示失败。表示失败。if(Stop=MAXSIZE1)/*栈满不能入栈栈满不能入栈*/return 0;else Stop+;SdataStop=x;return 1;5、出栈、出栈 出栈操作是在栈的顶部进行删除操作,首先判断栈是否出栈操作
12、是在栈的顶部进行删除操作,首先判断栈是否为空,若空退出,否则,由于栈的为空,若空退出,否则,由于栈的top指向栈顶,只要修改指向栈顶,只要修改top为为top 1即可:即可:int Pop_SeqStack(PSeqStack S,DataType*x)/删除栈顶元素并保存在删除栈顶元素并保存在*x,入口参数:顺序栈,返回值:入口参数:顺序栈,返回值:1表示出表示出栈成功,栈成功,0表示失败。表示失败。if(Empty_SeqStack(S)/*栈空不能出栈栈空不能出栈*/return 0;else *x=SdataStop;Stop;return 1;6、取栈顶元素、取栈顶元素 取栈顶元素操
13、作是取出栈顶指针取栈顶元素操作是取出栈顶指针top所指的元素值。先判所指的元素值。先判断栈是否为空,若空退出,否则返回断栈是否为空,若空退出,否则返回top 所指单元的值所指单元的值int GetTop_SeqStack(PSeqStack S,DataType*x)/取出栈顶元素,取出栈顶元素,入口参数:顺序栈,被取出的元素指针,这里用指针入口参数:顺序栈,被取出的元素指针,这里用指针带出栈顶值带出栈顶值;返回值:返回值:1表示成功,表示成功,0表示失败。表示失败。if(Empty_SeqStack(S)/*栈空栈空*/return 0;else *x=SdataStop;/*栈顶元素存入栈
14、顶元素存入*x中中*/return(1);若是栈中元素的数目变化范围较大或不清楚栈元素的若是栈中元素的数目变化范围较大或不清楚栈元素的数目,就应该考虑使用数目,就应该考虑使用链式存储结构链式存储结构“链栈链栈”。链栈通。链栈通常用一个常用一个无头结点的单链表表示无头结点的单链表表示。由于栈的插入删除操作只能在一端进行,而对于单链由于栈的插入删除操作只能在一端进行,而对于单链表来说,在首端插入删除结点要比尾端相对地容易一些,表来说,在首端插入删除结点要比尾端相对地容易一些,所以,我们将单链表的首端作为栈顶端,即将单链表的头所以,我们将单链表的首端作为栈顶端,即将单链表的头指针作为栈顶指针。指针作
15、为栈顶指针。三三 栈的链式存储及操作实现栈的链式存储及操作实现栈的链式存储在栈的链式存储在C中可用下列类型定义实现:中可用下列类型定义实现:定义栈的定义栈的节点节点:typedef struct node DataType data;struct node *next;StackNode,*PStackNode;定义定义栈栈:typedef struct PStackNode top;LinkStack,*PLinkStack;PLinkStack S;S=(PLinkStack)malloc(sizeof(LinkStack);1、初始化空栈、初始化空栈 PLinkStack Init_Li
16、nkStack(void)/初始化链栈,入口参数:空,返回值:链栈指针,初始化链栈,入口参数:空,返回值:链栈指针,null表示初始化失表示初始化失败败 PLinkStack S;S=(PLinkStack)malloc(sizeof(LinkStack);if(S)Stop=NULL;return(S);2、销毁栈、销毁栈void Destroy_LinkStack(PLinkStack *LS)/销毁链栈,入口参数:要销毁链栈指针地址,无返回值销毁链栈,入口参数:要销毁链栈指针地址,无返回值 PStackNode p,q;if(*LS)p=(*LS)top;while(p)q=p;p=pn
17、ext;free(q);free(*LS);*LS=NULL;/return;3、判栈空、判栈空int Empty_LinkStack(PLinkStack S)/判断链栈是否为空,入口参数:链栈指针,返回值:判断链栈是否为空,入口参数:链栈指针,返回值:1表示栈空,表示栈空,0表表示栈非空示栈非空 return(Stop=NULL);4、入栈、入栈 int LinkStack Push_LinkStack(PLinkStack S,DataType x)PStackNode p;p=(PStackNode)malloc(sizeof(StackNode));if(!p)printf(“内存溢
18、出内存溢出”);return(0);pdata=x;pnext=Stop;Stop=p;return(1);5、出栈、出栈int Pop_LinkStack(PLinkStack S,DataType*x)PStackNode p;if(Empty_LinkStack(S)printf(“栈空,不能出栈栈空,不能出栈”);return(0);*x=S topdata;p=S top;Stop=Stopnext;free(p);return(1);6、取栈顶元素、取栈顶元素int GetTop_LinkStack(PLinkStack S,DataType *x)/返回值:返回值:1表示出栈成功
19、,表示出栈成功,0表示失败表示失败 if(Empty_LinkStack(S)printf(“栈空栈空”);return(0);*x=S topdata;return(1);例例3.1 数制转换问题数制转换问题 将十进制数将十进制数N转换为转换为r进制的数,其转换方法利用进制的数,其转换方法利用辗转相除法辗转相除法 算法思想如下:算法思想如下:(1)初始化栈,初始化)初始化栈,初始化N为要转换的数,为要转换的数,r为进制数为进制数(2)判断)判断N的值,为的值,为0转(转(4),否则),否则N%r 压入栈压入栈s中中(3)用)用N/r 代替代替 N转(转(2)(4)出栈,出栈序列即为结果)出栈
20、,出栈序列即为结果3.23.2栈的应用举例栈的应用举例typedef int DataType;int conversion(int N,int r)PSeqStack S;/*定义一个顺序栈定义一个顺序栈*/DataType x;if(!r)printf(“基数不能为基数不能为0”);return(0);S=Init_SeqStack();/*初始化栈初始化栈*/if(!S)printf(“栈初始化失败栈初始化失败”);return(0);while(N)Push_SeqStack(S,N%r);/*余数入栈余数入栈*/N=N/r;/*商作为被除数继续商作为被除数继续*/while(!Emp
21、ty_SeqStack(S)/*直到栈空退出循环直到栈空退出循环*/Pop_SeqStack(S,&x);/*弹出栈顶元素弹出栈顶元素*/printf(“%d”,x);/*输出栈顶元素输出栈顶元素*/Destroy_ SeqStack(&S);/*销毁栈销毁栈*/例例3.2 迷宫求解(回溯法)迷宫求解(回溯法)求解思想求解思想:从入口出发,按某一方向向前探索,:从入口出发,按某一方向向前探索,若能走通并且未走过,则继续往前走,若能走通并且未走过,则继续往前走,否则沿原路返回前一点,换下一个方向再继续试探否则沿原路返回前一点,换下一个方向再继续试探 直到找到一条通路,或无路可走又返回到入口点。直
22、到找到一条通路,或无路可走又返回到入口点。在求解过程中,为了保证在到达某一点后不能向前继续行在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一点以便继续从下一个方向向走(无路)时,能正确返回前一点以便继续从下一个方向向前试探,则需要用一个栈保存所能够到达的每一点的下标及前试探,则需要用一个栈保存所能够到达的每一点的下标及从该点前进的方向。从该点前进的方向。1.表示迷宫的数据结构表示迷宫的数据结构2.测试方向测试方向 规定:从当前位置(规定:从当前位置(x,y)向前试探的方向)向前试探的方向从正东沿顺时针从正东沿顺时针方向进行方向进行从某点从某点(x,y)按某一方向按
23、某一方向 d(0v3)到达新点(到达新点(i,j)的坐标:)的坐标:i=x+moved.x;j=y+moved.y;3.栈的设计栈的设计 当到达了某点而无路可走时需返回前一点,再从前一当到达了某点而无路可走时需返回前一点,再从前一点开始向下一个方向继续试探。点开始向下一个方向继续试探。因此,压入栈中的不仅是顺序到达的各点的坐标,而因此,压入栈中的不仅是顺序到达的各点的坐标,而且还要有从前一点到达本点的方向。且还要有从前一点到达本点的方向。栈中元素是一个由行、栈中元素是一个由行、列、方向组成列、方向组成栈元素的设计如下:栈元素的设计如下:typedef struct int x,y,d;/*横纵
24、坐标及方向横纵坐标及方向*/DataType;栈的定义仍然为:栈的定义仍然为:PSeqStack S;4.如何防止重复到达某点,以避免发生死循环如何防止重复到达某点,以避免发生死循环一种方法:另外设置一个标志数组一种方法:另外设置一个标志数组markmn,它的所有元素,它的所有元素 都初始化为都初始化为0,一旦到达了某一点,一旦到达了某一点(i,j)之后,使之后,使 markij 置置1,下次再试探这个位置时就不能再走,下次再试探这个位置时就不能再走 了。了。另一种方法:当到达某点(另一种方法:当到达某点(i,j)后使)后使mazeij 置置 1,以便区,以便区别别 未到达过的点,同样也能起到
25、防止走重复点的目未到达过的点,同样也能起到防止走重复点的目 的。的。本算法采用后者方法,算法结束前可恢复原迷宫。本算法采用后者方法,算法结束前可恢复原迷宫。迷宫求解算法思想如下:迷宫求解算法思想如下:(1)栈初始化)栈初始化;(2)将入口点坐标所走方向()将入口点坐标所走方向(d设为)入栈设为)入栈(3)while(栈不空栈不空)栈顶元素(栈顶元素(x,y,d)出栈)出栈;求出下一个要试探的方向求出下一个要试探的方向d+;while (还有剩余试探方向时即(还有剩余试探方向时即d4)求新点坐标求新点坐标 (i,j);if((i,j)可走)可走)则则 则将(则将(x,y,d)再次入栈)再次入栈;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三章 栈和队列 第三 队列
限制150内