栈(Stack)是限定仅在表尾进行插入或删除操作的线性表。
表尾端称为栈顶(top)表头端称为栈底(bottom)不含元素的空表称为空栈。
出栈 进栈
↑ ↓
----------
| an | ←栈顶 top
----------
| . |
| . |
| . |
| . |
| . |
----------
| a2 |
----------
| a1 | ←栈底
----------
★其实吧,这东西非常好理解,你可以把栈理解为一口井,或者一个坑。
东西掉进去,想出来只能从上面爬出来。你总不可能从坑地下挖个地道穿到地球对面去。
你掉进去了之后,后来又有个人倒霉掉进去了,你自然就被压到下面了,除非上面那个人出来,你才能从坑里出来。(叠罗汉)
栈的关键 栈顶top,栈顶top表示了这个坑里有多少个倒霉蛋。
多一个倒霉蛋,他就往上移动一个。top++;
★这种结构是先进后出的。(先进来的掉的比较里面)
★应用:数值转换,括号匹配,行编辑程序,迷宫求解,表达式求值
☆数值转换:(1348)10进制 ----> (2504)8进制
原理:N = ( N div d ) X d + N mod d(其中:div为整除运算,mod为求余运算)
N N div 8 N mod 8 求得顺序 输出顺序
1348 168 4 ↓ ↑
168 21 0 ↓ ↑
21 2 5 ↓ ↑
2 0 2 ↓ ↑
(((8 X 0 + 2)X 8 + 5)X 8 + 0)X 8 + 4 =1348
综上:余数 红色的2 5 0 4就是所求的8进制。
为什么用栈?→ 因为求得顺序和输出顺序刚好是相反的,所以要用到栈。将先输入的,最后再放出来。
☆括号匹配:[ ( [ ] [ ] ) ] 为正确格式,[ ( ] ) 或 ( [ ( ) ) 或 ( ( ) ] 都是不正确的格式
操作:未匹配就进栈,匹配就出栈。
栈中状态 还未输入
[ ( [ ] [ ] ) ] 未匹配,下一步进栈
[ ( [ ] [ ] ) ] 未匹配,下一步进栈
[ ( [ ] [ ] ) ] 未匹配,下一步进栈
[ ( [ ] [ ] ) ] 匹配, 下一步出栈
[ ( [ ] ) ] 完成出栈
.... ..... 直到匹配完最后
如果最后栈为空,那么就是正确的格式。 如果最后栈里还有存在东西,那就时不正确的格式。
为什么用栈?→ 就近匹配,匹配就消除,所用栈比较方便。特别是删除操作(将大的问题变成小的问题,又不影响其他)这和普通的数组形式有着完全不一样的方便。
☆行编辑程序:w h l i # # i l r # e ( s # * s ) 实际是while( * s ) →编辑器的 输入缓冲区
直接存入用户数据区是不好的,因为可能会写错,所以需要一个缓冲区(草稿纸),在草稿纸(缓冲区)上写完之后,确认正确后再抄到试卷上(用户数据区)
w h i l e ( * s )
w h l i # # w h l i # # i l r #
↑ ↑ ↑ 。。。。。 省略
写错了,输入两个#,表示删除两个 写错了,输入一个#,表示删除一个
为什么用栈?→ 倒着写入数据区的优势:没有遇到# 说明目前都是正确的,只管写到数据区就是了;如果遇到# 说明下一个是不要的,就弹出丢掉。
☆迷宫求解:不细讲了,就是正确的进栈,发现走不通,就退栈。
☆表达式求值,就不细讲了,编译原理中写过。
★说了这么多,具体代码怎么弄呢。
手动写一个栈(顺序栈):传送门。(其实也可以写一个链表的形式,就像线性表一样)
可以用C++自带的STL 已经内置了一个栈,所以现成的工具为什么不用呢:传送门