出栈次序问题 (转)
编号为 1 到 n 的 n 个元素,顺序的进入一个栈,则可能的出栈序列有多少种?
![C_n = \frac{1}{n+1}{2n \choose n} = \frac{(2n)!}{(n+1)!n!}](http://upload.wikimedia.org/math/d/1/1/d118d8cea7b639dfd5244fcba65910cf.png)
#include <stdio.h> #define ELEMNUM 6; int getPermuStack(int n, int m) { if(n == 0)//递归边界 return 1; if(m == 0)//(n,0)问题的处理 return getPermuStack(n-1, 1); return getPermuStack(n, m-1) + getPermuStack(n-1, m+1); } int main() { printf("The total count of stackout permutation is %d.", getPermuStack(6, 0)); return 0; }
一个长度为n的无重复序列入栈的所有出栈方式
——by hahabrother
这是一个很有趣的问题,例如1、2、3这三个数字,入栈并出栈共有5种方式,分别为:321、312、231、213、123。那么对于长度为n的无重复序列中所有的出栈方式有哪些呢?
为了设计计算的算法,我们可以用队列(queue)来模拟输入,队列的输出则按照原先序列的顺序。使用一个栈(stack)来模拟入栈和出栈,结果保存在另外一个队列(queue)中。
现在的问题来了,怎么样可以实现所有的出栈入栈操作。首先来看看出栈和入栈是怎么回事,对于123这个序列,1先入栈之后有两种选择,1出栈和2入栈,而若2已经入栈之后,在2出栈之前1则不能先行出栈,故对于1我们只需要考虑其在2入栈之前出栈的情况,若1在栈内时2入栈,则1与2只能看成一个整体。
这样就可以用递归的方式求解,伪代码如下:
dostack(输入队列,中间栈,输出队列)
if(输入队列为空)
if(中间栈为空)
输出输出队列中的结果
else
中间栈出栈,放入输出队列
dostack(输入队列,中间栈,输出队列)
else
if(中间栈非空)
新建输入队列2、中间栈2、输出队列2
中间栈2出栈并放入输出队列2
dostack(输入队列2,中间栈2,输出队列2)
输入队列出队一个数并压入中间栈
dostack(输入队列,中间栈,输出队列)
其基本思想为对于中间栈的每一个时刻拍照,都递归其后续的所有可能,由于在递归返回的时候还需要递归前的信息,所以每次递归都是新建数据结构而保存当前时刻的状态。若输入队列已经为空,则中间栈只有一种出栈方式,中间栈也为空时递归结束。
详细代码如下:
输入为序列的长度n,初始化序列为1,2,3…n,而输出则为所有可能的出栈数列。
#include <iostream> #include <stack> #include <queue> using namespace std; int n,i,j; int res; stack <int> s; queue <int> in,out; void clear(stack <int> &s) { while(!s.empty()) s.pop(); } void clear(queue <int> &s) { while(!s.empty()) s.pop(); } void print(queue <int> i) { while(!i.empty()) { cout<<i.front(); i.pop(); } cout<<endl; } void dostack(queue <int> in,stack <int> s,queue <int> out) { if(in.empty()) { if(s.empty()) { res++; print(out); } else { out.push(s.top()); s.pop(); dostack(in,s,out); } } else { if(!s.empty()) { stack <int> ts; queue <int> tin,tout; tin=in; ts=s; tout=out; tout.push(ts.top()); ts.pop(); dostack(tin,ts,tout); } s.push(in.front()); in.pop(); dostack(in,s,out); } } int _tmain(int argc, _TCHAR* argv[]) { while(cin>>n) { res=0; clear(in); clear(out); clear(s); for(i=n;i>=1;i--) in.push(i); dostack(in,s,out); cout<<res<<endl; } return 0; }