朋友在刷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;
}