欢迎来到冰豆网! | 帮助中心 分享价值,成长自我!
冰豆网
全部分类
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • 党团工作>
  • ImageVerifierCode 换一换
    首页 冰豆网 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    数据结构辅导 栈和队列 1.docx

    • 资源ID:25932040       资源大小:24.35KB        全文页数:21页
    • 资源格式: DOCX        下载积分:3金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要3金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    数据结构辅导 栈和队列 1.docx

    1、数据结构辅导 栈和队列 1数据结构辅导 栈和队列 1一、栈1.栈的定义栈(Stack)又称堆栈,它是一种运算受限的线性表,其限制是仅答应在表的一端进行插入和删除运算。人们把此端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,把另一端称为栈底。向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称为出栈或退栈,它是把栈顶元素删除掉,使其下面的相邻元素成为新的栈顶元素。在日常生活中,有许多类似栈的例子,如刷洗盘子时,依次把每个洗净的盘子放到洗好的盘子上,相当于进栈;取用盘子时,从一摞盘子上一个接一个地向下拿,相当于出栈。又如向枪支弹夹里装子

    2、弹时,子弹被一个接一个地压入,则为进栈;射击时子弹总是从顶部一个接一个地被射出,此为子弹出栈。由于栈的插入和删除运算仅在栈顶一端进行,后进栈的元素必定先出栈,所以又把栈称为后进先出表(Last In First Out,简称LIFO)。例如,假定一个栈S为(a,b,c),其中字符c的一端为栈顶,字符c为栈顶元素。若向S压入一个元素d,则S变为(a,b,c,d),此时字符d为栈顶元素;若接着从栈S中依次删除两个元素,则首先删除的是元素d,接着删除的使元素c,栈S变为(a,b),栈顶元素为b。视频教程css.shtmltarget=_blanktitle=div视频教程div 2.栈的存储结构栈既

    3、然是一种线性表,所以线性表的顺序存储和链接存储结构同样适用于栈。(1)栈的顺序存储结构栈的顺序存储结构同样需要使用一个数组和一个整型变量来实现,利用数组来顺序存储栈中的所有元素,利用整型变量来存储栈顶元素的下标位置。假定栈数组用stackStackMaxSize表示,指示栈顶位置的整型变量用top表示,则元素类型为ElemType的栈的顺序存储类型可定义为:ElemType stackStackMaxSize;int top;其中,StackMaxSize为一个整型全局常量,需事先通过const语句定义,由它确定顺序栈(即顺序存储的栈)的最大深度,又称为长度,即栈最多能够存储的元素个数;由于t

    4、op用来指示栈顶元素的位置,所以把它称为栈顶指针。栈的顺序存储结构同样可以定义在一个记录类型中,假定该记录类型用Stack表示,则定义为:struct StackElemType stackStackMaxSize;int top;在顺序存储的栈中,top的值为-1表示栈空,每次向栈中压入一个元素时,首先使top增1,用以指示新的栈顶位置,然后再把元素赋值到这个位置上,每次从栈中弹出一个元素时,首先取出栈顶元素,然后使top减1,指示前一个元素成为新的栈顶元素。由此可知,对顺序栈的插入和删除运算相当于是在顺序表(即顺序存储的线性表)的表尾进行的,其时间复杂度为O(1)。设一个栈S为(a,b,c

    5、,d,e),对应的顺序存储结构如图4-1(a)所示。若向S中插入一个元素f,则对应如图4-1(b)所示。若接着执行两次出栈操作后,则栈S对应如图4-1(c)所示。若依次使栈S中的所有元素出栈,则s变为空,如图4-1(d)所示。在图4-1中栈是垂直画出的,并且使下标编号向上递增,这样可以形象地表示出栈顶在上,栈底在下。图4-1栈的顺序存储结构及操作过程在一个顺序栈中,若top已经指向了StackMaxSize-1的位置,则表示栈满,若top的值已经等于-1,则表示栈空。向一个满栈插入元素和从一个空栈删除元素都是不答应的,应该停止程序运行或进行非凡处理。(2)栈的链接存储结构栈的链接存储结构与线性

    6、表的链接存储结构相同,是通过由结点构成的单链表实现的,此时表头指针被称为栈顶指针,由栈顶指针指向的表头结点被称为栈顶结点,整个单链表被称为链栈,即链接存储的栈。当向一个链栈插入元素时,是把该元素插入到栈顶,即使该元素结点的指针域指向原来的栈顶结点,而栈顶指针则修改为指向该元素结点,使该结点成为新的栈顶结点。当从一个链栈中删除元素时,是把栈顶元素结点删除掉,即取出栈顶元素后,使栈顶指针指向原栈顶结点的后继结点。由此可知,对链栈的插入和删除操作是在单链表的表头进行的,其时间复杂度为O(1)。设一个栈为(a,b,c),当采用链接存储时,对应的存储结构示意图如图4-2(a)所示,其中HS表示栈顶指针,

    7、其值为存储元素c结点的地址。当向这个栈插入一个元素d后,对应如图4-2(b)所示。当从这个栈依次删除两个元素后,对应如图4-2(c)所示。当链栈中的所有元素全部出栈后,栈顶指针HS的值为空,即常量NULL所表示的数值0。图4-2栈的链接存储结构及操作过程3.栈的抽象数据类型栈的抽象数据类型中的数据部分为具有ElemType元素类型的一个栈,它可以采用任一种存储结构实现;操作部分包括元素进栈、出栈、读取栈顶元素、检查栈是否为空等。下面给出栈的抽象数据类型的具体定义。ADT STACK is Data:采用顺序或链接方式存储的栈,假定其存储类型用StackType标识符表示。Operation:v

    8、oid InitStack(StackType&S);/初始化栈S,即把它置为空void ClearStack(StackType&S);/清除栈S中的所有元素,使之成为一个空栈int StackEmpty(StackType&S);/判定S是否为空,若是则返回1,否则返回0 ElemType Peek(StackType&S)/返回S的栈顶元素,但不移动栈顶指针void Push(StackType&S,const ElemType&item)/元素item进栈,即插入到栈顶ElemType Pop(StackType&S)/删除栈顶元素并返回之int StackFull(Stack&S)/

    9、若栈已满则返回1,否则返回0,此函数为顺/序存储的栈所特有end STACK对于判定栈是否为空和返回栈顶元素的两种操作,由于它们不改变栈的状态,所以可在参数类型说明前使用常量定义符const。假定栈a的元素类型为int,下面给出调用上述栈操作的一些例子。(1)InitStack(a);/把栈a置空(2)Push(a,35);/元素35进栈(3)int x=48;Push(a,x);/48进栈(4)Push(a,x/2);/x除以2的值24进栈(5)x=Pop(a);/栈顶元素24退栈并赋给x(6)x=Peek(a);/读取栈顶元素48并赋给x(7)Pop(a);/栈顶元素48退栈(8)Stac

    10、kEmpty(a);/因栈非空,应返回0(9)cout Pop(a)endl;/栈顶元素35退栈并输出(10)x=StackEmpty(a);/因栈为空,应返回1,然后赋给x 4.栈运算的实现栈运算(操作)的具体实现取决于栈的存储结构,存储结构不同,其算法描述也不同。下面分别给出栈的运算在顺序存储结构和链接存储结构上实现的具体算法。(a)栈的操作在顺序存储结构上的实现假定采用顺序存储结构定义的栈用标识符S表示,其类型为已经给出过的Stack记录类型。(1)初始化栈void InitStack(Stack&S)/初始化栈S,即把它置为空S.top=-1;(2)把一个栈清除为空在顺序存储方式下,同

    11、初始化栈的算法相同。void ClearStack(Stack&S)/清除栈S中的所有元素,使之成为一个空栈S.top=-1;(3)检查一个栈是否为空int StackEmpty(Stack&S)/判定S是否为空,若是则返回1,否则返回0return S.top=-1;(5)读取栈顶元素ElemType Peek(StackType&S)/返回S的栈顶元素,但不移动栈顶指针/若栈为空则终止程序运行if(S.top=-1)cerrStack is empty!endl;exit(1);/返回栈顶元素的值return S.stackS.top;(5)向栈中插入元素void Push(Stack&S

    12、,const ElemType&item)/元素item进栈,即插入到栈顶/若栈已满则终止程序运行if(S.top=StackMaxSize-1)cerrStack overflow!endl;exit(1);/将栈顶指针后移一个位置S.top+;/将item的值赋给新的栈顶位置S.stackS.top=item;(6)从栈中删除元素ElemType Pop(StackType&S)/删除栈顶元素并返回之/若栈为空则终止程序运行if(S.top=-1)cerrStack is empty!endl;exit(1);/暂存栈顶元素以便返回ElemType temp=S.stackS.top;/栈

    13、顶指针前移一个位置S.top-;/返回原栈顶元素的值return temp;从出栈算法可以看出,原栈顶元素的值没有被改变,所以可以不使用临时变量保存它,返回语句中返回S.stackS.top+1的值即可。(7)检查栈是否已满int StackFull(Stack&S)/若栈已满则返回1,否则返回0,此函数为顺序栈所特有return S.top=StackMaxSize-1;(b)栈的操作在链接存储结构上的实现假定链栈中的结点仍采用在第二章中已经定义的LNode结点类型,并假定栈顶指针用HS表示,下面给出对由HS所指向的链栈进行每一种栈操作的算法。(1)初始化链栈void InitStack(L

    14、Node*&HS)HS=NULL;/将链栈置空。(2)清除链栈为空void ClearStack(LNode*&HS)LNode*cp,*np;/用cp作为指向待删除的结点,np指向cp的后继结点。cp=HS;/给cp指针赋初值,使之指向栈顶结点。while(cp!=NULL)/从栈顶到栈底依次删除每个结点np=cp-next;delete cp;cp=np;HS=NULL;/置链栈为空(3)检查链栈是否为空int StackEmpty(LNode*HS)/HS为值参或引用形参均可return HS=NULL;(4)读取栈顶元素ElemType Peek(LNode*HS)/HS为值参或引用形

    15、参均可if(HS=NULL)cerrLinked stack is empty!endl;exit(1);return HS-data;(5)向链栈中插入一个元素void Push(LNode*&HS,const ElemType&item)/为插入元素获取动态结点LNode*newptr=new LNode;if(newptr=NULL)cerrMemory allocation failare!endl;exit(1);/给新分配的结点赋值newptr-data=item;/向栈顶插入新结点newptr-next=HS;HS=newptr;(6)从链栈中删除一个元素ElemType Pop

    16、(LNode*&HS)if(HS=NULL)cerrLinked stack is empty!endl;exit(1);LNode*p=HS;/暂存栈顶结点HS=HS-next;/使栈顶指针指向其后继结点ElemType temp=p-data;/暂存原栈顶元素delete p;/回收原栈顶结点return temp;/返回原栈顶元素5.栈的简单应用举例例1.从键盘上输入一批整数,然后按照相反的次序打印出来。根据题意可知,后输入的整数将先被打印出来,这正好符合栈的后进先出的特点。所以此题很轻易用栈来解决。参考程序如下:#include iostream.h#include stdlib.h

    17、const int StackMaxSize=30;typedef int ElemType;/定义元素类型为整型struct StackElemType stackStackMaxSize;int top;#includestack.h/假定对顺序栈操作的算法已经存于stack.h头文件中void main()Stack a;InitStack(a);int x;cin x;while(x!=-1)/假定用-1作为终止键盘输入的标志,输入的整数个数/不能超过StackMaxSize所规定的值Push(a,x);cin x;while(!StackEmpty(a)/栈不为空时依次退栈打印出来c

    18、out Pop(a);cout endl;假定从键盘上输入为:78 63 45 82 91 34-1则输出为:34 91 82 45 63 78例2.堆栈在计算机语言的编译过程中用来进行语法检查,试编写一个算法,用来检查一个C+语言程序中的花括号、方括号和圆括号是否配对,若能够全部配对则返回1,否则返回0。在这个算法中,需要扫描待检查程序中的每一个字符,当扫描到每个花、中、圆左括号时,令其进栈,当扫描到每个花、中、圆右括号时,则检查栈顶是否为相应的左括号,若是则作退栈处理,若不是则表明出现了语法错误,应返回0。当扫描到程序文件结尾后,若栈为空则表明没有发现括号配对错误,应返回1,否则表明栈中还

    19、有未配对的括号,应返回0。另外,对于一对单引号或双引号内的字符不进行括号配对检查。根据分析,编写出算法如下:int BracketsCheck(char*fname)/对由fname所指字符串为文件名的文件进行括号配对检查ifstream ifstr(fname,ios:in|ios:nocreate);/用文件输入流对象ifstr打开以fname所指字符串为文件名的文件if(!ifstr)cerrFilefnamenot found!endl;exit(1);Stack a;/定义一个顺序栈InitStack(a);/栈a初始化char ch;while(ifstr ch)/顺序扫描文件中的

    20、每一个字符if(ch=39)/单引号内的字符不参与配对比较while(ifstr ch)if(ch=39)/39为单引号的ASCII值break;if(!ifstr)return 0;else if(ch=34)/双引号内的字符不参与配对比较while(ifstr ch)if(ch=34)/34为双引号的ASCII值break;if(!ifstr)return 0;switch(ch)case:case:case(:Push(a,ch);/出现以上三种左括号则进栈break;case:if(Peek(a)=)Pop(a);/栈顶的左花括号出栈else return 0;break;case:i

    21、f(Peek(a)=)Pop(a);/栈顶的左中括号出栈else return 0;break;case):if(Peek(a)=()Pop(a);/栈顶的左圆括号出栈else return 0;if(StackEmpty(a)return 1;else return 0;例3.把十进制整数转换为二至九之间的任一进制数输出。由计算机基础知识可知,把一个十进制整数x转换为任一种r进制数得到的是一个r进制的整数,假定为y,转换方法是逐次除基数r取余法。具体叙述为:首先用十进制整数x除以基数r,得到的整余数是r进制数y的最低位y0,接着以x除以r的整数商作为被除数,用它除以r得到的整余数是y的次最低

    22、位y1,依次类推,直到商为0时得到的整余数是y的最高位ym,假定y共有m+1位。这样得到的y与x等值,y的按权展开式为:y=y0+y1.r+y2.r2+.+ym.rm例如,若十进制整数为3425,把它转换为八进制数的过程如图4-3所示。图4-3十进制整数3425转换为八进制数的过程最后得到的八进制数为(6541)8,对应的十进制数为683+582+48+1=3425,即为被转换的十进制数,证实转换过程是正确的。从十进制整数转换为r进制数的过程中,由低到高依次得到r进制数中的每一位数字,而输出时又需要由高到低依次输出每一位。所以此问题适合利用栈来解决,具体算法描述为:void Transform

    23、(long num,int r)/把一个长整型数num转换为一个r进制数输出Stack a;/利用栈a存储转换后得到的每一位数字InitStack(a);/初始化栈while(num!=0)/由低到高求出r进制数的每一位并入栈int k=num%r;Push(a,k);num/=r;while(!StackEmpty(a)/由高到低输出r进制数的每一位cout Pop(a);cout endl;假定用下面的主程序调用Transform过程。void main()cout3425的八进制数为:;Transform(3425,8);cout3425的六进制数为:;Transform(3425,6)

    24、;cout3425的四进制数为:;Transform(3425,4);cout3425的二进制数为:;Transform(3425,2);则得到的运行结果如下:3425的八进制数为:6541 3425的六进制数为:23505 3425的四进制数为:311201 3425的二进制数为:110101100001二、算术表达式的计算在计算机中进行算术表达式的计算是通过栈来实现的。这一节首先讨论算术表达式的两种表示方法,即中缀表示法和后缀表示法,接着讨论后缀表达式求值的算法,最后讨论中缀表达式转换为后缀表达式的算法。1.算术表达式的两种表示通常书写的算术表达式是由操作数(又叫运算对象或运算量)和运算符

    25、以及改变运算次序的圆括号连接而成的式子。操作数可以是常量、变量和函数,同时还可以是表达式。运算符包括单目运算符和双目运算符两类,单目运算符只要求一个操作数,并被放在该操作数的前面,双目运算符要求有两个操作数,并被放在这两个操作数的中间。单目运算符为取正+和取负-,双目运算符有加+,减-,乘*和除/等。为了简便起见,在我们的讨论中只考虑双目运算符。如对于一个算术表达式2+5*6,乘法运算符*的两个操作数是它两边的5和6;对于加法运算符+的两个操作数,一个是它前面的2,另一个是它后面的5*6的结果即30。我们把双目运算符出现在两个操作数中间的这种习惯表示叫做算术表达式的中缀表示,这种算术表达式被称

    26、为中缀算术表达式或中缀表达式。中缀表达式的计算比较复杂,它必须遵守以下三条规则:(1)先计算括号内,后计算括号外;(2)在无括号或同层括号内,先进行乘除运算,后进行加减运算,即乘除运算的优先级高于加减运算的优先级;(3)同一优先级运算,从左向右依次进行。从这三条规则可以看出,在中缀表达式的计算过程中,既要考虑括号的作用,又要考虑运算符的优先级,还要考虑运算符出现的先后次序。因此,各运算符实际的运算次序往往同它们在表达式中出现的先后次序是不一致的,是不可猜测的。当然凭直观判别一个中缀表达式中哪个运算符最先算,哪个次之,哪个最后算并不困难,但通过计算机处理就比较困难了,因为计算机只能一个字符一个字

    27、符地扫描,要想得到哪一个运算符先算,就必须对整个中缀表达式扫描一遍,一个中缀表达式中有多少个运算符,原则上就得扫描多少遍才能计算完毕,这样就太浪费时间了,显然是不可取的。那么,能否把中缀算术表达式转换成另一种形式的算术表达式,使计算简单化呢?回答是肯定的。波兰科学家卢卡谢维奇(Lukasiewicz)很早就提出了算术表达式的另一种表示,即后缀表示,又称逆波兰式,其定义是把运算符放在两个运算对象的后面。采用后缀表示的算术表达式被称为后缀算术表达式或后缀表达式。在后缀表达式中,不存在括号,也不存在优先级的差别,计算过程完全按照运算符出现的先后次序进行,整个计算过程仅需一遍扫描便可完成,显然比中缀表

    28、达式的计算要简单得多。例如,对于后缀表达式12!4!-!5!/,其中!字符表示成分之间的空格,因减法运算符在前,除法运算符在后,所以应先做减法,后做除法;减法的两个操作数是它前面的12和4,其中第一个数12是被减数,第二个数4是减数;除法的两个操作数是它前面的12减4的差(即8)和5,其中8是被除数,5是除数。中缀算术表达式转换成对应的后缀算术表达式的规则是:把每个运算符都移到它的两个运算对象的后面,然后删除掉所有的括号即可。例如,对于下列各中缀表达式:(1)3/5+6(2)16-9*(4+3)(3)2*(x+y)/(1-x)(4)(25+x)*(a*(a+b)+b)对应的后缀表达式分别为:(

    29、1)3!5!/!6!+(2)16!9!4!3!+!*!-(3)2!x!y!+!*!1!x!-!/(4)25!x!+!a!a!b!+!*!b!+!*2.后缀表达式求值的算法后缀表达式的求值比较简单,扫描一遍即可完成。它需要使用一个栈,假定用S表示,其元素类型应为操作数的类型,假定为浮点型float,用此栈存储后缀表达式中的操作数、计算过程中的中间结果以及最后结果。假定一个后缀算术表达式以字符作为结束符,并且以一个字符串的方式提供。后缀表达式求值算法的基本思路是:把包含后缀算术表达式的字符串定义为一个输入字符串流对象,每次从中读入一个字符(空格作为数据之间的分隔符,不会被作为字符读入)时,若它是运

    30、算符,则表明它的两个操作数已经在栈S中,其中栈顶元素为运算符的后一个操作数,栈顶元素的下一个元素为运算符的前一个操作数,把它们弹出后进行相应运算即可,然后把运算结果再压入栈S中;否则,读入的字符必为操作数的最高位数字,应把它重新送回输入流中,然后把下一个数据作为浮点数输入,并把它压入到栈S中。依次扫描每一个字符(对于浮点数只需扫描它的最高位并一次输入整个浮点数)并进行上述处理,直到碰到结束符为止,表明后缀表达式计算完毕,最终结果保存在栈中,并且栈中仅存这一个值,把它弹出返回即可。具体算法描述为:float Compute(char*str)/计算由str字符串所表示的后缀表达式的值,/表达式要以字符结束。Stack S;/用S栈


    注意事项

    本文(数据结构辅导 栈和队列 1.docx)为本站会员主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2022 冰点文档网站版权所有

    经营许可证编号:鄂ICP备2022015515号-1

    收起
    展开