一、栈的定义

栈是(stack)是限定尽在表尾进行插入和删除操作的线性表。
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。

二、进栈出栈变化形式

注意: 并不是最新进栈的元素只能最后处栈。如,我们现在有三个元素一次进栈,次序会有以下5种:
1. 1、2、2进,再3、2、1出,出栈次序为321;
2. 1进,1出,2进,2出,3进,3出,出栈次序为123;
3. 1进,2进,2出,1出,3进,3出,出栈次序为213;
4. 1进,1出,2进,3进,3出,2出,出栈次序为132;
5. 1进,2进,2出,3进,3出,1出,出栈次序为231。

三、栈的顺序存储结构及实现

(一)栈的顺序存储结构
栈是线性表的特例,栈的顺序存储结构也是线性表存储结构的简化。线性表是用数组实现的,用下标为0的那一端作为栈底使栈变化最小。
我们定义一个top变量来指示栈顶元素在数组中的位置。若存储栈的 长度为StackSize,则栈顶位置top必须小于StackSize。当栈存在一个元素时,top=0.因此,通常把空栈的判定条件定位top=-1.

进栈:push;出栈:pop。(就像子弹的压和弹)。
没有涉及循环,两者的时间复杂度均为1.

两栈共享空间:两个类型相同的栈,则可以共享存储空间。让一个栈的栈底为数组的始端,即下标为0处,另一个栈为数组的末端,即下标为数组长度n-1处。这样,两个栈如果增加元素,就是两端点向中间延伸。两个栈见面之时,也就是两个栈指针相差1,即top1+1==top2为栈满。

(二)栈的链式存储结构
栈的链式存储结构,简称为链栈。
链栈的栈顶和单链表的头指针重合,不需要头结点。
对于链栈来说,不存在栈满的情况,除非内存已经没有可以使用的空间。如果真的发生,就是操作系统已经面临死机崩溃的情况,而不是这个链栈是否真的溢出。
对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top=NULL的时候。

对比顺序栈和链栈,它们在时间复杂度上是一样的,均为O(1)。对于空间性能,顺序栈要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便,而链栈则要求每个元素都有指针域,这同时也增加了一定的内存开销,但对于栈的长度无限制。所以它们的区别和线性表中讨论的一样,如果栈的使用过程中元素变化不可预料,有时候很小,有时候很大,那么最好是用链栈,如果它们的变化在可控范围内,建议使用顺序栈会更好一些。

四、栈的作用

有的人可能会问,用数组或链表直接实现功能不就行了吗?为什么还要引入栈这个数据结构呢?
其实这和我们明明有两只脚可以走路,干嘛还要乘汽车、火车、飞机一样。理论上,陆地上的任何地方,你都是可以用双脚走到的,可那需要多长时间和精力呢?我们更关注的是到达而不是如何去的问题。
栈的引入简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚焦于我们要解决的核心问题。反之,像数组等,因为要分散精力去考虑数组下标的增减问题,反而掩盖了问题的本质。
所以,现在的许多高级语言,比如Java,C#等都有对栈结构的封装,你可以不关注它的实现细节,就可以直接使用Stack的push和pop方法,非常方便。

五、栈的应用

(一) 递归
斐波那契数列
(二)四则运算表达式求值
后缀(逆波兰)表示法:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
中缀表示法:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为中缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号有优先级不高于栈顶符号(乘除有限加减)则栈顶元素依次出栈并输出,并将当前符号进栈,直到最终输出后缀表达式为止。

队列

一、队列定义

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

二、队列的抽象数据类型

同样是线性表,队列也有类似线性表的各种操作,不同的就是插入数据只能在队尾进行,删除数据只能在队头进行。

三、循环队列

队列也有线性表的两种存储方式:顺序存储和链式存储。
入队操作是在队尾增加一个元素,时间复杂度为O(1)。但是,出队时,如果规定队列中的元素都放在前n个位置,则第一个元素出队后,后面的元素都要向前移动,以保证对头不为空,也就是下标为0的位置不为空,此时时间复杂度为O(n)。
但是,我们可以想,如果没有队列的元素都必须放在前n个位置的规定,出队的性能就会大大增加。于是,我们因为两个指针,front指向对头元素,rear指针指向队尾的下一个元素,当front==rear,队列为空。这样,当出队时,只需移动front指针即可。但是,这样也会有一个问题,一个队列不可能只有出队,当继续进行入队操作致使队尾已经填满,rear指针指向队列外时,继续入队就可能产生数组越界的错误。但是,由于前面已经进行过出队操作,所以这个队列前面会有空位置,这种现象称为“假溢出”。这里举个例子,现实生活中,当你上了一辆公交车,发现前面有两个空位置,但后排的座位都已经满了。这是,你不会告诉自己,后面没座了,立马下车,等待下一辆。我们都不会这么笨,而都会坐在前面的位置。
这时,就引入了循环队列的概念。循环队列就是首尾相接的顺序存储结构。
那么,问题又来了,前面提到当front==rear时,队列为空,但在循环队列中,这个结论显然不成立。所以,如何判断队列是空还是满呢?以下给出两种方法:
1. 设置一个标志变量flag,当front==rear,且flag=0时队列为空,当front==rear,且flag=1时队列满。
2. 当队列空时,条件就是front=rear,当队列满时,我们修改条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。
我们来重点讨论第二种方法,由于rear可能比front大,也可能比front小,所以它们只相差一个位置时就是满的情况,但也可能是相差整整一圈。所以,若队列的最大尺寸是QueueSize,那么队满的条件是(rear+1)%QueueSize==front(取模%的目的就是为了整合front和rear大小为一个问题)
通用的计算队列长度的公式为(rear-front+QueueSize)%QueueSize
循环队列的相关条件和公式:
1. 队空条件:rear==front
2. 队满条件:(rear+1) %QueueSIze==front,其中QueueSize为循环队列的最大长度
3. 计算队列长度:(rear-front+QueueSize)%QueueSize
4. 入队:(rear+1)%QueueSize
5. 出队:(front+1)%QueueSize
到这里,大家可以发现,但是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列有面临着数组可能会溢出的问题,所以我们还需要研究一样不需要担心队列长度的链式存储结构。

四、队列的链式存储结构及实现

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾尽头出而已,称为链队列。将队头指针指向链队列的头结点,队尾指针指向终端结点。
空队列是,front和rear都指向头结点。
入队操作:就是在链尾插入结点。
出队操作,就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点。

对比循环队列和链队列,时间上,其实它们基本操作都是常数时间,即都为O(1)的。不过循环队列是事先申请好空间,使用期间不释放,而对于链队列,每次申请和释放结点也会存在一些时间开销,如果入队出队频繁,则两者还是存在细微差异。对于空间上来说,循环队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上的开销,但也可以接受。所以在空间上,链队列更加灵活。
总的来说,在可以确定队列长度最大值的情况下,建议使用循环队列,如果无法预估队列长度,则用链队列。

大话数据结构—栈与队列相关推荐

  1. 大话数据结构-栈与队列

    文章知识点来至于大话数据结构里边章节知识, 这篇主要介绍栈与队列在计算机中存储形式, 以及在某些算法领域中对栈和队列的相关应用.章节最后介绍了著名的逆波兰表达式, 以及通过算法来实现该表达式的运算过程 ...

  2. 数据结构栈和队列_使您的列表更上一层楼:链接列表和队列数据结构

    数据结构栈和队列 When you want to store several elements somewhere in a program, the go-to data type is an a ...

  3. 数据结构栈与队列的应用之汽车轮渡问题——自己的一些理解

    本题摘自王道数据结构栈与队列的应用的课后题,题目如下: 某汽车轮渡口,过江渡船每次能载10辆汽车过江.过江车辆分为客车类和货车类,上渡船有如下规定:同类车先到先上船,客车先于货车上船,且每上4辆客车, ...

  4. 数据结构——栈与队列相关题目

    数据结构--栈与队列相关题目 232. 用栈实现队列 思路 225. 用队列实现栈 1.两个队列实现栈 2.一个队列实现栈 20. 有效的括号 思路 1047. 删除字符串中的所有相邻重复项 思路 1 ...

  5. 第十章 基本数据结构——栈和队列

    摘要 本章介绍了几种基本的数据结构,包括栈.队列.链表以及有根树,讨论了使用指针的简单数据结构来表示动态集合.本章的内容对于学过数据结构的人来说,没有什么难处,简单的总结一下. 1.栈和队列 栈和队列 ...

  6. 数据结构——栈与队列操作(用栈模拟队列)

    [栈与队列操作] 问题描述:假设有两个长度相同的栈 S1,S2,已知以下入栈.出栈.判栈满和判栈空操作: void Push(S,x); Elemtype Pop(S); bool StackFull ...

  7. 【数据结构-栈和队列】详解栈和队列(代码+STL+原理)

    一.栈的应用 栈是一种先进后出(FILO)的数据结构 1.1 栈的操作实现 清空(clear): // 栈的清空操作就是把栈顶top置为-1 void clear(){top=-1; } // 清空栈 ...

  8. 算法与数据结构 -- 栈与队列(四)

    栈与队列定义了数据的操作 一.栈 栈是一种先入先出的数据结构.可以用顺序表实现,也可以用链表实现 栈操作 判断是否为空 压栈.入栈push 出栈 pop 返回栈顶元素 peek 栈的元素个数 # co ...

  9. 六十二、数据结构栈和队列的相互实现

    @Author:Runsen 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. ---- Runsen 算法,一门既不容易入门,也不容易精通的学问. 栈和队列都是用来保存数 ...

最新文章

  1. 元学习(meta learning) 最新进展综述论文,28页pdf
  2. [置顶] 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅
  3. UNP Chapter 9 - 基本名字与地址转换
  4. 直播预告丨B2B 企业如何高效获客增长?
  5. word2vec原理_Word2vec详细整理(1)—权重更新原理
  6. mysql inodb主键bug_MySQL的这个bug,坑了多少人?
  7. 开源.NET企业级应用系统 OpenVista
  8. dp线和hdmi区别_HDMI铜线与光纤线有啥区别?为什么铜线传播速度更快?看完涨知识...
  9. android手机常用功能,Windows Phone 7/Android手机常用功能对比
  10. Windows Server 2008 R2托管服务账户(MSA)的功能
  11. Storm介绍及核心组件和编程模型
  12. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_02 递归_3_练习_使用递归计算阶乘...
  13. 虚短虚断以及部分运放电路
  14. 直播知识点实录|百度大脑EasyDL产业应用系列 安全生产专场
  15. 自封装验证手机号码、邮箱格式、身份证号的工具
  16. 怎么使excel表只显示一部分分页内容
  17. MATLAB如何去掉坐标轴上的数字或去掉坐标轴但保留刻度边框
  18. 【目标检测】YOLOv5-PyQT可视化例程开发
  19. python如何创建excel文件_python创建Excel文件数据的方法
  20. 多种多样的Photoshop 的撤消命令

热门文章

  1. 【Java IO知识】读取中文乱码问题解决
  2. 判断滚动条是否到达页面的尾部
  3. Could not load the assembly 'DotNetNuke.Authentication.LiveID'. Make sure that it is compiled before
  4. 【第二届】Erlang Fans交流会(补充事宜)
  5. ASP.NET2.0学习8--WebPart部件
  6. oracle删除实体,oracle 按条件删除、查询表
  7. java ean13 条形码_【教程】Spire.Barcode 教程:如何在C#中创建EAN-13条码
  8. android高德地图搜索地址,地点/周边搜索-Android平台-开发指南-高德地图车机版 | 高德地图API...
  9. 二叉树学习——简单入门题
  10. 160 - 49 DueList.4