本篇文章将详细讲述数据结构 栈与队列 章节的内容。
本教程编程语言采用 JAVA ,文章框架参考自 HUST数据结构PPT ,源码内容参考自 尚硅谷 JAVA 数据结构教程 。
栈与队列章节部分概念方面比较简单,将放在具体的代码实现过程中。
栈的定义与操作
定义与术语
栈的基本操作
Initstack(s)// 置 s 为空栈Push(s,e)// 元素 e 进栈 sPop(s,e// 元素 e 出栈 sGettop(s,e)// 顶元素拷贝到 eEmpty(s)// 判断是否为空栈
栈的应用场景:
- 子程序的调用: 在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。 如方法中调用方法。
- 处理递归调用: 和子程序调用类似,只是除了存储下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
- 表达式的转换(中缀表达式转后缀表达式)与求值(实际解决)
- 二叉树的遍历
- 图形的深度优先(depth-first)搜索法
栈的存储表示和操作实现
顺序栈(用数组来模拟栈)
-
实现思路
- 定义一个数组,来模拟栈。
- 定义一个
top变量表示栈顶,初始化为-1。 - 入栈:
stack[++top] = data - 出栈:
return stack[top--]
-
代码实现
查看代码实现
- 编写
ArrayStack类
- 编写测试函数
- 测试结果
Terminal window pushTest:index=3 value=4index=2 value=3index=1 value=2index=0 value=1Stack full!popTest:index=1 value=2index=0 value=1pop data:2index=0 value=1pop data:1No data in stack! - 编写
链式栈(用链表来模拟栈)
-
实现思路
-
定义一个链表来模拟栈,成员变量有:
- 最大存储量:
maxSize - 栈中元素个数:
size - 栈顶元素(同时作为表头):
top
- 最大存储量:
-
入栈:
Node temp = top;top = new Node(value);top.next = temp;size++; -
出栈
Node temp = top;top = top.nextsize--;return temp.value; -
代码实现
查看代码实现
- 编写
LinkedListStack类
- 编写测试函数
- 测试结果
Terminal window pushTest;Node{value=4}Node{value=3}Node{value=2}Node{value=1}Stack full!popTest;Node{value=2}Node{value=1}pop data:2Node{value=1}pop data:1Stack empty! - 编写
栈的应用
栈的一个十分经典的应用就是计算机如何计算表达式。
中缀表达式
-
基本概念 中缀表达式是一个通用的 算术 或 逻辑公式表示方法 。 操作符 是以 中缀形式 处于操作数的 中间 (例: 3 + 4 ),中缀表达式是人们常用的算数表达方式。
中缀表达式就是 常见的运算表达式,如
(3+4)x5-6。中缀表达式的求值是人类最熟悉的,但是对于计算机来说却不好操作:- 需要计算运算符的优先级
- 对于中括号来说,笔者想不出实现办法 因此,在计算结果时,往往会将 中缀表达式 转成其他表达式,一般转成后缀表达式。
-
代码实现
如上图,代码实现的基本思路为:
- 先扫描字符串,可以通过一个 index 变量来辅助扫描。
- 如果发现是一个 数字 ,直接入栈。
- 如果发现是一个 操作符 ,分一下情况:
- 当 当前操作符 的优先级 大于栈顶符号 :将 当前操作符 入符号栈。
- 当 当前操作符 的优先级 小于或等于栈顶符号 :
- 弹出数栈中的 2 个数值。
- 弹出符号栈顶的元素。
- 2 个数字与符号进行运算。
- 将计算结果压入数栈。
- 将当前操作符压入符号栈。
- 当扫描完毕时:
- 顺序地从数栈中弹出 2 个数。
- 从符号栈中弹出 1 个操作符。
- 将他们进行计算,然后把计算结果压入数栈中。
- 最后数栈中只会存在一个数值,那就是计算结果。
查看代码实现
- 使用前面实现的数组栈来做我们的容器,只增加了一个查看栈顶元素的
peek()方法。
- 计算器代码实现
后缀表达式
后缀表达式 又称为 逆波兰表达式 ,与前缀表达式类似,只是 运算符 位于 操作数 之后。
-
后缀表达式求值过程:
- 从 左到右 扫描表达式。
- 遇到 数字 时,将数字压入堆栈。
- 遇到 符号 时,将数字栈栈顶和次顶元素弹出,计算顺序为 次顶元素(符号)栈顶元素。
- 重复上述过程直至剩余最后一个结果。
-
中缀表达式转后缀表达式
- 初始化两个栈
- 符号栈 s1
- 中间结果栈 s2
- 从左到右扫描中缀表达式
- 遇到操作数直接压入 s2
- 遇到运算符时
- 若 s1 为空,或者栈顶元素符号位
(,则将其压入符号栈 s1 - 若优先级比栈顶运算符 高 ,也将其压入符号栈 s1
- 若优先级比栈顶运算符 低或者相等 ,则弹出 s1栈顶元素,将其压入 s2 中,然后继续循环步骤 4,直至当前符号压入 s1
- 若 s1 为空,或者栈顶元素符号位
- 遇到括号时
- 如果是左括号
(:直接压入 s1 - 如果是右括号
): 则依次弹出 s1栈顶的运算符,并压入 s2 直到遇到 左括号 为止,此时将这一对括号 丢弃
- 如果是左括号
- 重复步骤 2 到 5 ,直到表达式的最右端
- 将 s1 的运算符依次弹出并压入 s2 ,结果的 逆序 即为:中缀表达式转后缀表达式的结果
-
中缀表达式转后缀表达式的举例说明
查看举例
将中缀表达式:
1+((2+3)*4)-5转化为后缀表达式扫描到的元素 s2(栈底->栈顶) s1(栈底->栈顶) 说明 11null遇到操作数直接压入 s2 +1+s1为空,直接压入(1+ (运算符为 (,直接压入(1+ ( (运算符为 (,直接压入21 2+ ( (遇到操作数直接压入 s2+1 2+ ( ( +栈顶元素为 (,直接压入s131 2 3+ ( ( +遇到操作数直接压入 s2 )1 2 3 ++ (遇到 )时,依次弹出 s1栈顶的运算符,并压入 s2 直到遇到 左括号 为止,此时将这一对括号 丢弃*1 2 3 ++ ( *栈顶元素为 (,直接压入s141 2 3 + 4+ ( *遇到操作数直接压入 s2)1 2 3 + 4 *+遇到 )时,依次弹出 s1栈顶的运算符,并压入 s2 直到遇到 左括号 为止,此时将这一对括号 丢弃-1 2 3 + 4 * +-优先级比栈顶运算符 低或者相等 ,则弹出 s1栈顶元素,将其压入 s2 中,然后继续循环步骤 4,直至当前符号压入 s1 51 2 3 + 4 * + 5-遇到操作数直接压入 s2null1 2 3 + 4 * + 5 -null将 s1 的运算符依次弹出并压入 s2 ,结果的 逆序 即为:中缀表达式转后缀表达式的结果 -
代码实现
查看代码实现
- 逆波兰表达式的计算器
实现思路:
- 先将后缀表达式转化为一个 List
- 对这个 List 进行遍历然后进行计算
- 中缀表达式转后缀表达式代码实现
前缀表达式
-
前缀表达式又称 波兰表达式 ,前缀表达式的 运算符位于操作数之前。
-
前缀表达式求值过程:
- 从 右到左 扫描表达式。
- 遇到 数字 将数字压入栈。
- 遇到 符号 弹出数字栈的两个元素,与运算符计算,顺序为: 先 弹出的 (符号) 后 弹出的。
- 重复上述过程直至剩余最后一个结果。
-
中缀表达式转前缀表达式
查看思路
(1) 初始化两个栈:运算符栈 S1 和储存中间结果的栈 S2; (2) 从右至左扫描中缀表达式; (3) 遇到操作数时,将其压入 S2; (4) 遇到运算符时,比较其与 S1 栈顶运算符的优先级: (4-1) 如果 S1 为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈; (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入 S1; (4-3) 否则,将 S1 栈顶的运算符弹出并压入到 S2 中,再次转到(4-1)与 S1 中新的栈顶运算符相比较; (5) 遇到括号时: (5-1) 如果是右括号“)”,则直接压入 S1; (5-2) 如果是左括号“(”,则依次弹出 S1 栈顶的运算符,并压入 S2,直到遇到右括号为止,此时将这一对括号丢弃; (6) 重复步骤(2)至(5),直到表达式的最左边; (7) 将 S1 中剩余的运算符依次弹出并压入 S2; (8) 依次弹出 S2 中的元素并输出,结果即为中缀表达式对应的前缀表达式。
值得注意的是 s2 输出结果 不需要 逆序
代码实现思路与后缀表达式类似,且使用情况较少,故不再详细讲述。
队列
基本概念
数组模拟队列
声明 4 个变量:
arr:用来储存数据的数组maxSize:该队列的最大容量front:队首下标,随着数据输出而改变rear:队尾下标,随着数据输入二改变
队列中常用操作分析,以 add ,把数据存入队列为例,思路分析:
- 存入数据后将尾指针往后移:
rear + 1,前提是当front == rear时,队列是空的 - 若尾指针
rear < maxSize - 1:- 则将数据存入
rear所指的数组元素中 - 否则无法存入数据,
rear = maxSize - 1表示队列满了
- 则将数据存入
查看代码实现
循环队列
基本思路:
查看代码实现
评论
评论加载中…







