考察三个栈A、B、S,其中B、S初始为空。A中含有
对于长度为n的输入序列,每一个栈混洗都对应于由栈S的n次push操作和n次pop操作所构成的某一合法操作序列。
例如,对于
反过来,由n次push和n次pop构成的任何操作序列,只要满足任一前缀中的push不少于pop这一条件,则该序列唯一对应于某个栈混洗。
栈混洗的甄别
设B为A = { 1, 2, 3, …, n }的任一排列。
试证明,B是A的一个栈混洗,当且仅当对于任意
先证明“仅当”,采用反证法。
注意到,对于输入序列的任意三个元素,其在输出序列中的相对次序,与其他元素无关。因此,只需关注只有三个元素的情况
既然以上规律与其余元素无关,{ k, i, j }即可视作判定整体输出序列不可行的一个特征,我们不妨称之为“禁形”(forbidden pattern)
再证明“当”。
按照如下算法,对于不含禁形的输出序列,均可模拟出其栈混洗的过程1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17void stackPermutation ( stack<T> B, stack<T> A )
{
stack<T> RB;
while(!B.empty()) RB.push(B.pop());
stack<T> S;
while(!RB.empty())
{
while( S.empty() || RB.top()!=S.top() )
{
S.push(A.pop());
//cout<<"push"<<" ";
}
S.pop();
RB.pop();
//cout<<"pop"<<" ";
}
}//O(n)
若对任意
此类禁形是前面禁形的特例,将
分别称作“915”式禁形、“615”式禁形。
只需证明:只要B中含有“915”式禁形,则必然也含有“615”式禁形
做数学归纳。假定对于任何的
不妨设
1)
此时,
2)
此时,
栈混洗的计数
考虑第一个元素是第k个被压入栈B的元素的情形,由于其在S的栈底,此时栈S为空,栈A中留有n-k个元素。
由乘法原理可得共有
再由加法原理,
考虑边界情况,
可以解得结果为
即著名的卡特兰数。