算法学习日记 火车站出站问题序排列算法。

算法学习日记  火车站出站问题

问题:给定指定的火车入站序列,给出所有可能的出站序列(以字典序排序)

思路:先将所有的入站序列进行全排列,再每个序列进行检查,看其是否符合出栈序列的要求。

(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;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值