零基础学数据结构-第4章-栈课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《零基础学数据结构-第4章-栈课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基础 数据结构 课件
- 资源描述:
-
1、第第4章章 栈栈 栈是一种操作受限的线性表。栈具有线性表的结构特点,即每栈是一种操作受限的线性表。栈具有线性表的结构特点,即每一个元素只有一个前驱元素和后继元素(除了第一个元素和最后一一个元素只有一个前驱元素和后继元素(除了第一个元素和最后一个元素外),但它只允许在表的一端进行插入和删除操作。个元素外),但它只允许在表的一端进行插入和删除操作。本章重点和难点:本章重点和难点:1、栈的顺序表示与算法实现、栈的顺序表示与算法实现 2、栈的链式表示与算法实现、栈的链式表示与算法实现 3、求算术表达式的值、求算术表达式的值 4、迷宫求解问题、迷宫求解问题 5、递归的消除、递归的消除4.1 栈的定义与抽
2、象数据类型栈的定义与抽象数据类型4.1.1 什么是栈 栈(栈(stack),也称为堆栈,它是限定仅在表尾进行插入和删除),也称为堆栈,它是限定仅在表尾进行插入和删除操作的线性表。对栈来说,表尾(允许操作的一端)称为栈顶操作的线性表。对栈来说,表尾(允许操作的一端)称为栈顶(top),另一端称为栈底(),另一端称为栈底(bottom)。栈顶是动态变化的,它由一)。栈顶是动态变化的,它由一个称为栈顶指针(个称为栈顶指针(top)的变量指示。当表中没有元素时,称为空栈。)的变量指示。当表中没有元素时,称为空栈。栈的插入操作称为入栈或进栈,删除操作称为出栈或退栈。栈的插入操作称为入栈或进栈,删除操作称
3、为出栈或退栈。4.1 栈的定义与抽象数据类型栈的定义与抽象数据类型 在栈在栈S=(a1,a2,an)中,中,a1称为栈底元素,称为栈底元素,an称为栈顶元素,由栈称为栈顶元素,由栈顶指针顶指针top指示。栈中的元素按照指示。栈中的元素按照a1,a2,an的顺序进栈,当前的顺序进栈,当前的栈顶元素为的栈顶元素为an。如图。如图4.1所示。最先进栈的元素一定是栈底元素,所示。最先进栈的元素一定是栈底元素,最后进栈的元素一定是栈顶元素。每次删除的元素是栈顶元素,也就最后进栈的元素一定是栈顶元素。每次删除的元素是栈顶元素,也就是最后进栈的元素。因此,栈是一种后进先出(是最后进栈的元素。因此,栈是一种后
4、进先出(last in first out,简,简称称LIFO)的线性表。)的线性表。4.1 栈的定义与抽象数据类型栈的定义与抽象数据类型 若将元素若将元素a、b、c和和d依次入栈,最后将栈顶元素出栈,依次入栈,最后将栈顶元素出栈,栈顶指针栈顶指针top的变化情况如图的变化情况如图4.2所示。所示。4.1 栈的定义与抽象数据类型栈的定义与抽象数据类型4.1.2 栈的抽象数据类型 1数据对象集合数据对象集合 栈的数据对象集合为栈的数据对象集合为a1,a2,an,每个元素都有,每个元素都有相同的类型相同的类型DataType。栈中数据元素之间是一对一的关系。栈具有线性表的特栈中数据元素之间是一对一
5、的关系。栈具有线性表的特点:除了第一个元素点:除了第一个元素a1外,每一个元素有且只有一个直接外,每一个元素有且只有一个直接前驱元素,除了最后一个元素前驱元素,除了最后一个元素an外,每一个元素有且只有外,每一个元素有且只有一个直接后继元素。一个直接后继元素。4.1 栈的定义与抽象数据类型栈的定义与抽象数据类型 2 2基本操作集合基本操作集合 (1)InitStack(&S):初始化操作,建立一个空栈:初始化操作,建立一个空栈S。(2)StackEmpty(S):若栈:若栈S为空,返回为空,返回1,否则返回,否则返回0。(3)GetTop(S,&e):返回栈:返回栈S的栈顶元素给的栈顶元素给e
6、。(4)PushStack(&S,e):在栈:在栈S中插入元素中插入元素e,使其成为新的栈顶元,使其成为新的栈顶元素。素。(5)PopStack(&S,&e):删除栈:删除栈S的栈顶元素,并用的栈顶元素,并用e返回其值。返回其值。(6)StackLength(S):返回栈:返回栈S的元素个数。的元素个数。(7)ClearStack(S):清空栈:清空栈S。4.2 栈的顺序表示与实现栈的顺序表示与实现 4.2.1 栈的顺序存储结构 采用顺序存储结构的栈称为顺序栈。顺序栈是利用一组地址连续的采用顺序存储结构的栈称为顺序栈。顺序栈是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,可利用存储
7、单元依次存放自栈底到栈顶的数据元素,可利用C语言中的数组作语言中的数组作为顺序栈的存储结构,同时附设一个栈顶指针为顺序栈的存储结构,同时附设一个栈顶指针top,用于指向顺序栈的,用于指向顺序栈的栈顶元素。当栈顶元素。当top=0时表示空栈。时表示空栈。栈的顺序存储结构类型描述如下:栈的顺序存储结构类型描述如下:#define StackSize 100 typedef struct DataType stackStackSize;int top;SeqStack;中缀表达式6+(7-1)*3+10/2#转换为后缀表达式的处理流程如图4.return 1;如何将中缀表达式转换为后缀表达式呢?vo
8、id ClearStack(SeqStack*S)(2)StackEmpty(S):若栈S为空,返回1,否则返回0。/*将塔座A上按照从小到大自上而下编号为1到n的那个圆盘按照规则搬到塔座C上,B可以作为辅助塔座*/if(S-top0=S-top1)/*如果共享栈已满*/case 1:/*当flag为1,表示将元素进左端的栈*/两个月后,生下一对小兔子,小兔子数共有2对兔子;递归的调用过程也是系统借助栈的特性实现的。(1)后缀表达式与中缀表达式的操作数出现顺序相同,只是运算符先后顺序改变了;递归问题可以被分解成规模小、性质相同的问题加以解决。p=p-next;/*p指向下一个结点,即下一次要释
9、放的结点*/typedef structLStackNode,*LinkStack;转换后的八进制数为(13056)8。【例4_5】通过键盘输入一个表达式,如6+(7-1)*3+10/2,要求将其转换为后缀表达式,并计算该表达式的值。return 0;/*返回0*/case 2:/*当flag为2,表示将元素要进右端的栈*/4.2 栈的顺序表示与实现栈的顺序表示与实现 当栈中元素已经有当栈中元素已经有StackSize个时,称为栈满。如果继续进栈操作则会产生个时,称为栈满。如果继续进栈操作则会产生溢出,称为上溢。对空栈进行删除操作,称为下溢。溢出,称为上溢。对空栈进行删除操作,称为下溢。顺序栈
10、的结构如图顺序栈的结构如图4.3所示。元素所示。元素a、b、c、d、e、f、g、h依次进栈后,依次进栈后,a为栈底元素,为栈底元素,h为栈顶元素。在实际操作中,栈顶指针指向栈顶元素的下一个为栈顶元素。在实际操作中,栈顶指针指向栈顶元素的下一个位置。位置。顺序栈涉及的一些基本操作如下:顺序栈涉及的一些基本操作如下:(1)在初始化栈时,将栈顶指针置为)在初始化栈时,将栈顶指针置为0,即令,即令S.top=0。(2)判断栈空条件为)判断栈空条件为S.top=0,栈满条件为,栈满条件为S.top=StackSize-1。(3)栈的长度(即栈中元素个数)为)栈的长度(即栈中元素个数)为S.top。(4)
11、进栈操作时,先判断栈是否已满,若未满,将元素压入栈中,即)进栈操作时,先判断栈是否已满,若未满,将元素压入栈中,即S.stackS.top=e,然后使栈顶指针加,然后使栈顶指针加1,即,即S.top+。出栈操作时,先判断。出栈操作时,先判断栈是否为空,若为空,使栈顶指针减栈是否为空,若为空,使栈顶指针减1,即,即S.top-,然后元素出栈,即,然后元素出栈,即e=S.stackS.top。4.2 栈的顺序表示与实现栈的顺序表示与实现4.2.2 顺序栈的基本运算顺序栈的基本运算(1)初始化栈。)初始化栈。void InitStack(SeqStack*S)/*初始化栈初始化栈*/S-top=0;
12、/*把栈顶指针置为把栈顶指针置为0*/(2)判断栈是否为空。)判断栈是否为空。int StackEmpty(SeqStack S)/*判断栈是否为空,栈为空返回判断栈是否为空,栈为空返回1,否则返回,否则返回0*/if(S.top=0)/*如果栈顶指针如果栈顶指针top为为0*/return 1;/*返回返回1*/else/*否则否则*/return 0;/*返回返回0*/4.2 栈的顺序表示与实现栈的顺序表示与实现(3)取栈顶元素。)取栈顶元素。int GetTop(SeqStack S,DataType*e)if(S.toptop=StackSize)/*如果栈已满如果栈已满*/print
13、f(“栈已满,不能将元素进栈!栈已满,不能将元素进栈!n”);return 0;else/*否则否则*/S-stackS-top=e;/*元素元素e进栈进栈*/S-top+;/*修改栈顶指针修改栈顶指针*/return 1;4.2 栈的顺序表示与实现栈的顺序表示与实现(5)将栈顶元素出栈。)将栈顶元素出栈。int PopStack(SeqStack*S,DataType*e)if(S-top=0)/*如果栈为空如果栈为空*/printf(“栈中已经没有元素,不能进行出栈操作栈中已经没有元素,不能进行出栈操作!n”);return 0;else/*否则否则*/S-top-;/*先修改栈顶指针,即
14、出栈先修改栈顶指针,即出栈*/*e=S-stackS-top;/*将出栈元素赋给将出栈元素赋给e*/return 1;4.2 栈的顺序表示与实现栈的顺序表示与实现(6)求栈的长度。)求栈的长度。int StackLength(SeqStack S)/*求栈的长度求栈的长度*/return S.top;(7)清空栈。)清空栈。void ClearStack(SeqStack*S)/*清空栈清空栈*/S-top=0;/*将栈顶指针置为将栈顶指针置为0*/4.2 栈的顺序表示与实现栈的顺序表示与实现4.2.3 顺序栈应用举例 【例【例4_1】利用顺序栈的基本操作,将元素】利用顺序栈的基本操作,将元素
15、A、B、C、D、E、F依次进栈,然后将依次进栈,然后将F和和E出栈,再将出栈,再将G和和H进栈,最后将元素全部出进栈,最后将元素全部出栈,并依次输出出栈元素。栈,并依次输出出栈元素。4.2 栈的顺序表示与实现栈的顺序表示与实现 【例【例4_2】有两个栈】有两个栈S1和和S2都采用顺序结构存储,并且共享一个存都采用顺序结构存储,并且共享一个存储区。为了尽可能利用存储空间,减少溢出的可能,采用栈顶相向,储区。为了尽可能利用存储空间,减少溢出的可能,采用栈顶相向,迎面增长的方式,试设计迎面增长的方式,试设计S1和和S2有关入栈和出栈算法。有关入栈和出栈算法。【分析】该题是哈尔滨工业大学的考研试题,主
16、要考察共享栈的算【分析】该题是哈尔滨工业大学的考研试题,主要考察共享栈的算法设计。法设计。1 1什么是栈的共享什么是栈的共享 在使用顺序栈时,因为栈空间的大小难以准确估计,可能会出现有的栈还有空闲空间。为了能充分利用栈的空间,可以让多个栈共享一个足够大的连续存储空间,通过利用栈顶指针能灵活移动的特性,使多个栈存储空间互相补充,存储空间得到有效利用,这就是栈的共享栈的共享。4.2 栈的顺序表示与实现栈的顺序表示与实现 共享栈的数据结构类型描述如下。共享栈的数据结构类型描述如下。typedef struct DataType stackStackSize;int top2;SSeqStack;其中
17、,其中,top0和和top1分别是两个栈的栈顶指针。分别是两个栈的栈顶指针。用一维数组表示的共享栈如图用一维数组表示的共享栈如图4.5所示。所示。4.2 栈的顺序表示与实现栈的顺序表示与实现2 2共享栈的基本运算共享栈的基本运算(1)初始化栈。)初始化栈。void InitStack(SSeqStack*S)/*共享栈的初始化共享栈的初始化*/S-top0=0;S-top1=StackSize-1;4.2 栈的顺序表示与实现栈的顺序表示与实现(2)取栈顶元素。)取栈顶元素。int GetTop(SSeqStack S,DataType*e,int flag)/*取栈顶元素。将栈顶元素值返回给取
18、栈顶元素。将栈顶元素值返回给e,并返回,并返回1表示成功;否则返回表示成功;否则返回0表示失败。表示失败。*/switch(flag)case 1:/*为为1,表示要取左端栈的栈顶元素,表示要取左端栈的栈顶元素*/if(S.top0=0)return 0;*e=S.stackS.top0-1;break;case 2:/*为为2,表示要取右端栈的栈顶元素,表示要取右端栈的栈顶元素*/if(S.top1=StackSize-1)return 0;*e=S.stackS.top1+1;break;default:return 0;return 1;4.2 栈的顺序表示与实现栈的顺序表示与实现(3)
19、将元素)将元素e入栈。入栈。int PushStack(SSeqStack*S,DataType e,int flag)/*将元素将元素e入共享栈。进栈成功返回入共享栈。进栈成功返回1,否则返回,否则返回0*/if(S-top0=S-top1)/*如果共享栈已满如果共享栈已满*/return 0;/*返回返回0,进栈失败,进栈失败*/switch(flag)case 1:/*当当flag为为1,表示将元素进左端的栈,表示将元素进左端的栈*/S-stackS-top0=e;/*元素进栈元素进栈*/S-top0+;/*修改栈顶指针修改栈顶指针*/break;case 2:/*当当flag为为2,表
20、示将元素要进右端的栈,表示将元素要进右端的栈*/S-stackS-top1=e;/*元素进栈元素进栈*/S-top1-;/*修改栈顶指针修改栈顶指针*/break;default:return 0;return 1;/*返回返回1,进栈成功,进栈成功*/4.2 栈的顺序表示与实现栈的顺序表示与实现(4)将栈顶元素出栈。)将栈顶元素出栈。int PopStack(SSeqStack*S,DataType*e,int flag)switch(flag)/*在出栈操作之前,判断哪个栈要进行出栈操作在出栈操作之前,判断哪个栈要进行出栈操作*/case 1:/*为为1,表示左端的栈需要出栈操作,表示左端
21、的栈需要出栈操作*/if(S-top0=0)/*左端的栈为空左端的栈为空*/return 0;/*返回返回0,出栈操作失败,出栈操作失败*/S-top0-;/*修改栈顶指针,元素出栈操作修改栈顶指针,元素出栈操作*/*e=S-stackS-top0;/*将出栈的元素赋给将出栈的元素赋给e*/break;case 2:/*为为2,表示右端的栈需要出栈操作,表示右端的栈需要出栈操作*/if(S-top1=StackSize-1)/*右端的栈为空右端的栈为空*/return 0;/*返回返回0,出栈操作失败,出栈操作失败*/S-top1+;/*修改栈顶指针,元素出栈操作修改栈顶指针,元素出栈操作*/
22、*e=S-stackS-top1;/*将出栈的元素赋给将出栈的元素赋给e*/break;default:return 0;return 1;/*返回返回1,出栈操作成功,出栈操作成功*/4.2 栈的顺序表示与实现栈的顺序表示与实现(5)判断栈是否为空。)判断栈是否为空。int StackEmpty(SSeqStack S,int flag)switch(flag)case 1:/*为为1,表示判断左端的栈是否为空,表示判断左端的栈是否为空*/if(S.top0=0)return 1;break;case 2:/*为为2,表示判断右端的栈是否为空,表示判断右端的栈是否为空*/if(S.top1=
23、StackSize-1)return 1;break;default:printf(“输入的输入的flag参数错误参数错误!”);return-1;return 0;else/*否则*/else if(n=1)转换后的八进制数为(13056)8。/*判断栈是否为空,栈为空返回1,否则返回0*/if(S-top0=S-top1)/*如果共享栈已满*/printf(“栈已空”);(2)StackEmpty(S):若栈S为空,返回1,否则返回0。当n=1时,递归调用开始逐层返回,参数开始出栈,如图4.递归问题可以被分解成规模小、性质相同的问题加以解决。S-top0=0;和、和、(和)分别是匹配的括号
24、,括号的嵌套顺序是任意的,即()和()等为正确的格式,、()和()等为不正确的格式。case 2:/*当flag为2,表示将元素要进右端的栈*/switch(flag)(2)后缀表达式不出现括号。return Ack(m-1,1);else if(n=1)当top=0时表示空栈。(3)将控制转到被调用函数的入口。完整的求解迷宫程序如下。top-next=p。由于链栈的操作都是在链表的表头位置进行,因而链栈的基本操作的时间复杂度均为O(1)。if(*top=(LinkStack)malloc(sizeof(LStackNode)=NULL)4.3 栈的链式表示与实现栈的链式表示与实现 在顺序栈中
25、,由于顺序存储结构需要事先静态分配,而存储规模往往在顺序栈中,由于顺序存储结构需要事先静态分配,而存储规模往往又难以确定,如果栈空间分配过小,可能会造成溢出;如果栈空间分配又难以确定,如果栈空间分配过小,可能会造成溢出;如果栈空间分配过大,又造成存储空间浪费。过大,又造成存储空间浪费。4.3.1 栈的存储结构 栈的链式存储结构是用一组不一定连续的存储单元来存放栈中的数栈的链式存储结构是用一组不一定连续的存储单元来存放栈中的数据元素的。一般来说,当栈中数据元素的数目变化较大或不确定时,使据元素的。一般来说,当栈中数据元素的数目变化较大或不确定时,使用链式存储结构作为栈的存储结构是比较合适的。人们
展开阅读全文