数据结构之初识stack

栈结构一定要结合具体应用场景去理解。。。

主要参考邓俊辉老师的数据结构课程,基于c++的实现。

一 基本概念

栈(stack)是受限的序列:只能在栈顶(top)插入和删除,栈底为盲端。

特点:先进后出(FILO),后进先出(LIFO)

基本接口:size() / empty()

      push()   入栈

      pop()    出栈

      top()     查顶

拓展接口:getMAX()...

基本实现:

栈也属于序列的特例,故可由向量或者列表派生

1 template <typename> class Stack :: public Vector<T> { //由向量派生的栈模板类
2 
3 pubilic: //size(),empty()以及其他开放接口均可直接沿用
4     void push(T const &e) {insert(size(),e);} //入栈
5     T pop() {return remove(size() - 1);} //出栈
6     T &top() {return (*this)[size()-1];} //取顶
7 }

上述三种基本接口实现均只需Ο(1)时间。

二 应用场景

什么时候用到栈?需满足两个条件:1.需要保存状态;2.状态输出有先后顺序

典型应用场合

逆序输出 :输出次序与处理过程颠倒;递归深度和输出长度不易预知。实例:进制转换

延迟缓冲 :线性扫描算法模式中,在预读足够长之后,方能确定可处理的前缀。实例:括号匹配

三 实例

1.进制转换

算法实现

 1 void convert( Stack<char> & S,_int64 n,int base) {
 2     static char digit[] = //新进制下的数位符号,可视base取值范围适当扩充
 3      {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
 4     while(n > 0) { //由低到高,逐一计算出新进制下的各数位
 5         S.push(digit[n % base]); //余数(当前的数位)入栈
 6         n /= base; //n更新为其对base的除商
 7     }
 8     
 9 }
10 main() {
11     Stack<char> S; convert( S, n, base); //用栈记录转换得到的各数位
12     while ( !S.empty()) printf("%c", S.pop()); //逆序输出
13 }

2.括号匹配

算法实现

 1 bool paren( const char exp[], int lo, int hi) { //exp[lo,hi)
 2     Stack<char> S; //使用栈记录已发现但尚未匹配的左括号
 3     for ( int i = lo; i < hi; i++) //逐一检查当前字符
 4          if ( '(' == exp[i]) S.push( exp[i] ); //遇左括号,入栈
 5          else if (!S.empty()) S.pop(); //遇右括号,若栈非空,则弹出左括号
 6             else return false; //否则栈已空,括号不匹配
 7     return S.empty(); //最终,当且仅当匹配时栈空
 8     
 9     
10 }

四 栈混洗

混洗总数:SP(n) = (2n)! / (n+1)! / (n)!

不含“禁形”的混洗排列都是合法的。原排列为<...i <j<k...],混洗排列为[...k,....,i,....,j....,....>这种是“禁形”。

 

posted @ 2018-05-05 23:53  loongnotdragon  阅读(184)  评论(0编辑  收藏  举报