词典序法生成出栈序列
本文用词典序产生1,2,...,n的所有出栈序列,本质上,给出的算法也生成了n节点的所有树.
关于出栈序列与 catalan 0-1序列的关系,在我blog中的“出栈序列与catalan 0-1序列”一文中,已经阐述地很清楚了,由那里的知识,我们知道:生成出栈序列,就是生成catalan 0-1序列。我们规定:在词典序下,0的序数大于1的序数。那么,最大的catalan 0-1序列的形式为 0n1n;最小的catalan 0-1序列的形式为0101...01。于是,按词典序法,我们只要将序列s尾部的10p1q 替换成01q-p+201p-1就可以得到s在词典序下的下一个序列。算法思路大致如上所述。算法的C++实现如下:
void Generate_Catalan_01_Sequence( int n ){
int *List=new int[2*n], p=1, q=1, i, j;
for( i=0; i<2*n; ++i ) List[i]=i&1;
while( 1 ){
copy( List, List+2*n, ostream_iterator<int>(cout," ") ),cout<<endl;
if( p==n && q==n ) return;
for( i=1; i<=2*(p-1); ++i ) List[2*n-i]=i&1;
for( j=0; j<q-p+2; ++j ) List[2*n-i-j]=1;
List[2*n-i-j]=0;
p=q=0;
while( List[2*n-1-q]==1 ) ++q;
while( List[2*n-1-q-p]==0 ) ++p;
}
delete []List;
}
int *List=new int[2*n], p=1, q=1, i, j;
for( i=0; i<2*n; ++i ) List[i]=i&1;
while( 1 ){
copy( List, List+2*n, ostream_iterator<int>(cout," ") ),cout<<endl;
if( p==n && q==n ) return;
for( i=1; i<=2*(p-1); ++i ) List[2*n-i]=i&1;
for( j=0; j<q-p+2; ++j ) List[2*n-i-j]=1;
List[2*n-i-j]=0;
p=q=0;
while( List[2*n-1-q]==1 ) ++q;
while( List[2*n-1-q-p]==0 ) ++p;
}
delete []List;
}
上面是生成catalan 0-1序列的算法,将catalan 0-1序列转化为出栈序列的算法在“出栈序列与catalan 0-1序列”一文中已经给出,利用转化算法,可以将上面的catalan 01 序列生成算法改写为生成出栈序列的算法。C++代码列出如下:
void Generate_Out_Stack_Sequence( int n ){
int *List=new int[2*n], p=1, q=1, i, j, count;
stack<int> s;
for( i=0; i<2*n; ++i ) List[i]=i&1;
while( 1 ){
for( count=i=0; i<2*n; ++i )
if( List[i] ) cout<<s.top()<<" ", s.pop();
else s.push(++count);
cout<<endl;
if( p==n ) return;
for( i=1; i<=2*(p-1); ++i ) List[2*n-i]=i&1;
for( j=0; j<q-p+2; ++j ) List[2*n-i-j]=1;
List[2*n-i-j]=0;
p=q=0;
while( List[2*n-1-q]==1 ) ++q;
while( List[2*n-1-q-p]==0 ) ++p;
}
delete []List;
}
int *List=new int[2*n], p=1, q=1, i, j, count;
stack<int> s;
for( i=0; i<2*n; ++i ) List[i]=i&1;
while( 1 ){
for( count=i=0; i<2*n; ++i )
if( List[i] ) cout<<s.top()<<" ", s.pop();
else s.push(++count);
cout<<endl;
if( p==n ) return;
for( i=1; i<=2*(p-1); ++i ) List[2*n-i]=i&1;
for( j=0; j<q-p+2; ++j ) List[2*n-i-j]=1;
List[2*n-i-j]=0;
p=q=0;
while( List[2*n-1-q]==1 ) ++q;
while( List[2*n-1-q-p]==0 ) ++p;
}
delete []List;
}