出栈序列问题

题目:栈排序。对于给定的进栈序列(如1,2,3),输出所有可能的出栈序列。

1: 关于出栈序列种数:

符合卡特兰数递归式。设f(n)是序列元素个数为n的出栈序列种数,假定最后出栈的元素为k,k取不同值时相互独立。k将1-n的序列额分为两个序列(1~k-1,k+1~n),由于k最后出栈,在k入栈之前,前k-1个元素全部出栈,有f(k-1)种情况,k之后入栈的元素都在k之前出栈,有f(n-k)种情况。由于两个序列入栈出栈情况相互独立,根据乘法原理,共有f(k-1)*f(n-k)种情况; 而k取值为[1,n],根据加法原理将k取不同值的序列种数相加得到总序列种数f(n)=f(0)*f(n-1)+f(1)f(n-2)+...+f(n-1)f(0),即卡特兰数递归式,其中f(0)=f(1)=1。

2.输出所有出栈序列:

入栈序列为123时,出栈序列可用如下二叉树表示:

出栈序列问题_第1张图片

每一个结点只有两种可能,栈顶元素出栈或下一个元素入栈,据此设计递归条件。

instr用来记录入栈序列,outstr记录每一种出栈序列,栈s模拟进出栈的情况,pos记录入栈元素个数,注意回退时要使恢复栈原来状态。
#include
#include
#include
using namespace std;

void in_out_stack(string instr, int pos, stacks, string outstr)
{
	if (outstr.size() == instr.size())        //判断是否出栈完毕
	{
		cout << outstr << endl;    
		return;
	}
	if (pos < instr.size())                    //判断是否入栈完毕,进行入栈
	{
		s.push(instr[pos]);                
		in_out_stack(instr, pos + 1, s,outstr);
		s.pop();    //恢复
	}
	if (s.size() > 0)                           //判断栈中是否为空,进行出栈
	{
		char out = s.top();   
		outstr.append(1, out);
		s.pop();
		in_out_stack(instr, pos, s, outstr);
		s.push(out);    //恢复
	}
}
int main()
{
	stack s;
	string instr, outstr;
	while (cin >> instr,instr[0] != '#')
	{
		cout << "出栈序列有:" << endl;
		in_out_stack(instr, 0, s, outstr);
		cout << "---------" << endl;
	}
	return 0;
}

你可能感兴趣的:(算法)