栈的实现
使用向量来构成栈,向量首部为栈底,不可倒置,否则复杂度会上升为O(n)
template <typename T> class Stack:public Vector<T>{
void push(T const &e){insert(size(),e);}
T pop(){return remove(size()-1);};
T &top(){return (*this)[size()-1];}
}
栈的应用:进制转换(逆序输出)
输入与输出次序颠倒;递归次数和输出长度不易预知
短除法得到的余数需要逆序构成二进制数,而且事先不知道会转化为多少位的二进制数,所以可以吧余数全都压入栈,然后再pop出按照从高到低位排列
void convert(Stack<char> &S,_int64 n,int base){
static char digit[]=
{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F};
while(n>0){
S.push(digit[n%base]);
n/=base;
}
}
main(){
Stack<char> S; convert(S,n,base);
while(!S.empty())printf("%c",S.pop);
}
栈的应用:括号匹配(递归嵌套)
具有自相似问题可递归描述,但分支位置和嵌套深度不固定
括号匹配:遇到左括号入栈,遇到右括号把左括号出栈
栈的应用:栈混洗(延迟缓冲)
只允许将A的顶端元素弹出压入S,或者将S的顶端元素弹出压入B,这样的所有组成可能称为栈混洗
将A中的第一号元素最终压入为B中的第k号元素,则B中第前k-1号元素排列和第后n-k号元素排列无关,所以可得栈混洗总数为catalan数:
2
n
!
/
(
n
+
1
)
!
n
!
2n!/(n+1)!n!
2n!/(n+1)!n!
充要条件:甄别一个排列是否为栈混洗,如果A中为i,j,k,如果某个排列中出现了k,i,j,称为禁型,则该排列必不为栈混洗
合法的栈混洗序列与合法的括号匹配之间成对应关系
中缀表达式(延迟缓冲)
中缀表达式即为计算其中常见的带括号的从左往右的表达式
但是需要两个栈,一个存放数字,一个存放字符
运算符优先级顺序表,行表示当前运算符,列表示栈顶运算符