[工学]数据结构与算法-第四章课件.ppt
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《[工学]数据结构与算法-第四章课件.ppt》由用户(晟晟文业)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 工学 数据结构 算法 第四 课件
- 资源描述:
-
1、4 栈和队列栈和队列 4.1 栈 4.1.1 栈的定义 栈(栈(stack)又称堆栈,)又称堆栈,它是一种运算受限的线性表,它是一种运算受限的线性表,其限制是仅允许在表的一端进其限制是仅允许在表的一端进行插入和删除运算。行插入和删除运算。人们把对栈进行运算的一人们把对栈进行运算的一端称为栈顶,栈顶的第一个元端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,素被称为栈顶元素,相对地,把另一端称为栈底。把另一端称为栈底。v向一个栈插入新元素又称为进栈或入栈,它是把向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶该元素放到栈顶元素的上面,使之成为新的栈顶元素;元
2、素;v从一个栈删除元素又称为出栈或退栈,它是把栈从一个栈删除元素又称为出栈或退栈,它是把栈顶元素删除掉,使其下面的相邻元素成为新的栈顶元素删除掉,使其下面的相邻元素成为新的栈顶元素。顶元素。v由于栈的插入和删除运算仅在栈顶一端进行,后由于栈的插入和删除运算仅在栈顶一端进行,后进栈的元素必定先出栈,所以又把栈称为后进先进栈的元素必定先出栈,所以又把栈称为后进先出表出表(Last In First Out,简称简称LIFO)。v栈的物理存储可以用顺序存储结构,也可以用链栈的物理存储可以用顺序存储结构,也可以用链式存储结构式存储结构v栈中没有任何元素称为空栈。栈中没有任何元素称为空栈。假定一个栈假定
3、一个栈S为为(a,b,c),其中表尾的一端,其中表尾的一端为栈顶,字符为栈顶,字符c为栈顶元素。若向为栈顶元素。若向S压入一个压入一个元素元素d,则,则S变为变为(a,b,c,d),此时字符,此时字符d为栈为栈顶元素;若接着从栈顶元素;若接着从栈S中依次删除两个元素,中依次删除两个元素,则首先删除的是元素则首先删除的是元素d,接着删除的是元素,接着删除的是元素c,栈栈S变为变为(a,b),栈顶元素为,栈顶元素为b。4.1.2 栈的数据类型和运算栈的数据类型和运算v栈的抽象数据类型中的数据部分为具有ElemType元素类型的一个栈,它可以采用任一种存储结构实现;v栈的操作部分应包括元素进栈、元素
4、出栈、读取栈顶元素、检查栈是否为空等。栈的主要操作及程序:(1)初始化栈S,即把它置为空 void InitStack(S);(2)新元素x进栈,即把x值插入到栈顶 void Push(S,ElemType x);(3)删除栈顶元素并返回之 ElemType Pop(S);(4)返回栈顶元素的值,不会改变栈的状态 ElemType Peek(S);(5)判断栈S是否为空,若是则返回1表示真,否则返回0表示假 int EmptyStack(S);(6)清除栈S中的所有元素,使之成为一个空栈 void ClearStack(S);假定栈a的元素类型为int,下面为调用栈操作的一些例子。(1)Ini
5、tStack(a);/表示把栈a置空 (2)Push(a,18);/表示元素18进栈 (3)int x=46;Push(a,x);/表示x的值46进栈 (4)Push(a,x/3);/表示x除以3的整数值15进栈 (5)x=Pop(a);/表示栈顶元素15退栈并赋给x (6)printf(“%d”,Peek(a);/表示读取当前栈顶元素46并输出 (7)Pop(a);/栈顶元素46出栈,返回值46自动丢失 (8)EmptyStack(a);/因此时栈a非空,所以返回的值false (9)printf(“%dn”,Pop(a);/栈顶元素18退栈并输出,此时栈已空 (10)x=EmptyStac
6、k(a);/因栈为空,返回true,接着把对应的整数值1赋给x4.2 栈的顺序存储结构和操作实现栈的顺序存储结构和操作实现v栈的顺序存储结构也称为顺序栈,它是栈的顺序存储结构也称为顺序栈,它是一种运算受限的顺序表。一种运算受限的顺序表。v顺序栈具有栈的一切特点顺序栈具有栈的一切特点4.2.1 顺序栈的定义 1.利用普通数组加栈顶指针来实现栈的定义 栈的顺序存储结构需要使用一个数组和一个整型变量来实现,利用数组来顺序存储栈中的所有元素,利用整型变量来存储栈顶元素的下标位置。假定栈数组用stackMaxSize表示,指示栈顶位置的整型变量用top表示,则元素类型为ElemType的栈的顺序存储结构
7、可定义为:ElemType stackMaxSize;int top;其中,MaxSize为一个整型全局常量,需事先定义,由它确定顺序栈(即顺序存储的栈)的最大长度,又称为深度,即栈空间最多能够存储的元素个数;由于top用来指示栈顶元素的位置,所以把它称为栈顶指针栈顶指针。2.利用记录来实现栈的定义 假定该记录类型用StackSq表示,则定义为:struct StackSq ElemType stackMaxSize;int top;3.采用动态分配存储空间的方法来实现栈的定义 struct StackSq ElemType*stack;/*存栈元素的数组指针*/int top;/*存栈顶元素
8、的下标位置*/int MaxSize;/*存stack数组长度*/;v在顺序存储的栈中,top的值为-1表示栈空,v每次向栈中压入一个元素时,首先使top增1,用以指示新的栈顶位置,然后再把元素赋值到这个空位置上,每次从栈中弹出一个元素时,首先取出栈顶元素,然后使top减1,指示出前一个元素成为新的栈顶元素。v在一个顺序栈中,若top已经指向了MaxSize-1 的位置,则表示栈满,若再向其插入新元素时就需要进行栈满处理,v由于顺序栈的插入和删除运算相当于是在顺序表的表尾进行的,其时间复杂度为O(1)。设一个栈S为(a,b,c,d,e),对应的顺序存储结构如下图(a)所示。若向S中插入一个元素
9、f,则对应如下图(b)所示。若接着执行两次出栈操作后,则栈S对应如下图(c)所示。若依次使栈S中的所有元素出栈,则s变为空,如下图(d)所示。MaxSize-10 a0 a1 b0 a1 b1 b2 2 c2 c2 c3 d3 d3 d4 e4 e5 f401234toptoptop(a)top=4(b)top=5(c)top=3(d)top=-1MaxSize-1MaxSize-1MaxSize-1栈在顺序存储结构下的操作实现:1.初始化栈初始化栈S为空为空 此操作可以包括两种情况,一种是置空并隐含分配固定大小的动态存储空间,另一种是置空并分配由参数指定大小的动态存储空间。首先给出第一种置空
10、的算法。void InitStack(struct StackSq*S)/*置栈空间初始最大长度为10*/S-MaxSize=10;/*动态存储空间分配*/S-stack=malloc(10*sizeof(ElemType);/*置栈为空*/S-top=-1;第二种置空栈的算法:void InitStack(struct StackSq*S,int ms)/*检查ms是否有效,若无效则退出运行*/if(msMaxSize=ms;/*动态存储空间分配,若分配失败则退出运行*/S-stack=malloc(ms*sizeof(ElemType);if(!S-stack)printf(动态存储分配失
11、败!n);exit(1);/*初始置栈为空*/S-top=-1;2.新元素进栈,即把它插入到栈顶新元素进栈,即把它插入到栈顶 在这个算法中,对栈满的处理方法是调用一个函数,使之得到大一倍的栈数组空间,接着进行新元素的插入操作。void Push(struct StackSq*S,ElemType x)/*若栈空间用完则重新分配更大的存储空间*/if(S-top=S-MaxSize-1)againMalloc(S);/*栈顶指针后移一个位置*/S-top+;/*将新元素插入到栈顶*/S-stackS-top=x;void againMalloc(struct StackSq*S)/*空间扩展为原
12、来的2倍,原内容被自动 拷贝到p所指向的存储空间中*/ElemType*p;p=realloc(S-stack,2*S-MaxSize*sizeof(ElemType);if(!p)/*分配失败退出运行*/printf(存储空间用完!n);exit(1);/*使stack指向新的栈空间*/S-stack=p;/*把栈空间大小修改为新的长度*/S-MaxSize=2*S-MaxSize;3.删除栈顶元素并返回值删除栈顶元素并返回值 ElemType Pop(struct StackSq*S)/*若栈空则退出运行*/if(S-top=-1)printf(栈空,无元素出栈!n);exit(1);/*
13、栈顶指针减1表示退栈*/S-top-;/*返回原栈顶元素的值*/return S-stackS-top+1;4.3 栈的链接存储结构和操作实现栈的链接存储结构和操作实现 栈的链接存储结构是通过由结点构成的单链表实现的,此时表头指针被称为栈顶指栈顶指针针,由栈顶指针指向的表头结点被称为栈顶栈顶结点结点,整个单链表被称为链栈链栈,即链接存储的栈。v当向一个链栈插入元素时,是把该元素插入到栈顶,即使该元素结点的指针域指向原来的栈顶结点,而栈顶指针则修改为指向该元素结点,使该结点成为新的栈顶结点。v当从一个链栈中删除元素时,是把栈顶元素结点删除掉,即取出栈顶元素后,使栈顶指针指向原栈顶结点的指针域所指
14、向的结点。v对链栈的插入和删除操作均是在单链表的表头进行的,其时间复杂度为O(1)。设一个栈为(a,b,c),当采用链接存储时,对应的存储结构如下图(a)所示,其中HS表示栈顶指针,其值为存储元素c结点的地址。其插入和删除操作如图所示:data nextc(a)(b)(c)aabbdabcHSHSHS4.3.1 链栈中数据结点的定义v链栈中的结点仍采用以前已经定义的sNode结点类型,即:struct sNode ElemType data;/数据域数据域 struct sNode*next;/指针域指针域 Struct sNode*L;4.3.2 链栈的主要操作 假定链栈中的结点采用已经定义
15、的sNode结点类型,并假定栈顶指针用HS表示,链栈操作的算法有:1.初始化链栈为空Void InitStack(struct sNode*HS)*HS=NULL;如果 定义为 struct sNode*类型的栈顶变量p作为一个栈顶指针,则初始化程序可变为:Void InitStack(&p)p=NULL;2.向链栈中插入一个元素向链栈中插入一个元素 void Push(struct sNode*HS,ElemType x)/*为插入元素获取动态结点*/struct sNode*newp;newp=malloc(sizeof(struct sNode);if(newp=NULL)printf(
16、内存动态空间用完,退出运行!n);exit(1);/*给新分配的结点赋值*/newp-data=x;/*向栈顶插入新结点*/newp-next=*HS;*HS=newp;3.从链栈中删除一个元素并返回它从链栈中删除一个元素并返回它 ElemType Pop(struct sNode*HS)struct sNode*p;ElemType temp;/*对于空栈则退出运行*/if(*HS=NULL)printf(栈空无法删除!n);exit(1);/*暂存栈顶结点指针,并使栈顶指针指向下一结点*/p=*HS;*HS=p-next;/*暂存原栈顶元素以便返回,同时回收原栈顶结点*/temp=p-da
17、ta;free(p);/*返回原栈顶元素*/return temp;4.读取栈顶元素读取栈顶元素 ElemType Peek(sNode*HS)/HS为值参或引用形参均可 if(*HS=NULL)/无法从空栈中读取 printf(“栈空,无栈顶结点!n”)exit(1);return(*HS)-data;/返回栈顶结点的值 4.4 栈的简单应用举例 例例4-1 从键盘上输入一批整数,然后按照相反的次序打印出来 根据题意可知,后输入的整数将先被打印出来,这正好符合栈的后进先出的特点。所以此题很容易用栈来解决。假定采用顺序栈,其参考程序如下:#include#include typedef int
18、 ElemType;/*定义元素类型为整型*/struct StackSq ElemType*stack;/*存栈元素的动态数组指针*/int top;/*存栈顶元素的下标位置*/int MaxSize;/*存stack数组长度,亦即所能存储栈的最大长度*/;#include顺序栈操作.c /*假定对顺序栈各种操作的算法已经存于该程序文件中*/void main()struct StackSq a;int x;InitStack(&a);printf(输入一批整数,直到输入终止标志-1为止!n);scanf(%d,&x);while(x!=-1)Push(&a,x);scanf(%d,&x);
19、while(!EmptyStack(&a)/*栈不为空时依次退栈并输出*/printf(%d,Pop(&a);printf(n);v假定从键盘上输入为:v 78 63 45 82 91 34-1v则输出为:v 34 91 82 45 63 78 例例4-2 堆栈在计算机语言的编译过程中可用来进行语法检查。试编写一个算法,用来检查一个C/C+语言程序中的花括号、方括号和圆括号是否配对,若能够全部配对则返回1,否则返回0。编写出算法如下:int BracketsCheck(char*fname)/*对由fname所指字符串为文件名的程序文件进行括号配对检查*/Struct StackSq a;/*
20、定义一个顺序栈*/char ch;/*定义一个字符变量*/FILE*finstr;/*定义一个文件指针变量,即文件流*/finstr=fopen(fname,r);/*用文件流finstr打开以fname所指字符串为文件名的文件,并规定为读文件方式*/if(!finstr)/*没有找到对应的磁盘文件则退出运行*/printf(File%snot found!n,fname);exit(1);InitStack(&a);/*栈a初始化*/ch=fgetc(finstr);/*从文件中读取第一个字符到ch*/while(ch!=EOF)/*未读到文件最后的结束标志则循环*/printf(%c,ch
21、);/*向屏幕输出被读出的字符*/switch(ch)/*对读到的各种括号分情况处理*/case:case:case(:Push(&a,ch);/*出现以上三种左括号则进栈*/break;case:if(Peek(&a)=)Pop(&a);/*栈顶的左花括号出栈*/else return 0;break;case:if(Peek(&a)=)Pop(&a);/*栈顶的左中括号出栈*/else return 0;break;case):if(Peek(&a)=()Pop(&a);/*栈顶的左圆括号出栈*/else return 0;break;ch=fgetc(finstr);/*从文件中顺序读取
22、下一个字符到ch*/if(EmptyStack(&a)/*栈最后为空时返回1否则返回0*/return 1;else return 0;4.5 4.5 算术表达式的计算算术表达式的计算 4.5.1 算术表达式的两种表示v算术表达式是操作数(又叫运算对象)和运算符以及改变运算次序的括号(圆或方括号)所组成。v操作数可以是常量,变量和函数,同时还可以是另一个表达式。v而运算符可以是单目运算符和双目运算符。单目运算符只需一个操作数,双目运算符要求两个操作数,并被放在两个操作数的中间。v单目运算符有取正,取负,平方、开根等。而双目运算符有+、-、等。v双目运算符出现在两个操作数中间的这种习惯表示法叫做
23、算术表达式的中缀表示法(如 2+56)。这种算术表达式称为中缀表达式。v中缀表达式的计算必须遵守以下三条规则:(1)先计算括号内,后计算括号外;(2)在无括号或同层括号内,先进行乘除运算,后 进行加减运算,即乘除运算的优先级高于加减 运算的优先级;(3)同一优先级运算,从左向右依次进行。v运算符放在两个计算对象的后面的算式表示法叫做后缀表示法v在利用后缀表示法进行计算时,不存在括号,也不存在优先级的差别,计算过程完全按照运算符出现的先后次序来进行,整个计算过程只需前面的一个运算符的扫描排序过程。v采用后缀表示的计算表达式,可利用标准的计算程序来实现多种复杂的算术表达式的计算。例如,对于下列各中
24、缀表达式:(1)3/5+6 (2)16-9*(4+3)(3)2*(x+y)/(1-x)(4)(25+x)*(a*(a+b)+b)对应的后缀表达式分别为:(1)35/6+(2)16943+*-(3)2xy+*1x-/(4)25x+aab+*b+*4.5.2 后缀表达式求值的算法算法思想:1.利用堆栈对算式从头到尾进行扫描,来实现对算式的解释和计算。2.算式用一字符串来表示,并用空格来分隔各操作数和运算符3.在扫描时,遇到操作数就将其压入堆栈(如遇到小数点则将整个带小数点的数字转换为浮点数后再压入堆栈),直到遇到运算符4.在扫描时,遇到运算符,就将堆栈内的最上面的两个操作数弹出,并按其扫描到的运算
25、符进行计算。5.将计算结果存入一个结果变量中(如x),并压入堆栈,以便作为后面运算的操作数6.依次向下扫描每一个字符直到遇到字符串结束符例子:假定有一个中缀算术表达式:(12+34)+(5/2)*2 该表达式用后缀表示法的表示字符串为:char*a=“12 34+5 2/+2*”;使用后缀表达式求值的算法计算后可得到与中缀表达式计算相同的结果值:97.v用后缀表示法进行求值过程中,其堆栈的变换如图所示:4.5.3 把中缀表达式转换为后缀表达式的算法算法思想:1.中缀表达式保存在字符串S1中,后缀表达式保存在S2中2.在转换过程中,设一保存运算符的堆栈,保存在扫描过程所遇到的运算符,3.在栈底放
展开阅读全文