用链表和大小可变的指针数组实现多个栈的建立与操作

朋友在刷PTA遇到了这样一道有意思的题:
在这里插入图片描述
实现起来不难,但是总是提示时间超限或内存超限。
这里给出输出入和输出示例:
输入

2
2 15
1 1 10
1 1 11
1 2 12
1 2 13
3 1 2
1 2 14
2 1
2 1
2 1
2 1
2 1
3 2 1
2 2
2 2
2 2
3 7
3 1 2
3 1 3
3 2 1
2 1
2 2
2 3
2 3

输出:

13
12
11
10
EMPTY
14
EMPTY
EMPTY
EMPTY
EMPTY
EMPTY
EMPTY

简单的用二维数组开辟好空间显然是行不通的,因而选择使用链表:

typedef struct stack
{
    int n;
    struct stack* next;
}*sta,stack;

首先我们实现第一个操作将数据存入链表:

void opera1(sta head,int n)
{
    sta p=(sta)malloc(sizeof(stack));
    p->next=head->next;
    head->next=p;
    p->n=n;
    //printf("%d",p->n);
}

这里直接采用了头插法。这样我们可以方便对栈顶进行操作。我们在实现第二种操作时就是利用这种特性:

void opera2(sta head)
{
    sta p;
    if(head->next==NULL)
        printf("EMPTY\n");
    else
    {
        p=head->next;
        printf("%d\n",p->n);
        head->next=p->next;
        free(p);
    }
}

接下来是方法3也是简单的拼接操作,可以直接把链表拼接到头部降低时间复杂度:

void opera3(sta head1,sta head2)
{
    sta p=head1;
    int i=0;
    while(p->next!=NULL)
    {
        p=p->next;
        i++;
    }
    if(i!=0)
    {
        p->next=head2->next;
        head2->next=head1->next;
        head1->next=NULL;
    }
}

为了降低其对空间的占用且符合规范,由于存在多组输入我们要及时释放内存:

void destroy(sta head)
{
    sta p=head;
    sta q;
    while(p!=NULL)
    {
        q=p->next;
        free(p);
        p=q;
    }
}

为了进一步节约空间我们需要将指针数组的大小也可变,也就是创建一个指针的指针来作为数组的首地址:

sta* head=NULL;

接下来只要根据需要分配空间就可以了:

head=(sta*)malloc(sizeof(sta)*n);

n为我们需要的头结点数量。
main函数里通过switch语言调用各个方法,同时为了避免空间浪费我们只在对应标号的栈被用到时创建头结点。
接下来我们直接给出整个main函数的代码:

int main()
{
    int t,i;
    scanf("%d",&t);
    for(i=0;i<t;i++)
    {
        int n,q,s,v,h1,h2;
        int j,k;
        int op;
        sta* head=NULL;
        scanf("%d %d",&n,&q);
        head=(sta*)malloc(sizeof(sta)*n);
        for(j=0;j<n;j++)
            head[j]=NULL;
        for(k=0;k<q;k++)
        {
            scanf("%d",&op);
            switch(op)
            {
            case 1:
                scanf("%d %d",&s,&v);
                s--;
                if(head[s]==NULL)
                {
                    head[s]=(sta)malloc(sizeof(sta));
                    head[s]->next=NULL;
                }
                opera1(head[s],v);
                break;
            case 2:
                scanf("%d",&s);
                s--;
                if(head[s]==NULL)
                {
                    head[s]=(sta)malloc(sizeof(sta));
                    head[s]->next=NULL;
                }
                //printf("%d",head[s]->next->n);
                opera2(head[s]);
                break;
            case 3:
                scanf("%d %d",&h1,&h2);
                h1--;
                h2--;
                if(head[h1]==NULL)
                {
                    head[h1]=(sta)malloc(sizeof(sta));
                    head[h1]->next=NULL;
                }
                if(head[h2]==NULL)
                {
                    head[h2]=(sta)malloc(sizeof(sta));
                    head[h2]->next=NULL;
                }

                opera3(head[h2],head[h1]);
            }
        }
        for(k=0;k<n;k++)
        {
            if(head[k]!=NULL)
                destroy(head[k]);
        }
    }
    return 0;
}

接下来我们给出整体代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct stack
{
    int n;
    struct stack* next;
}*sta,stack;

void opera1(sta head,int n)
{
    sta p=(sta)malloc(sizeof(stack));
    p->next=head->next;
    head->next=p;
    p->n=n;
    //printf("%d",p->n);
}

void opera2(sta head)
{
    sta p;
    if(head->next==NULL)
        printf("EMPTY\n");
    else
    {
        p=head->next;
        printf("%d\n",p->n);
        head->next=p->next;
        free(p);
    }
}

void opera3(sta head1,sta head2)
{
    sta p=head1;
    int i=0;
    while(p->next!=NULL)
    {
        p=p->next;
        i++;
    }
    if(i!=0)
    {
        p->next=head2->next;
        head2->next=head1->next;
        head1->next=NULL;
    }
}
void destroy(sta head)
{
    sta p=head;
    sta q;
    while(p!=NULL)
    {
        q=p->next;
        free(p);
        p=q;
    }
}
int main()
{
    int t,i;
    scanf("%d",&t);
    for(i=0;i<t;i++)
    {
        int n,q,s,v,h1,h2;
        int j,k;
        int op;
        sta* head=NULL;
        scanf("%d %d",&n,&q);
        head=(sta*)malloc(sizeof(sta)*n);
        for(j=0;j<n;j++)
            head[j]=NULL;
        for(k=0;k<q;k++)
        {
            scanf("%d",&op);
            switch(op)
            {
            case 1:
                scanf("%d %d",&s,&v);
                s--;
                if(head[s]==NULL)
                {
                    head[s]=(sta)malloc(sizeof(sta));
                    head[s]->next=NULL;
                }
                opera1(head[s],v);
                break;
            case 2:
                scanf("%d",&s);
                s--;
                if(head[s]==NULL)
                {
                    head[s]=(sta)malloc(sizeof(sta));
                    head[s]->next=NULL;
                }
                //printf("%d",head[s]->next->n);
                opera2(head[s]);
                break;
            case 3:
                scanf("%d %d",&h1,&h2);
                h1--;
                h2--;
                if(head[h1]==NULL)
                {
                    head[h1]=(sta)malloc(sizeof(sta));
                    head[h1]->next=NULL;
                }
                if(head[h2]==NULL)
                {
                    head[h2]=(sta)malloc(sizeof(sta));
                    head[h2]->next=NULL;
                }

                opera3(head[h2],head[h1]);
            }
        }
        for(k=0;k<n;k++)
        {
            if(head[k]!=NULL)
                destroy(head[k]);
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章