文章目录
- 栈
- 一、栈的表示和实现
- 1.1 栈的概念
- 1.2 栈的初始化
- 1.3 栈的销毁
- 1.4 栈的扩容
- 1.5 元素入栈
- 1.6 元素出栈
- 1.7 返回栈顶元素
- 1.8 返回栈的元素个数
- 1.9 栈的判空与清空
- 1.10 栈的打印输出
- 二、栈的应用
- 2.1 数制转换
- 2.2 括号匹配检验
- 2.3 行编辑程序
- 2.4 表达式求值
- 2.5 汉诺塔
栈
一、栈的表示和实现
1.1 栈的概念
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端(表尾)被称为栈顶,相对地,把另一端称为栈底。
向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈又称为后进先出表(LIFO)
主要接口:
返回顶部
1.2 栈的初始化
创建一个新的空元素栈,栈顶指向下标0,此后指向栈顶数据的下一个;初始容量赋为0。
返回顶部
1.3 栈的销毁
将栈的内存地址释放并置空,将栈顶归零,栈的容量大小置零。
返回顶部
1.4 栈的扩容
如果栈顶指向与栈的空间大小相等(同为0
,初始分配4个大小空间;同不为0
,栈满,扩容)
返回顶部
1.5 元素入栈
入栈,首先判断栈满(空栈),进行扩容(初始分配空间)操作。接着,将元素从top
位置进行插入,并将 top++
。
返回顶部
1.6 元素出栈
出栈,需要进行判空操作,否则一直出栈会发生下标越界(C语言中不报错,通过断言终止程序)。top--
实现了栈的上界阻断,以达到元素出栈的目的。
返回顶部
1.7 返回栈顶元素
这里我们考虑 top = 0
,所以top
每次添加完元素后,指向的是下一个栈元素的位置,所以输出栈顶元素的时候需要将其减1。
返回顶部
1.8 返回栈的元素个数
同理,top
从0
开始,元素的个数即为top
的值大小。
返回顶部
1.9 栈的判空与清空
同理,栈元素的个数为0
,即为空栈。
返回顶部
1.10 栈的打印输出
因为栈是先进后出表,所以必须将元素从栈顶依次取出,才能获取下面的元素,所以需要结合出栈、获取栈顶元素函数实现栈的打印输出。
返回顶部
二、栈的应用
2.1 数制转换
十进制数 和其他
为整除运算,
例如:
N | N div 8 | N mod 8 |
1348 | 168 | 4 |
168 | 21 | 0 |
21 | 2 | 5 |
2 | 0 | 2 |
分析:对于任意的一个非负十进制整数,打印输出与其相等的8进制数。按照上述的计算过程,从低位到高位依次产生,最后逆序输出。其过程与栈的存取十分相似,满足先进后出的条件。
返回顶部
2.2 括号匹配检验
括号匹配的思想:
- 依次从左至右检查字符串,若为左括号,则入栈;
- 若遇右括号则获取栈顶元素,检查栈顶元素与当前元素是否匹配,
- 若匹配,则栈顶元素出栈。
- 反之,则不匹配,程序结束。
以此类推,直至检查完所有字符串。如果此时栈空则匹配,反之则不匹配。
解析:if (top + 1 == str[i] || top + 2 == str[i]) {...}
,通过如下的Ascall码字符匹配表可以看到,[
]
、{
}
之间相差为2,(
)
之间相差为1。
返回顶部
2.3 行编辑程序
一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区。
由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的。
较好的做法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。允许用户输入出差错,并在发现有误时可以及时更正。
例如,当用户发现刚刚键入的一个字符是错的时,可补进一个退格符“#”
,以表示前一个字符无效;如果发现当前键入的行内差错较多或难以补救,则可以键入一个退行符“@”
,以表示当前行中的字符均无效。
返回顶部
2.4 表达式求值
返回顶部
2.5 汉诺塔
汉诺塔(Tower of Hanoi),又称河内塔。源自印度古老传说的一个游戏,大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
- 若有1个圆盘时,需要移动1次;
- 若有2个圆盘时,需要移动3次;
- 若有3个圆盘时,需要移动7次……
不难看出,汉诺塔步数的数学规律为 (n为柱子上的圆盘个数)。
所以若有64个圆盘那将会移动2^64-1次(即:18,446,744,073,709,551,615次),若每次移动需要1s时间,则需要将近5849亿年的时间才能够做到。
假设:现有三个柱子A、B、C,其中有n个圆盘在A柱上,最终要实现把这n个圆盘从A柱借助B柱移动到C柱上。实现实现思路:先将n-1个圆盘从A柱移动到B柱上,然后将A柱上最后一个圆盘n移动到C柱上,最后再把B柱上的n-2个圆盘移动到A柱上,再将B柱上的最后一个圆盘n-1移动到C柱上,如此往复。如下图所示:
返回顶部