《数据结构(刘大有)》学习(3)

系列文章目录

一、绪论

二、顺序表、链表

三、堆栈、队列

四、数组


文章目录


堆栈


堆栈的定义和基本操作

定义

堆栈(简称栈)是插入和删除只能在其同一端进行的线性表,并按后进先出的原则进行操作

栈顶:允许进行插入、删除操作的一段,又称表尾。用栈顶指针(top)来指示栈顶元素

栈底:固定端,又称表头

空栈:表中没有元素

性质

  • 后进先出性:可以对输入序列部分或全局求逆;凡符合后进先出性,都可以应用栈,如十进制数与其他数制的转换、递归的实现、算术表达式求值等问题。堆栈也称后进先出(Last In First Out)表,简称LIFO表
  • 封闭性:插入和删除只能在栈顶进行,除了栈顶元素外,其他元素不会被改变。因而,栈的封闭性很好,使用起来很安全

基本操作

  • 初始化
  • push(item):压入一个元素(插入)
  • pop(item):弹出一个元素(删除)
  • peek(item):取出栈顶元素值
  • IsEmpty():判断栈空
  • IsFull():判断栈满
  • clean():置空栈

顺序栈

定义

  • 顺序存储方式实现的堆栈称为顺序栈
  • 顺序方式:使用数组存储
  • 存储要求:栈的规模必须小于或等于数组的规模,当栈的规模等于数组的规模时,就不能再向栈中插入元素

示例:

存放堆栈元素的数组:

        T stackArray[MaxStackSize]

栈顶所在数组元素的下标:int top

堆栈空: top = -1

堆栈满: top = MaxStackSize - 1

入栈算法

  1. 判断栈是否满
  2. top = top  + 1
  3. A[top] = item

出栈算法

  1. 判断栈是否空
  2. item = A[top]
  3. top = top + 1

存取栈顶元素算法

  1. 判断栈是否空
  2. item = A[top]

综述

  • 堆栈是一种操作受限制的线性表
  • push和pop操作只与栈顶有关
  • 堆栈的特性:后进先出
  • 堆栈状态
    • 栈空:top = -1
    • 栈满:top = MaxStackSize - 1
  • 使用数组实现顺序栈效率很高,但若同时使用多个栈,顺序栈将浪费大量空间

链式栈

定义

栈的链式存储方式称为链栈

链栈是运算受限制的单链表。其插入和删除操作只能在表头位置进行。因此,链栈没有必要像单链表那样附加头节点,栈顶指针top就是链表的头指针

链式表中不需要哨位结点


入栈算法

  1. 创建结点s(申请空间)
  2. item = data(s)     next(s) = top
  3. top = s

出栈算法

  1. 判断栈是否空
  2. item = data(top)
  3. q = next(top)
  4. 释放top结点空间
  5. top = q

存取栈顶元素

  1. 判断栈是否空
  2. item = data(top)

清空栈

  1. 如果栈不空,循环2,3,4
  2. q = next(top)
  3. 释放top结点空间
  4. top = q


顺序栈与链式栈比较

  • 空间复杂性
    • 顺序栈有空间浪费
    • 链式栈所需空间是根据需要随时申请,其代价是为每个元素提供空间以存储其next指针域
  • 时间复杂性
    • 栈顶的基本操作(压入、弹出和栈顶元素存取),顺序栈和链式栈的时间复杂性均为O(1)
    • 非栈顶元素的基本操作,顺序栈时间复杂性为O(1),链式栈为O(n)

堆栈的应用

括号匹配

  • 高级语言程序设计中的各种括号应该匹配,开括号与相应的闭括号匹配
    • “(” 与 “)”匹配
    • “[”与 “]” 匹配
    • “{”与 “}” 匹配
    • 示例:字符串{a=(b*c}+free( ) ]中的括号就没有匹配上,因为串中第一个闭括号 “}” 和最近的未匹配开括号 “(” 不匹配

  • 检查输入文本文件中的括号是否正确匹配,文件中的字符是按次序依次输入的
    • 如果输入的字符是开括号,应该将其存放起来,继续下一个字符的输入
    • 如果输入的是闭括号,应考察其与最近的未匹配开括号是否匹配,若匹配,则应将匹配的开括号从存放处删除
    • 每次用来和闭括号进行匹配的开括号都是最后输入的,这符合堆栈的后进先出策略,因此用堆栈来存放开括号是合理的

十进制数转换为r进制数

  • 十进制数转换为r进制数
    • 十进制整数 x 除以基数 r,所得整余数是 r 进制数 y 的最低位 y0,压入堆栈
    • 用 x除以 r 的整数商除以 r,所得整余数是 y 的次低位 y1,压入堆栈,依此类推
    • 直到商为 0 ,所得整余数是 y 的最高位ym,压入堆栈;此时,栈中的 m+1 个 r 进制数即为所得

算数表达式求值

  • 算术表达式求值是程序设计语言编译中的一个最基本问题。它的实现方法是栈的一个典型的应用实例
  • 表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的
  • 其中操作数可以是常数,也可以是变量或常量的标识符;运算符是算术运算符( + , - , * , / );界限符为左右括号和标识表达式结束的结束符

中缀表达式——运算符在操作数之间
        如: A * B / C
运算规则:

  • 先计算括号内,后计算括号外
  • 在无括号或同层括号内,先进行乘除运算,后进行加减运算,即乘除运算的优先级高于加减运算的优先级
  • 同一优先级运算,从左向右依次进行

  • 用计算机来处理中缀表达式比较复杂。一个中缀表达式中有多少个运算符,原则上就得对表达式扫描多少遍,才能完成计算
  • 在编译系统中,把中缀表达式转换成另外一种表示方法,即后缀表达式,然后对后缀表达式进行处理,后缀表达式也称为逆波兰式

后缀表达式
1929 年,由波兰逻辑学家(Lukasiewicz)提出。
  [例]   A * B / C;
            A B * C / ;

  • 定义:运算符紧跟在两个操作数之后的表达式称为后缀表达式
  • 优点
    • 后缀表达式没有括号
    • 不存在优先级的差别
    • 计算过程完全按照运算符出现的先后次序进行

中缀表达式转换成后缀表达式

  • 首先设定一个运算符栈,用来保存扫描中缀表达式得到的暂不能放入后缀表达式中的运算符
  • 基本思想:从左到右依次读出中缀表达式中的各个符号(操作数或运算符),每读出一个符号后,根据如下运算规则进行处理:
    • 假如是操作数,将其放入后缀表达式中
    • 如果是运算符
      • 栈空:运算符放入栈中
      • 栈不空:比较当前读到的运算符与栈顶运算符的优先级
        • 假如读出的运算符的优先级大于栈顶运算符的优先级,则将其压入运算符栈,读中缀表达式的下一个符号
        • 若栈顶运算符的优先级比读到的运算符的优先级高或二者相等,弹出栈顶运算符放入后缀表达式中,返回(2)继续比较
        • 遇到“(”,压入堆栈
        • 遇到“)”,把“(”上面的操作符依次弹出加到后缀表达式中,“(”出栈
        • 假如读出的是表达式结束符“#”,栈中剩余的运算符依次出栈并写入到后缀表达式中,转换完成

后缀表达式计算 

  • 从左到右读入后缀表达式,若读到的是操作数,将它压入堆栈
  • 若读到的是运算符,就从堆栈中连续弹出两个元素(操作数),进行相应的运算,并将结果压入栈中
  • 读入结束符时,栈顶元素就是计算结果。
     

拓展

  • 递归
  • 双栈:两个底部相连的栈
  • 超栈:一种插入首先的双端栈,插入操作限制在一段,而删除操作允许在两端

多栈共享邻接空间

在计算机系统软件中,各种高级语言的编译系统都离不开栈的使用。常常一个程序中要用到多个栈,为了不发生上溢错误,就必须给每个栈预先分配一个足够大的存储空间,但实际中很难准确地估计。另一面方面,若每个栈都预分配过大的存储空间,势必会造成系统空间紧张。若让多个栈共用一个足够大的连续存储空间,则可利用栈的动态特性使它们的存储空间互补。这就是栈的共享邻接空间

双向栈

栈的共享中最常见的是栈的共享。假设两个栈共享一维数组stack[MAXNUM],则可以利用栈的“栈底位置不变,栈顶位置动态变化”的特性,两个栈底分别为-1和MAXNUM, 而它们的栈顶都往中间方向延伸。因此,只要整个数组stack[MAXNUM]未被占满,无论哪个栈的入栈都不会发生上溢。


队列

队列的定义和基本操作

定义 

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

队首:允许进行删除的一端称为队首

队尾:允许进行插入的一端称为队尾

没有元素的队列称为空队列

性质

  • 先进先出性:可以对输入序列起缓冲作用;凡符合先进先出性,都可以应用队列,如果操作系统中作业调度、图的广度优先搜索等问题
  • 封闭性:与栈类似,队列的封闭性也很好,使用起来很安全

基本操作

  • 队列初始化
  • 向队尾添加元素(入队)
  • 删除队首元素(出队)
  • 获取队首元素(存取)
  • 判断队列是否为空
  • 确定队列元素个数
  • 置空队列

顺序队列

用顺序存储方式存储的队列被称为顺序队列。

  • 存放队列元素的数组
    • T qlist[MaxQSize]
    • front 队首元素的数组下标
    • rear(要入队元素的下标)队尾元素的下标+1

  •  插入:rear = rear+1

  • 删除队首元素的方法1:令front = front + 1
    • 出现问题,空间利用差

  • 删除队首方元素法2:元素向前移动,front总是等于0

  • 删除队首元素方法3 :循环队列
    • 删除时front往前移动一位
    • 插入元素时:rear顺时针移动一位


 链式队列

限制仅在表头进6行删除操作和表尾进行插入操作的单链表

结构:

插入操作

  • s ← new()   data(s)← item  next(s)← NULL
  • 判断队列是否为空
  • 若为空  front ← s  
  • 非空  next(rear)← s
  • rear ← s

删除操作

  • 判断队列是否为空
  • 不为空, q ← front ,item ←data(q)
  • front ← next(front)
  • delete q
  • 判断出队后是否为空
  • 若为空 rear ← NULL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值