《限定性线性表》PPT课件.ppt
《《限定性线性表》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《限定性线性表》PPT课件.ppt(107页珍藏版)》请在三一办公上搜索。
1、第3章 限定性线性表栈和队列,3.1 栈,3.2 队列,返回主目录,3.3 总结与提高,3.1 栈,3.1.1 栈的定义,3.1.2 栈的表示和实现,3.1.3 栈的应用举例,3.1.4 栈与递归的实现,返回主目录,栈的定义:,栈作为一种限定性线性表,是将线性表的插入和删除运算限制为仅在表的一端进行。通常将表中允许进行插入、删除操作的一端称为栈顶(Top),表的另一端被称为栈底(Bottom)。当栈中没有元素时称为空栈。栈的插入操作被形象地称为进栈或入栈,删除操作称为出栈或退栈。,返回主目录,根据栈定义,每次进栈的元素都被放在原栈顶元素之上而成为新的栈顶,而每次出栈的总是当前栈中“最新”的元素
2、,即最后进栈的元素。因此,栈又称为后进先出的线性表。简称为LIFO表。如下图所示:,进栈、出栈图例,进栈,出栈,进栈,出栈,ana2a1,返回主目录,栈的抽象数据类型定义,关系:栈中数据元素之间是线性关系,数据元素:可以是任意类型的数据,但必须属于同一个数据对象。,基本操作:InitStack(S)2.ClearStack(S)3.IsEmpty(S)4.IsFull(S)5.Push(S,x)6.Pop(S,x)7.GetTop(S,x),返回主目录,3.1.2 栈的表示和实现,栈在计算机中主要有两种基本的存储结构:顺序存储结构和链式存储结构。顺序存储的栈为顺序栈;链式存储的栈为链栈。,返回
3、主目录,1.顺序栈,顺序栈是用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时由于栈的操作的特殊性,还必须附设一个位置指针top(栈顶指针)来动态地指示栈顶元素在顺序栈中的位置。通常以top=-1表示空栈。,返回主目录,栈的顺序存储结构定义如下:,#define Stack_Size 50typedef struct StackElementType elemStack_Size;/*用来存放栈中元素的一维数组*/int top;/*用来存放栈顶元素的下标,top为-1表示空栈*/SeqStack;,返回主目录,顺序栈中的进栈和出栈图例,top,top,t
4、op,top,返回主目录,顺序栈基本操作的实现,1)初始化,void InitStack(SeqStack*S)/*构造一个空栈S*/S-top=-1;,返回主目录,2)进栈,int Push(SeqStack*S,StackElementType x)if(S-top=Stack_Size)return(FALSE);/*栈已满*/S-top+;S-elemS-top=x;return(TRUE);,返回主目录,3)出栈,int Pop(SeqStack*S,StackElementType*x)if(S-top=-1)/*栈为空*/return(FALSE);else*x=S-elemS-
5、top;S-top-;/*修改栈顶指针*/return(TRUE);,返回主目录,4)取栈顶元素,int GetTop(SeqStack S,StackElementType*x)/*将栈S的栈顶元素弹出,放到x所指的存储空间中,但 栈顶指针保持不变*/if(S-top=-1)/*栈为空*/return(FALSE);else*x=S-elemS-top;return(TRUE);,返回主目录,在实现GetTop操作时,也可将参数说明SeqStack*S 改为SeqStack S,也就是将传地址改为传值方式。传值比传地址容易理解,但传地址比传值更节省时间、空间。,注意:,两栈共享技术(双端栈)
6、:,主要利用了栈“栈底位置不变,而栈顶位置动态变化”的特性。首先为两个栈申请一个共享的一维数组空间SM,将两个栈的栈底分别放在一维数组的两端,分别是0,M-1。,共享栈的空间示意为:top0和top1分别为两个栈顶指示器。,top0,top1,Stack:0,M-1,返回主目录,两栈共享的数据结构定义,#define M 100typedef struct StackElementType StackM;int top2;/*top0和top1分别为两个栈顶指示器*/DqStack;,返回主目录,(1)两栈共享的初始化操作算法,void InitStack(DqStack*S)S-top0=-
7、1;S-top1=M;,返回主目录,(2)两栈共享的进栈操作算法,int Push(DqStack*S,StackElementType x,int i)/*把数据元素x压入i号堆栈*/if(S-top0+1=S-top1)/*栈已满*/return(FALSE);switch(i)case 0:S-top0+;S-StackS-top0=x;break;case 1:S-top1-;S-StackS-top1=x;break;default:return(FALSE)/*参数错误*/return(TRUE);,返回主目录,(3)两栈共享的出栈操作算法,int Pop(DqStack*S,St
8、ackElementType*x,int i)/*从i 号堆栈中弹出栈顶元素并送到x中*/switch(i)case 0:if(S-top0=-1)return(FALSE);*x=S-StackS-top0;S-top0-;break;case 1:if(S-top1=M)return(FALSE);*x=S-StackS-top1;S-top1+;break;default:return(FALSE);return(TRUE);,返回主目录,说明读栈顶与退栈顶的处理异同,并标明将已知的退栈顶算法改为读栈顶算法时应做哪些改动。,【思考题】,2.链栈,链栈是采用链表作为存储结构实现的栈。为便于
9、操作,采用带头结点的单链表实现栈。由于栈的插入和删除操作仅限制在表头位置进行,所以链表的表头指针就作为栈顶指针。,链栈的示意图为:,top,top为栈顶指针,始终指向当前栈顶元素前面的头结点。若top-next=NULL,则代表空栈。注意:链栈在使用完毕时,应该释放其空间。,返回主目录,链栈结构的用C语言定义,typedef struct node StackElementType data;struct node*next;LinkStackNode;typedef LinkStackNode*LinkStack;,返回主目录,链栈的进栈操作,int Push(LinkStack top,S
10、tackElementType x)/*将数据元素x压入栈top中*/LinkStackNode*temp;temp=(LinkStackNode*)malloc(sizeof(LinkStackNode);if(temp=NULL)return(FALSE);/*申请空间失败*/temp-data=x;temp-next=top-next;top-next=temp;/*修改当前栈顶指针*/return(TRUE);,返回主目录,链栈的出栈操作,int Pop(LinkStack top,StackElementType*x)/*将栈top的栈顶元素弹出,放到x所指的存储空间中*/LinkS
11、tackNode*temp;temp=top-next;if(temp=NULL)/*栈为空*/return(FALSE);top-next=temp-next;*x=temp-data;free(temp);/*释放存储空间*/return(TRUE);,返回主目录,如果将可利用的空闲结点空间组织成链栈来管理,则申请一个新结点(类似C语言中的malloc函数)相当于链栈的什么操作?归还一个无用结点(类似C语言中的free函数)相当于链栈的什么操作?试分别写出从链栈中申请一个新结点和归还一个空闲结点的算法。,【思考题】,(3)多栈运算,将多个链栈的栈顶指针放在一个一维指针数组中来统一管理,从而
12、实现同时管理和使用多个栈。,#define M 10/*M个链栈*/typedef struct node StackElementType data;struct node*next;LinkStackNode,*LinkStack;LinkStack topM;,用c语言定义,(1)第i号栈的进栈操作int pushi(LinkStack topM,int i,StackElementType x)/*将元素x进入第i号链栈*/LinkStackNode*temp;temp=(LinkStackNode*)malloc(sizeof(LinkStackNode);if(temp=NULL)
13、return(FALSE);/*申请空间失败*/temp-data=x;temp-next=topi-next;topi-next=temp;/*修改当前栈顶指针*/return(TRUE);,(2)第i号栈元素的出栈操作int Pop(LinkStack topM,int i,StackElementType*x)/*将栈top的栈顶元素弹出,放到x所指的存储空间中*/LinkStackNode*temp;temp=topi-next;if(temp=NULL)/*第i号栈为空栈*/return(FALSE);topi-next=temp-next;*x=temp-data;free(tem
14、p);/*释放存储空间*/return(TRUE);,1.数制转换 假设要将十进制数N转换为d进制数,一个简单的转换算法是重复下述两步,直到N等于零:X=N mod d(其中mod为求余运算)N=N div d(其中div为整除运算),3.1.3 栈的应用举例,数制转换算法void Conversion(int N)/*对于任意一个非负十进制数N,打印出与其等值的二进制数*/Stack S;int x;/*S为顺序栈或链栈*/InitStack(,2.括号匹配问题,思想:在检验算法中设置一个栈,若读入的是左括号,则直接入栈,等待相匹配的同类右括号;若读入的是右括号,且与当前栈顶的左括号同类型,
15、则二者匹配,将栈顶的左括号出栈,否则属于不合法的情况。另外,如果输入序列已读尽,而栈中仍有等待匹配的左括号,或者读入了一个右括号,而栈中已无等待匹配的左括号,均属不合法的情况。当输入序列和栈同时变为空时,说明所有括号完全匹配。,返回主目录,算法:,void BracketMatch(char*str)Stack S;int i;char ch;InitStack(else,GetTop(,返回主目录,3.表达式求值,1)无括号算术表达式求值,表达式运算及运算符优先级,3+4*5#+-*/*0 1 2 3,返回主目录,2)算术表达式处理规则,规定优先级表;(2)设置两个栈:OVS(运算数栈)和O
16、PTR(运算符栈);(3)自左向右扫描,遇操作符则与OPTR栈顶优先级比较:当前操作符OPTR栈顶则进OPTR栈;当前操作符 OPTR栈顶,OVS栈顶、次顶和OPTR栈顶,退栈形成运算T(i),T(i)进OVS栈。,返回主目录,返回主目录,无括号算术表达式的处理过程如右图,例:实现A/BC+D*E#的运算过程时栈区变化情况,返回主目录,算法具体描述如下:,int ExpEvaluation()/*读入一个简单算术表达式并计算其值。OPTR和OVS分 别为运算符栈和运算数栈,OPSet为运算符集合*/InitStack(/*用ch逐个读入操作数的各位数码,并转化为十进制数a*/else,swit
17、ch(Compare(GetTop(operator),ch)case=:Pop(,3)带括号算术表达式 首先要了解算术四则运算的规则:从左算到右;先乘除,后加减;先括号内,后括号外。,其次,确定运算符的优先关系。运算符和界限符可统称为算符,它们构成的集合命名为OPS。任意两个前后相继出现的算符1和2之间的优先关系:12,1的优先权高于2。,算符之间的优先关系,实现算符优先算法时需要使用两个工作栈:一个称作运算符栈operator;另一个称作操作数栈operand。算法的基本过程如下:A.初始化操作数栈operand和运算符栈operator,并将表达式起始符“#”压入运算符栈;B.读入表达式
18、中的每个字符,若是操作数则直接进入操作数栈operand,若是运算符,则与运算符栈operator的栈顶运算符进行优先权比较,并做如下处理:,返回主目录,(1)若栈顶运算符的优先级低于刚读入的运算符,则让刚读入的运算符进operator栈;(2)若栈顶运算符的优先级高于刚读入的运算符,则将栈顶运算符退栈,送入,同时将操作数栈operand退栈两次,得到两个操作数a、b,对a、b进行运算后,将运算结果作为中间结果推入operand栈;(3)若栈顶运算符的优先级与刚读入的运算符的优先级相同,说明左右括号相遇,只需将栈顶运算符(左括号)退栈即可。当operator栈的栈顶元素和当前读入的字符均为“#
19、”时,说明表达式起始符“#”与表达式结束符“#”相遇,整个表达式求值完毕。,返回主目录,算法具体描述如下:,int ExpEvaluation()/*读入一个简单算术表达式并计算其值。operator和operand 分别为运算符栈和运算数栈,OPS为运算符集合*/InitStack(/*用ch逐个读入操作数的各位数码,并转化为十进制数a*/else,switch(Compare(GetTop(operator),ch)case:/退栈并将运算结果入栈 Pop(,利用算法EvaluateExpression_reduced对算术表达式3*(7-2)求值,操作过程如下所示。,3.1.4 栈与递归
20、的实现,递归:在定义自身的同时又出现了对自身的调用。直接递归函数:如果一个函数在其定义体内直接调用自己,则称直接递归函数。间接递归函数:如果一个函数经过一系列的中间调用语句,通过其它函数间接调用自己,则称间接递归函数。,返回主目录,1.具有递归特性的问题,1)递归定义的数学函数如二阶Fibonacci数列:,Ackerman函数:,Ackerman函数可用一个简单的C语言函数描述:,int ack(int m,int n)if(m=0)return n+1;else if(n=0)return ack(m-1,1);else return ack(m-1,ack(m,n-1);,我们在后续章节
21、将要学习的一些数据结构,如广义表、二叉树、树等结构其本身均具有固有的递归特性,因此可以自然地采用递归法进行处理。,2)递归数据结构的处理,主函数执行期间运行栈的状态,后调用先返回,3)递归求解方法,许多问题的求解过程可以用递归分解的方法描述,一个典型的例子是著名的汉诺塔问题(hanoi)问题。n阶Hanoi塔问题:假设有三个分别命名为X,Y和Z的塔座,在塔座X上插有n个直径大小各不相同、从小到大编号为1,2,.,n的圆盘。现要求将塔座X上的n个圆盘移至塔座Z上,并仍按同样顺序叠排。,(1)每次只能移动一个圆盘;(2)圆盘可以插在X,Y和Z中的任何一个塔座上;(3)任何时刻都不能将一个较大的圆盘
22、压在较小的圆盘之上。,圆盘移动时必须遵循下列规则:,算法思想:,当n=1时,问题比较简单,只要将编号为1的圆盘从座X直接移动到塔座Z上即可;当n1时,需利用塔座Y作辅助塔座,若能设法将压在编号为n的圆盘上的n-1个圆盘从塔座X(依照上述原则)移至塔座Y上,则可先将编号为n的圆盘从塔座X 移至塔座Z上,然后再将塔座Y上的n-1个圆盘(依照上述原则)移至塔座Z上。而如何将n-1个圆盘从一个塔座移至另一个塔座问题是一个和原问题具有相同特征属性的问题,只是问题的规模小于1,因此可以用同样方法求解。,求解n阶Hanoi塔问题的递归算法,void hanoi(int n,char x,char y,cha
23、r z)/*将塔座X上从上到下编号为1至n,且按直径由小到大叠放的n个圆盘,按规则搬到塔座Z上,Y用作辅助塔座。*/1 2 if(n=1)3 move(x,1,z);/*将编号为1的圆盘从x移动z*/4 else 5 hanoi(n-1,x,z,y);/*将X上编号为1至n-1的圆盘移到y,z作辅助塔*/6 move(x,n,z);/*将编号为n的圆盘从x移到z*/7 hanoi(n-1,y,x,z);/*将y上编号为1至n-1的圆盘移到z,x作辅助塔*/8 9,续,续,递归方法的优点:,对问题描述简洁,结构清晰,程序的正确性容易证明,设计递归算法的方法,递归算法就是在算法中直接或间接调用算法
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 限定性线性表 限定性 线性 PPT 课件
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-5654298.html