想要存储逻辑关系为“一对一”的数据,除了顺序表和链表存储,还可以用栈结构存储。
栈是一种“特殊”的线性存储结构,它的特殊之处体现在以下两个地方:
1、元素进栈和出栈的操作只能从一端完成,另一端是封闭的。
通常,将元素进栈的过程简称为“入栈”、“进栈”或者“压栈”;将元素出栈的过程简称为“出栈”或者“弹栈”。
2、栈中无论存数据还是取数据,都必须遵循“先进后出”(LIFO)的原则,即最后入栈的元素最先出栈。
图为例:
很容易可以看出是元素 1 最先入栈,然后依次是元素 2、3、4 入栈。在此基础上,如果想取出元素 1,根据“先进后出”的原则,必须先依次将元素 4、3、2 出栈,最后才能轮到元素 1 出栈。
注意:
我们习惯将栈的开口端称为栈顶,封口端称为栈底。图中,元素 4 一侧为栈顶 (top),元素 1 一侧为栈底 (bottom)。
栈就像装数据的桶或箱子。假设我们要取出放在箱子里面底下的东西(放入的比较早的物体),我们首先要移开压在它上面的物体(放入的比较晚的物体)。也可以类比成一叠松饼。
栈的实际应用
对于刚刚接触栈存储结构的人来说,可能很难理解它有什么具体的用法?
栈是一种特殊的线性存储结构,借助它的“特殊性”,可以解决很多实际问题。
1) 实现浏览器的“回退”功能
比如用浏览器打开 A 页面,然后从 A 页面跳转到 B 页面,然后再从 B 页面跳转到 C 页面。这种情况下,如果想回到 A 页面,有两种方法:
- 重新搜索找到 A 页面;
- 借助浏览器的“回退”功能,先从 C 页面回退到 B 页面,再从 B 页面回退到 A 页面。
浏览器的“回退”功能底层就是用栈存储结构实现的:
当从 A 页面跳转到 B 页面时,浏览器会执行入栈操作,A 页面信息会存入栈中;
同样,从 B 页面跳转到 C 页面时,B 页面信息会存入栈中。
当点击浏览器的“回退”按钮时,浏览器会执行“出栈”操作,根据“先进后出”的原则,B 页面先出栈,然后 A 页面出栈,这样就实现了“回退”的功能。
2) 解决一些实际问题
借助栈存储结构,可以快速解决类似“进制转换”、“括号匹配”等问题。
栈的基本操作
InitStack(S) 初始化操作,建立一个空栈S
StackEmpty(S) 判空栈操作,若S为空栈,返回一个真值
Push(S,x) 进栈操作,在栈S顶插入一个元素X
Pop(S,*y) 出栈操作,若栈S不空, 删除栈顶元素并保存在 *y中
GetTop(S, *y) 取栈顶元素操作,若栈S不空则取栈顶元素保存在 *y中