算法学习日记 火车站出站问题
问题:给定指定的火车入站序列,给出所有可能的出站序列(以字典序排序)
思路:先将所有的入站序列进行全排列,再每个序列进行检查,看其是否符合出栈序列的要求。
(1)全排列算法
见“字典序全排列算法”
(2)判断是否为出栈序列(出栈序列合法性的判断)
这里采用的是最笨的办法。给定入站序列in,检查指定的序列out是否为合法的出站序列。方法是,首先判断当前的栈头是不是与出站序列第一个相同,不是的话将当前入站序列的数压入栈中。当出现相同的,出栈,然后检查现在的栈头是不是与出栈序列的下一个相符,如果相同,再出栈,在检查。如果不相同,再将当前入栈序列的数压入栈中。一直到进栈序列压完。判断此时栈是否为空,如果为空,说明出栈序列合法。否则不合法。
代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct stackrecord;
typedef struct stackrecord* stack;
struct stackrecord
{
int Capacity;
int toppoint;
int *array;
};
/***********定义栈ADT*********************/
void Makeempty(stack s)
{
s->toppoint=-1;
}
int Isempty(stack s)
{
return s->toppoint==-1;
}
int Isfull(stack s)
{
return s->toppoint==s->Capacity-1;
}
stack Create_stack(int max_storage)
{
stack s;
s=malloc(sizeof(struct stackrecord));
s->array=malloc(max_storage * sizeof(int));
s->Capacity=max_storage;
Makeempty(s);
return s;
}
void push(stack s,int element)
{
if(Isfull(s))
{
// Error("Full stack!");
}
else
{
s->toppoint++;
s->array[s->toppoint]=element;
}
}
void pop(stack s)
{
if(Isempty(s))
{
// Error("stack is empty!");
}
else
{
s->toppoint--;
}
}
int Top(stack s)
{
if(Isempty(s))
{
// Error("stack is empty");
return 0;
}
else
{
return s->array[s->toppoint];
}
}
/*****************检验出栈序列是否合法*********************/
int Check_correct(int* out,int* in,int in_maxsize)
{
int i=0,j=0;
stack s;
s=Create_stack(in_maxsize);
while(i<in_maxsize)
{
if(Isempty(s))
push(s,in[i++]);
if(Top(s)!=out[j])
{
push(s,in[i++]);
}
else
{
pop(s);
j++;
}
}
while(!Isempty(s))
{
if(s->array[s->toppoint]!=out[j++])
{
return 0;
}
pop(s);
}
return 1;
}
/*****************全排列用到的函数******************/
void invert_array(int *begin,int *end)
{
int temp;
while(begin<end)
{
temp=*begin;
*begin=*end;
*end=temp;
++begin;
--end;
}
}
void print(int *a,int array_number)
{
int i;
for(i=0;i<array_number;i++)
{
if(i==array_number-1)
printf("%d",a[i]);
else
printf("%d ",a[i]);
}
printf("\n");
}
int main(void)
{
int *list=NULL,*list_1=NULL;
int min=0,point=0;
int temp=0;
int flag=0;
int *begin=NULL;
int *end=NULL;
int i=0,j=0;
int N=0;
scanf("%d",&N);
list=malloc(N * sizeof(int));
list_1=malloc(N * sizeof(int));
for(i=0;i<N;i++)
{
scanf("%d",&list[i]);
}
end=list+N-1;
for(i=0;i<N;i++)
{
list_1[i]=list[i];
}
print(list_1,N);
while(1)
{
i=N-2;
while(i>=0&&list[i]>list[i+1])
i--;
if(i<0) break;
point=i;
begin=&list[i+1];
min=1000;
for(j=i;j<N;j++)
{
if((list[j]>list[i])&&(list[j]<min))
{
min=list[j];
point=j;
}
}
temp=list[i];
list[i]=list[point];
list[point]=temp;
invert_array(begin,end);
flag=Check_correct(list,list_1,N);
if(flag==1)
print(list,N);
}
return 0;
}