C语言课件3.ppt
- 文档编号:2667723
- 上传时间:2022-11-06
- 格式:PPT
- 页数:54
- 大小:208.50KB
C语言课件3.ppt
《C语言课件3.ppt》由会员分享,可在线阅读,更多相关《C语言课件3.ppt(54页珍藏版)》请在冰豆网上搜索。
第第33章章栈和队列栈和队列本章主要介绍以下内容:
本章主要介绍以下内容:
l栈的概念、存储结构及其基本操作栈的概念、存储结构及其基本操作l队列的概念、存储结构及其基本操作队列的概念、存储结构及其基本操作l栈与队列的应用举例栈与队列的应用举例退出退出3.1栈栈3.2队列队列3.1栈栈3.1.13.1.1栈的定义栈的定义栈是一种特殊的线性表。
其特殊性在于限定插入栈是一种特殊的线性表。
其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行。
如和删除数据元素的操作只能在线性表的一端进行。
如下所示:
下所示:
进行插入和删除的一端是浮动端,通常被称为进行插入和删除的一端是浮动端,通常被称为栈栈顶顶,并用一个,并用一个“栈顶指针栈顶指针”指示;而另一端是固定端,指示;而另一端是固定端,通常被称为通常被称为栈底栈底。
我们经常将栈用下图。
我们经常将栈用下图3-1的形式描述:
的形式描述:
a1,a2,a3,.,an插入和删除插入和删除端端图图3-1结论:
结论:
后进先出后进先出(LastInFirstOut),),简称为简称为LIFO线性表。
线性表。
举例举例1:
家里吃饭的碗,通常在洗干净后一个一个:
家里吃饭的碗,通常在洗干净后一个一个地落在一起存放,在使用时,若一个一个地拿,一定地落在一起存放,在使用时,若一个一个地拿,一定最先拿走最上面的那只碗,而最后拿出最下面的那只最先拿走最上面的那只碗,而最后拿出最下面的那只碗。
碗。
举例举例2:
在建筑工地上,使用的砖块从底往上一层:
在建筑工地上,使用的砖块从底往上一层一层地码放,在使用时,将从最上面一层一层地拿取。
一层地码放,在使用时,将从最上面一层一层地拿取。
下面我们先给出栈结构的基本操作:
下面我们先给出栈结构的基本操作:
(1)初始化栈)初始化栈InitStack(S)
(2)入栈入栈Push(S,item)(3)出栈出栈Pop(S,item)(4)获取栈顶元素内容获取栈顶元素内容GetTop(S,item)(5)判断栈是否为空判断栈是否为空StackEmpty(S)3.1.23.1.2栈的顺序存储栈的顺序存储栈的顺序存储结构是用一组连续的存储单元依次栈的顺序存储结构是用一组连续的存储单元依次存放栈中的每个数据元素,并用起始端作为栈底。
存放栈中的每个数据元素,并用起始端作为栈底。
类型定义如下所示:
类型定义如下所示:
#defineMAX_STACK10/栈的最大数据元素数目栈的最大数据元素数目typedefstructstackStackEntryitemMAX_STACK;/存放栈中数据元素的存储单元存放栈中数据元素的存储单元inttop;/栈顶指针栈顶指针STACK;基本操作算法:
基本操作算法:
1.初始化栈初始化栈SvoidInItStack(STACK*S)s-top=-1;2.入栈入栈voidPush(STACK*S,StackEntryitem)if(S-top=MAX_STACK-1)exit(“Stackisfull”);elseS-item+S-top=item;图图3-23.出栈出栈voidPop(STACK*S,StackEntry*item)if(StackEmpty(*S)exit(“Stackisempty”);else*item=S-itemS-top-;4.获取栈顶元素内容获取栈顶元素内容voidGetTop(STACKS,StackEntry*item)if(StackEmpty(S)exit(“Stackisempty”);else*item=S.itemS.top;5.判断栈判断栈S是否为空是否为空intStackEmpty(STACKS)if(S.top=-1)returnTRUE;elseFALSE;结论:
由于栈的插入和删除操作具有它的特殊性,结论:
由于栈的插入和删除操作具有它的特殊性,所以用顺序存储结构表示的栈并不存在插入删除数据所以用顺序存储结构表示的栈并不存在插入删除数据元素时需要移动的问题,但栈容量难以扩充的弱点仍元素时需要移动的问题,但栈容量难以扩充的弱点仍就没有摆脱。
就没有摆脱。
3.1.33.1.3栈的链式存储栈的链式存储若是栈中元素的数目变化范围较大或不清楚栈元素若是栈中元素的数目变化范围较大或不清楚栈元素的数目,就应该考虑使用链式存储结构。
人们将用链的数目,就应该考虑使用链式存储结构。
人们将用链式存储结构表示的栈称作式存储结构表示的栈称作“链栈链栈”。
链栈通常用一个。
链栈通常用一个无头结点的单链表表示。
如图无头结点的单链表表示。
如图3-3所示。
所示。
由于栈的插入删除操作只能在一端进行,而对于由于栈的插入删除操作只能在一端进行,而对于单链表来说,在首端插入删除结点要比尾端相对地容单链表来说,在首端插入删除结点要比尾端相对地容易一些,所以,我们将单链表的首端作为栈顶端,即易一些,所以,我们将单链表的首端作为栈顶端,即将单链表的头指针作为栈顶指针。
将单链表的头指针作为栈顶指针。
top图3-3栈的链式存储结构在栈的链式存储结构在C语言中可用下列类型定义实现:
语言中可用下列类型定义实现:
typestructnode/链栈的结点结构链栈的结点结构StackEntryitem;/栈的数据元素类型栈的数据元素类型structnode*next;/指向后继结点的指针指向后继结点的指针NODE;typedefstructstackNODE*top;STACK;下面我们将给出链栈各项基本操作的算法。
下面我们将给出链栈各项基本操作的算法。
1.初始化栈初始化栈SvoidInitStack(STACK*S)S-top=NULL;2.入栈入栈voidPush(STACK*S,StackEntryitem)p=(NODE*)malloc(sizeof(NODE);if(!
p)exit(OVERFLOW);elsep-item=item;p-next=S-top;S-top=p;3.出栈出栈voidPop(STACK*S,StackEntry*item)if(StackEmpty(*S)exit(“Stackisempty”);else*item=S-top-item;p=S-top;S-top=p-next;free(p);4.获取栈顶元素内容获取栈顶元素内容voidGetTop(STACKS,StackEntry*item)if(StackEmpty(S)exit(“Stackisempty”);else*item=S.top-item;5.判断栈判断栈S是否空是否空intStackEmpty(STACKS)if(S.top=NULL)returnTRUE;elseFALSE;3.1.43.1.4栈的应用举例栈的应用举例【举例举例11】将从键盘输入的字符序列逆置输出将从键盘输入的字符序列逆置输出比如,从键盘上输入:
比如,从键盘上输入:
tsetasisihT;算法将输出:
算法将输出:
Thisisatest下面我们给出解决这个问题的完整算法。
下面我们给出解决这个问题的完整算法。
typedefcharStackEntry;voidReverseRead()STACKS;/定义一个栈结构定义一个栈结构Scharch;InitStack(&S);/初始化栈初始化栈while(ch=getchar()!
=n)/从键盘输入字符,直到输入换行符为止从键盘输入字符,直到输入换行符为止Push(&S,ch);/将输入的每个字符入栈将输入的每个字符入栈while(!
StackEmpty(S)/依次退栈并输出退出的字符依次退栈并输出退出的字符Pop(&S,&ch);putchar(ch);putchar(n);【举例举例22】十进制数值转换成二进制十进制数值转换成二进制使用展转相除法将一个十进制数值转换成二进制使用展转相除法将一个十进制数值转换成二进制数值。
即用该十进制数值除以数值。
即用该十进制数值除以2,并保留其余数;重复,并保留其余数;重复此操作,直到该十进制数值为此操作,直到该十进制数值为0为止。
最后将所有的余为止。
最后将所有的余数反向输出就是所对应的二进制数值。
数反向输出就是所对应的二进制数值。
比如:
比如:
(692)10=(1010110100)2,其展转相除的过,其展转相除的过程如图程如图3-4所示:
所示:
图图3-4下面给出解决这个问题的完整算法。
下面给出解决这个问题的完整算法。
voidDecimal_Binary()STACKS;/定义栈结构定义栈结构SInitStack(&S);/初始化栈初始化栈Sscanf(“%d”,data);/输入十进制正整数输入十进制正整数while(data)Push(&S,data%2);/余数入栈余数入栈data/=2;/被除数被除数data整除以整除以2,得到新的被除数,得到新的被除数while(!
StackEmpty(S)/依次从栈中弹出每一个余数,并输出之依次从栈中弹出每一个余数,并输出之Pop(&S,&data);printf(“%d”,data);【举例举例33】检验表达式中的括号匹配情况检验表达式中的括号匹配情况假设在一个算术表达式中,可以包含三种括号:
假设在一个算术表达式中,可以包含三种括号:
圆括号圆括号“(”和和“)”,方括号,方括号“”和和“”和花括和花括号号“”和和“”,并且这三种括号可以按任意的次序,并且这三种括号可以按任意的次序嵌套使用。
比如,嵌套使用。
比如,.(.).。
现。
现在需要设计一个算法,用来检验在输入的算术表达式在需要设计一个算法,用来检验在输入的算术表达式中所使用括号的合法性。
中所使用括号的合法性。
算术表达式中各种括号的使用规则为:
出现左括算术表达式中各种括号的使用规则为:
出现左括号,必有相应的右括号与之匹配,并且每对括号之间号,必有相应的右括号与之匹配,并且每对括号之间可以嵌套,但不能出现交叉情况。
我们可以利用一个可以嵌套,但不能出现交叉情况。
我们可以利用一个栈结构保存每个出现的左括号,当遇到右括号时,从栈结构保存每个出现的左括号,当遇到右括号时,从栈中弹出左括号,检验匹配情况。
在检验过程中,若栈中弹出左括号,检验匹配情况。
在检验过程中,若遇到以下几种情况之一,就可以得出括号不匹配的结遇到以下几种情况之一,就可以得出括号不匹配的结论。
论。
(1)当遇到某一个右括号时,栈已空,说明到目)当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号;前为止,右括号多于左括号;
(2)从栈中弹出的左括号与当前检验的右括号类)从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉情况;型不同,说明出现了括号交叉情况;(3)算术表达式输入完毕,但栈中还有没有匹配)算术表达式输入完毕,但栈中还有没有匹配的左括号,说明左括号多于右括号。
的左括号,说明左括号多于右括号。
下面是解决这个问题的完整算法。
下面是解决这个问题的完整算法。
typedefcharStackEntry;intCheck()STACKS;/定义栈结构定义栈结构Scharch;InitStack(&S);/初始化栈初始化栈Swhile(ch=getchar()!
=n)/以字符序列的形式输入表达式以字符序列的形式输入表达式switch(ch)case(ch=(|ch=|ch=):
Push(&S,ch);break;/遇左括号入栈遇左括号入栈/在遇到右括号时,分别检测匹配情况在遇到右括号时,分别检测匹配情况case(ch=):
if(StackEmpty(S)retrunFALSE;elsePop(&S,&ch);if(ch!
=()returnFALSE;break;case(ch=):
if(StackEmpty(S)retrunFALSE;elsePop(&S,&ch);if(ch
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 课件