第3章栈和队列.ppt
《第3章栈和队列.ppt》由会员分享,可在线阅读,更多相关《第3章栈和队列.ppt(105页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、3.1 栈的类型定义栈的类型定义3.2 栈类型的实现栈类型的实现3.3 栈的应用举例栈的应用举例3.4 队列的类型定义队列的类型定义3.5 队列类型的实现队列类型的实现3.1 栈的类型定义一、栈的定义一、栈的定义 栈栈(stack)(stack)作为一种限定性线性表,是将线性表的插插入入和删删除除运算限制为仅在表的一端仅在表的一端进行。栈顶栈顶(Top):(Top):表中允许进行插入、删除操作的一端表中允许进行插入、删除操作的一端栈底栈底(Bottom):(Bottom):同时表的另一端为固定的一端同时表的另一端为固定的一端空栈空栈:栈中没有元素。栈的插入操作被称为进栈、入栈或压入进栈、入栈或
2、压入栈的删除操作被称为出栈、退栈或弹出出栈、退栈或弹出。栈是一种后进先出(Last In First Out)的线性表,简称为LIFO表。例例:设设一一个个栈栈的的输输入入序序列列为为A,B,C,D,则则借借助助一一个栈所得到的输出序列不可能是个栈所得到的输出序列不可能是 。(A)A,B,C,D(B)D,C,B,A (C)A,C,D,B(D)D,A,B,C本题答案为本题答案为D二、栈的抽象数据类型定义二、栈的抽象数据类型定义 ADT Stack 数据对象数据对象:D ai|ai ElemSet,i=1,2,.,n,n0 数据关系数据关系:R1|ai-1,aiD,i=2,.,n 约定an 端为栈
3、顶,a1 端为栈底。基本操作:基本操作:ADT Stack置空栈setnull(s):将栈S设置成空栈,即不管栈的原来状态如何一律置为空栈;判栈空empty(s):返回一个布尔值,当栈S为空时返回1,否则返回0;push(s,x)把元素x压入栈s中,成为新的栈顶元素a1a2anx pop(s,e)从栈顶弹出栈顶元素并返回1(成功),当栈S为空时返回0(不成功)a1a2anan-1 gettop(s,e)栈不空时读取栈s的栈顶元素,并返回1(成功),当栈s为空时返回0(不成功)a1a2an 3.2 栈类型的实现顺序栈顺序栈链栈链栈/-栈的顺序存储表示栈的顺序存储表示-#define MAXSIZ
4、E 100typedef struct elemtype dataMAXSIZE;int top;seqstack;seqstack*s;类似于线性表的顺序映象实现,指向表尾的指针可以作为栈顶指针。栈顶指针top与数据元素之间的关系v通常把0下标端设为栈底,栈空条件:栈顶指针top=-1栈满条件:栈顶指针top=MAXSIZE-1;v入栈时:s-top+,然后数据元素进栈;v出栈时在读出栈顶数据元素后,s-top-。v在栈满时做入栈操作会产生空间不足的情况,简称上溢(overflow);v而在栈空时做出栈操作会产生无元素可出的情况,简称下溢(underflow)。v上溢和下溢两种情况均应该避免
5、,而栈空在应用中通常作为算法(或程序)的控制转移条件。顺序栈的基本运算空栈操作置空栈算法 void setnull(seqstack*s)/*不不论论栈栈S状状态态如如何何,都置都置top为为-1*/s-top=-1;判栈空算法 int empty(seqstack*s)/*依依top值值,在在空空栈栈时返回时返回1,否则返回,否则返回0*/if(s-top=-1)return 1;else return 0;顺序栈的基本运算进栈int push(seqstack*s,elemtype x)/*把把元元素素x压压入入栈栈s中中*/if(s-top=MAXSIZE-1)return 0;/*栈上
6、溢进栈不成功返回栈上溢进栈不成功返回0标志标志*/else s-top+;/*栈顶指针加栈顶指针加1*/s-datas-top=x;/*元素元素x进栈进栈*/return 1;/*进栈成功返回进栈成功返回1标志标志*/顺序栈的基本运算出栈int pop(seqstack*s,elemtype&e)if(s-top=-1)return 0;/栈栈空返回空返回0 else s-top-;/*栈顶指针减栈顶指针减1*/e=s-datas-top+1;/*原原栈栈顶顶元元素素的的值值赋赋给给e*/return 1;顺序栈的基本运算读栈顶元素int gettop(seqstack*s,elemtype&
7、e)/*读栈顶元素读栈顶元素*/if(s-top=-1)return 0;/*栈空无元素返回栈空无元素返回0*/else e=s-datas-top;/*栈顶元素值赋给栈顶元素值赋给e*/return 1;栈的共享栈的共享为了充分利用各个栈的存储空间,这时可以采用多个栈共享存储单元,即给多个栈分配一个足够大的存储空间,让多个栈实现存储空间优势互补。两个栈共享的类型定义:两个栈共享的类型定义:typedef struct elemtype stackm;/*m为数组长度,依具体问为数组长度,依具体问题题 而定而定*/int top2;/*top0和和top1分别为两栈的栈顶指分别为两栈的栈顶指针
8、针*/sharedstack;栈空:栈空:s-top0=-1;s-top1=m;栈满:栈满:s-top0+1=s-top1栈空与栈满条件?栈空与栈满条件?两栈共享的基本运算置空栈void setnull(sharedstack*s)s-top0=-1;/*0号栈空为号栈空为-1*/s-top1=m;/*1号栈空为号栈空为m*/两栈共享的基本运算进栈int push(sharedstack*s,int i,elemtype x)/*i=0,1为两栈的编号,算法把元素为两栈的编号,算法把元素x压入栈压入栈si 中中*/if(i1|s-top0+1=s-top1)return 0;else if(i
9、=0)s-stack+s-top0=x;else s-stack-s-top1=x;return 1;两栈共享的基本运算出栈int pop(sharedstack*s,int i,elemtype&e)/*弹出弹出i号栈的栈顶元素号栈的栈顶元素*/if(i1)return 0;/*参数出错无法弹出参数出错无法弹出*/else if(i=0)if(s-top0=-1)return 0;/*0号栈无法弹出号栈无法弹出*/else e=s-stacks-top0-;return 1;else if(s-top1=m)return 0;/*1号栈无法弹出号栈无法弹出*/else e=s-stacks-
10、top1+;return 1;链栈v链式存储结构实现的栈链栈(link stack)。v由于在链头运算,所以不用像单链表那样附加头结点,更方便运算链栈的类型定义typedef struct node elemtype data;struct node*next;linkstack;linkstack*top;/*栈顶指针,即链头指针栈顶指针,即链头指针*/链栈的基本运算空栈操作置空栈算法void setnull(linkstack*top)top=NULL;/*只要置只要置top为空即可为空即可*/判栈空算法int empty(linkstack*top)/*栈空返回栈空返回1否则返回否则返回
11、0*/if(top=NULL)return 1;else return 0;链栈的基本运算进栈void push(linkstack*top,elemtype x)/*注意:链栈不会发生上溢!注意:链栈不会发生上溢!*/linkstack*p;p=(linkstack*)malloc(sizeof(linkstack);p-data=x;p-next=top;top=p;链栈的基本运算出栈int pop(linkstack*top,elemtype&x)linkstack*p;if(top=NULL)return 0;/*栈为空无元素弹出栈为空无元素弹出*/else p=top;/*保存栈顶指
12、针于保存栈顶指针于P中中*/x=top-data;top=top-next;free(p);return 1;链栈的基本运算读栈顶元素int gettop(linkstack*top,elemtype&x)if(top=NULL)return 0;/*若栈为空返回若栈为空返回0*/else x=top-data;return 1;/*否则返回否则返回1*/3.3 栈的应用举例例一、例一、数制转换数制转换例二、例二、表达式求值表达式求值例三、例三、实现递归实现递归 例一、例一、数制转换数制转换 算法基于原理:N=(N div d)d+N mod d 例如:例如:(1348)10=(2504)8,
13、其运算过程如下:N N div 8 N mod 81348 168 4 168 21 0 21 2 5 2 0 2计计算算顺顺序序输输出出顺顺序序void conversion()setnull(s);/将栈s初始化为一个空栈 scanf(%d,N);while(N!=0)push(s,N%8);N=N/8;while(!empty(s)pop(s,e);printf(%d,e);/conversion一、表达式表达式由操作数、运算符和界限符组成其中:操作数operand:常数或变量 运算符operator:算术运算符(+,-,*,/等等)关系运算符(=!=等等)逻辑运算符:AND,OR,NO
14、T界限符delimiter:左右括号,表达式结束符#等例二、例二、表达式求值表达式求值二、算符优先关系表v先乘除,后加减:*+v先括号内,后括号外:(一切算符v同级按左结合律:+v不允许的:)(,(#,#)v三、算术表达式求值的算符优先算法1、使用DS算符栈OPTR:有效算符操作数栈OPND:有效操作数、运算结果v2、算法思想初始化:OPND置为空栈,将#放入OPTR栈底依次读入表达式中的每个字符,若是操作数,则入OPND栈;若是算符,则和OPTR栈顶算符进行优先级比较a.“”:若栈顶算符优先,则执行相应运算,结果存入OPND栈重复,直到表达式求值完毕OperandType EvaluateE
15、xpression()/算术表达式求值的算符优先算法。设OPTR/OPND分别为运算符栈和操作数栈,OP为/运算符集合setnull(OPTR);push(OPTR,#);setnull(OPND);c=getchar();while(c!=#|gettop(OPTR)!=#)/whilereturn gettop(OPND);/EvaluateExpression if(!In(c,OP)push(OPND,c);c=getchar();else switch(Precede(gettop(OPTR),c)case:/退栈并将运算结果入栈pop(OPTR,theta);pop(OPND,b)
16、;pop(OPND,a);push(OPND,Operate(a theta b);break;/switch 1 1、什么是递归、什么是递归 在定义一个过程或函数时出现调用本过程或在定义一个过程或函数时出现调用本过程或本函数的成分本函数的成分,称之为称之为递归递归。直接递归:直接递归:调用自身。调用自身。间接递归:间接递归:过程或函数过程或函数p p调用过程或函数调用过程或函数q,q,而而q q又又调用调用p p。尾递归:尾递归:一个递归过程或递归函数中递归调用语一个递归过程或递归函数中递归调用语句是最后一条执行语句。句是最后一条执行语句。例三、例三、栈与递归的实现栈与递归的实现例例 以下是
17、求以下是求n!(n为正整数为正整数)的递归函数。的递归函数。int fun(int n)int x;if(n=1)/*语句语句1*/x=1;/*语句语句2*/else/*语句语句3*/x=fun(n-1)*n;/*语句语句4*/return(x);/*语句语句5*/2 2、何时使用递归、何时使用递归 在以下三种情况下在以下三种情况下,常常要用到递归的方法。常常要用到递归的方法。1)定义是递归的定义是递归的 有许多数学公式、数列等的定义是递归的。例如有许多数学公式、数列等的定义是递归的。例如,求求n!和和Fibonacci数列等。这些问题的求解过程可以将数列等。这些问题的求解过程可以将其递归定义
18、直接转化为对应的递归算法。其递归定义直接转化为对应的递归算法。v这个数列从第三项开始,每一项都等于前两项之和。v如果设F(n)为该数列的第n项(nN+)。那么这句话可以写成如下形式:vF(0)=0,n=0v F(1)=1,n=1v F(n)=F(n-1)+F(n-2)(n3)2)数据结构是递归的数据结构是递归的 例如:链表例如:链表 其结点类型定义如下:其结点类型定义如下:typedef struct node ElemType data;struct node*next;LinkList;该定义中该定义中,结构体结构体node的定义中用到了它自身的定义中用到了它自身,即即指针域指针域next
19、是一种指向自身类型的指针是一种指向自身类型的指针,所以它是一种所以它是一种递归数据结构。递归数据结构。对对于于递递归归数数据据结结构构,采采用用递递归归的的方方法法编编写写算算法法既既方方便又有效。便又有效。例例如如,求求一一个个不不带带头头结结点点的的单单链链表表head的的所所有有data域域(假设为假设为int型型)之和的递归算法如下:之和的递归算法如下:int Sum(LinkList*head)if(head=NULL)return 0;else return(head-data+Sum(head-next);3)问题的求解方法是递归的问题的求解方法是递归的 有有些些问问题题的的解解
20、法法是是递递归归的的,典典型型的的有有Hanoi问问题题求求解解函数的嵌套调用时栈变化过程3 3、递归函数的实现、递归函数的实现v将所有的实在参数、返回地址等信息传递给被调用函数保存;v为被调用函数的局部变量分配存储区;v将控制转移到被调用函数的入口。当在一个函数的运行期间调用另一个函数时,在运行该被调用函数之前,需先完成三项任务:v保存被调函数的计算结果;v释放被调函数的数据区;v依照被调函数保存的返回地址将控制转移到调用函数。从被调用函数返回返回调用函数之前之前,应该完成下列三项任务:多个函数嵌套调用的规则是:此时的内存管理实行“栈式管理栈式管理”后调用先返回后调用先返回!例如:void
21、main()void a()void b()a();b();/main /a /bMain的数据区函数a的数据区函数b的数据区 递归函数的执行过程v递归函数的执行过程类似于嵌套调用时的情况v如阶乘函数:vint fact(int n)v if(n=0)v return 1;v elsev return n*fact(n-1);v v由于被调用函数与调用函数是同一个函数,其返回地址应为同一语句位置设为r。递归调用fact(4)的工作栈变量情况Hanoi问题问问题题描描述述:设设有有3个个分分别别命命名名为为X,Y和和Z的的塔塔座座,在在塔塔座座X上上有有n个个直直径径各各不不相相同同,从从小小到
22、到大大依依次次编编号号为为1,2,n的的盘盘片片,现现要要求求将将X塔塔座座上上的的n个盘片移到塔座个盘片移到塔座Z上并仍按同样顺序叠放上并仍按同样顺序叠放v盘片移动规则盘片移动规则:v1、每次只能移动一个盘片;、每次只能移动一个盘片;v2、盘片可以插在、盘片可以插在X,Y和和Z中任一塔座;中任一塔座;v3、任何时候都不能将一个较大的盘片放在较、任何时候都不能将一个较大的盘片放在较小的盘片上。小的盘片上。v设设Hanoi(n,x,y,z)表示将表示将n个盘片从个盘片从x通过通过y移移动到动到z上上,递归分解的过程是:递归分解的过程是:vhanoi(n-1,x,z,y);v /将x上编号为至n-
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 队列
限制150内