一个长度为n的无重复序列入栈的所有出栈方式
例如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,而输出则为所有可能的出栈数列。
-
//输入压栈顺序如1 2 3 4 5 6 7 8 ..n,确定所有可能出栈的得到的结果 -
//同时计算情况的总数n -
#include <stdio.h> -
#include <iostream> -
#include <stack> -
#include <queue> -
using namespace std; -
//递归法只计算所有情况总数 -
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); -
} -
//Catalan公式法 最多只能算到n=10 -
long long jiecheng(long long n) -
{ -
if(n==1) return 1; -
else return n*jiecheng(n-1); -
} -
long long catalan(long long n) -
{ -
return (jiecheng(2*n)/jiecheng(n+1)/jiecheng(n)); -
} -
//下面算法函数既输出所有可能压栈(不全压,但仍按给定顺序压栈)的情况,也输出对应的出栈情况及总数 -
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 main() -
{ -
cout<<"请输入1~n共n个数:"; -
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; -
} -
cout<<"1~n依次进栈时,使用递归函数所有的情况总数:"<<endl; -
for(i=1;i<15;i++) -
cout<<"n="<<i<<" "<<getPermuStack(i,0)<<endl; -
cout<<endl<<"1~n依次进栈时,使用Catalan公式所有的情况总数:"<<endl; -
for(i=1;i<15;i++) -
cout<<"n="<<i<<" "<<catalan(i)<<endl; -
return 0; -
}
本文探讨了长度为n的无重复序列的入栈出栈问题,通过队列和栈模拟操作,提出使用递归算法求解所有可能的出栈序列。对于给定的序列,例如123,有5种出栈方式,分别是321、312、231、213、123。详细代码展示了如何实现这一算法。

1万+

被折叠的 条评论
为什么被折叠?



