设集合 N 中的元素按次序1,2,3,...,n 入栈,其所有不同的出栈序列的集合为Sn,则|Sn|=。
1、结果证明:
定义1、 集合 N={1,2,3,...,n}中的元素按一定次序入栈,其每个出栈序列是 N 的一个元排列,若 N 的两个元排列不同,则称为两个不同的出栈序列(栈序列),记栈序列集为 Sn。
定义2、 n个0和n个1组成2n位0-1序列,若对任意i(i=1,2,3,...,2n),序列前i项中1的个数不少于0的个数,则称此序列为Catalan 0-1序列,记Catanlan 0-1序列集为Tn。
定义3、 集合 N={1,2,3,...,n}的一个n元排列,若对任意i,j(j=1,2,3,...,n,且j>i),如j排在i之前,要么j与i相邻,要么j与i之间所排的任一数均大于i,则称该排列为N的栈排列,记栈排列集为Pn。
引理 Tn=
证明:由于在2n位上填入n个1,不填1的其余n位自动填0的序列个数是,从中减去不符合要求的序列数即为所求Tn。不符合要求的序列是指:从左到右扫描,出现0的个数超过1的个数的序列。
不符合要求的序列在从左向右扫描时,必然在某一奇数2m+1位上首先出现m+1个0的累计数和m个1的累计数。此后的2(n-m)-1位上有n-m个1,n-m-1个0。如若把后面这部分2(n-m)-1位,0与1互换,使之成为n-m个0,n-m-1个1,那么便得到一个由n+1个0和n-1个1组成的2n位0-1序列。即一个不符合要求的序列对应于一个由n+1个0和n-1个1组成的一个排列。反之,任何一个由n+1个0和n-1个1组成的2n位0-1序列,由于0的个数多2个,2n是偶数,故在某一个奇数位上出现0的累计数超过1的累计数,同样在后面的部分,令0和1互换,使之成为一个由n个0和n个1组成的2n位0-1序列。也就是说,我们建立了不符合要求的序列与n+1个0和n-1个1组成的2n位0-1序列之间的一一对应关系。
而由n+1个0和n-1个1组成的2n位0-1序列共有
因此,Tn=-=。
定理1、集合 N={1,2,3,...,n}的n个元素按次序1,2,3,...,n入栈时,Sn=。
证明:1):Sn到Tn存在单射:设集合N={1,2,3,...,n}中的元素按一定次序1,2,3,...,n入栈,对Sn中的任一出栈序列,可以用Tn中唯一一个Catalan 0-1序列描述其出栈过程。按照“入栈记1,出栈记0”的原理顺序可得一个长为2n的Catanlan 0-1序列,且具有唯一性。具体方法为:对任意i(i=1,2,3,...,n),设i在某个出栈序列中排在第j个位置(从左起)上,且在出栈序列的前j项中最大数为m,则在2n为0-1序列的第j+m个位置(从左起)上记0,这样,可以在n个位置上记0,其余位置均记1。如:1,2,3,4,5顺次入栈,出栈序列21453对应的0-1序列为1100110100。
2):Sn到Tn存在满射。对Tn中每一个Catalan 0-1序列,从左到右,看成集合中的元素按1,2,3,...,n入栈时,入栈出栈的过程记录。按照“1看成入栈操作,0看成出栈操作”可唯一写出Sn中一个出栈序列,具体方法为:把0-1序列从左第一个1起上方写1,2,3,...,n;然后把序列的每个0(从左到右)与其左边最近的1配对,相应的1上方的数依次构成一个出栈序列。如:1100110100,其配对为:,因此,对应的唯一的出栈序列为2,1,3,4,5。故Sn到Tn存在一个双射。即:Tn=Sn=。
由上面的分析,可以写出出栈序列与Catalan 0-1序列相互转换的程序,以下是我用写的C++代码:
#include <iostream>
#include <iterator>
#include <stack>
#include <vector>
using namespace std;
vector<int> Map2Stack( vector<char>& list )... {...} {
int i, count=0, j=0;
vector<int> out(list.size()/2);
stack<int> s;
for( i=0; i<list.size(); ++i )
if( list[i]=='1' )
s.push( ++count );
else
out[j++]=s.top(), s.pop();
return out;
}
vector<char> Map2Catan( vector<int>& list )... {...} {
int i, Max=0;
vector<int> index(list.size()+1), Max_index(list.size()+1);
vector<char> catanlan(2*list.size(),'1');
for( i=0; i<list.size(); ++i )...{
index[list[i]]=i+1;//list[i]排在第i+1位
if( list[i]>Max )
Max=list[i];
Max_index[i+1]=Max;//前i+1位的最大数为Max
}
for( i=0; i<list.size(); ++i )
catanlan[list[i]+Max_index[list[i]]-1]='0';
return catanlan;
}
int main(int argc, char *argv[])... {...} {
int list[]=...{2,1,4,5,3} ;
vector<int> e(list,list+sizeof(list)/sizeof(list[0]));
vector<char> r1=Map2Catan( e );
copy( r1.begin(), r1.end(), ostream_iterator<char>(cout) );
cout<<endl;
vector<int> r2=Map2Stack( r1 );
copy( r2.begin(), r2.end(), ostream_iterator<int>(cout," ") );
cout<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}