pta 7-3 两个有序链表序列的合并 (20 分)

本文深入探讨了两个非降序链表的合并问题,通过对比不同的实现方式,详细讲解了使用空头结点简化链表合并过程的方法,以及从错误代码中汲取的经验教训。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。

输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。

输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。

输入样例:
1 3 5 -1
2 4 6 8 10 -1
输出样例:
1 2 3 4 5 6 8 10

第一次链表的实现。之前看链表,啥空表头的链表,双向,循环链表,感觉会,然后实现才发现,有点难呀。
第一次写的错误代码,超时了。

#include<stdio.h>
#include<stdlib.h>
struct Node
{
	int dat;
	struct Node *pre;
	struct Node *next;
};
typedef struct Node node;
node *headl;
node *make_new_node(node *head,int data)
{
	node *p,*tep=head;
	p=(node*)malloc(sizeof(node));
	if(p==NULL)
	{
		exit(0);
	}
	if(head==NULL)//first node
	{
		head=p;
		head->dat=data; 
		head->pre=NULL;
		head->next=NULL;
	}
	else
	{
		tep=head;
		while(tep->next!=NULL)
		{
			tep=tep->next;
		}**这里可以优化**
		tep->next=p;
		p->dat=data;
		p->pre=tep;
		p->next=NULL;
	}
	return head;
}
int get_merge(node *head1,node *head2)
{
	node *pos1,*pos2;
	//here,we put head1 as a new node's first head;
	if(head1==NULL&&head2==NULL)
	{
		return 0;//输出null;
	}
		if(head1==NULL||head2==NULL)
	{
		return 1;//只需输出一个链表的值
	}
	int t1=head1->dat,t2=head2->dat;
	**下面判断这么复杂,就是因为最后一个节点的null,无法有效的解决**
	if(t1>t2)
	{
		headl=head2;
		while(1)
		{
			t1=head1->dat,t2=head2->dat;
			if(t1>t2)
			{
				if(head2->next==NULL)
				{
					head2->next=head1;
					break;
				}
				else
					head2=head2->next;
			}
			else if(t1<t2)
			{
				pos2=head1->next;
				head2->pre->next=head1;
				head1->next=head2;
				head1=pos2;
			}
			else 
			{
				pos1=head1->next;
				pos2=head2->next;
				head1->next=head2;
				head2->next=pos1;
				head2=pos2;
				if(head1==NULL) break;
			}
		}
	}
	else
	{
		headl=head1;
		while(1)
		{
			t1=head1->dat,t2=head2->dat;
			if(t2>t1)
			{
				if(head1->next==NULL)
				{
					head1->next=head2;
					break;
				}
				else
					head1=head1->next;
			}
			else if(t2<t1)
			{
				pos2=head2->next;
				head1->pre->next=head2;
				head2->next=head1;
				head2=pos2;
			}
			else 
			{
				pos1=head1->next;
				pos2=head2->next;
				head1->next=head2;
				head2->next=pos1;
				head2=pos2;
				if(head2==NULL) break;
			}
		}
	}
	return 2;
}
void dis_link(node *head)
{
	
	node *p=head,*pr;
	while(p->next!=NULL)
	{
		printf("%d ",p->dat);
		p=p->next;
	}
	printf("%d\n",p->dat);
}
void free_node(node *head)
{
	node *p;
	node *pr=head;
	while(pr->next!=NULL)
	{
		p=pr->next;
		free(pr);
		pr=p;
	}
	free(pr);
}
int main(void)
{
	node *head1=NULL,*head2=NULL;
	int data;
	while(scanf("%d",&data)&&data!=-1)
	{
		head1=make_new_node(head1,data);
	}
	while(scanf("%d",&data)&&data!=-1)
	{
		head2=make_new_node(head2,data);
	}
	int flag=get_merge(head1,head2);
	if(flag==1)
	{
		if(head1==NULL)
		{
			dis_link(head2);
			free_node(head2);
		}
		else 
		{
			dis_link(head1);
			free_node(head1);
		}
	}
	else if(flag==0)
	{
		printf("NULL\n");
	}
	else
	{
		dis_link(headl);
		free_node(headl);
	}
	return 0;
}

带了空头结点简单多了

#include<stdio.h>
#include<stdlib.h>
struct Node
{
	int dat;
	struct Node *next;
};
typedef struct Node node;
node *headp;
node *make_new_node(node *head)
{
**这里改为只建立一个空头结点**
	node *p;
	p=(node*)malloc(sizeof(node));
	head=p;
	p->next=NULL;
	return head;
}
int get_merge(node *head1,node *head2)
{
	node *pos1,*pos2,*headl;
	if(head1->next==NULL&&head2->next==NULL)
	{
		return 0;//输出null;
	}
	if(head1->next==NULL||head2->next==NULL)
	{
		return 1;//只需输出一个链表的值
	}
	pos1=(node*)malloc(sizeof(node));
	headl=pos1;
	headp=headl;
	**开始以为空头结点不需要开空间**
	head1=head1->next;
	head2=head2->next;
	**这里的空头结点很有用。**
	while(head1&&head2)
	{
		if(head1->dat<head2->dat)
		{
			headl->next=head1;
			head1=head1->next;
		}
		else
		{
			headl->next=head2;
			head2=head2->next;
		}
		headl=headl->next;
	}
	if(!head1&&!head2) return 2;
	if(head1!=NULL)
	{
		headl->next=head1;
	}
	if(head2!=NULL)
	{
		headl->next=head2;
	}
	return 2;
}
void dis_link(node *head)
{

	node *p=head->next,*pr;
	while(p->next!=NULL)
	{
		printf("%d ",p->dat);
		p=p->next;
	}
	printf("%d\n",p->dat);
}
void free_node(node *head)
{
	node *p;
	node *pr=head;
	while(pr->next!=NULL)
	{
		p=pr->next;
		free(pr);
		pr=p;
	}
	free(pr);
}
int main(void)
{
	node *head1=NULL,*head2=NULL;
	head1=make_new_node(head1);
	head2=make_new_node(head2);
	int data;
	node *ll=head1;
	while(scanf("%d",&data),data!=-1)
	{
		node *tep;
		tep=(node*)malloc(sizeof(node));
		ll->next=tep;
		tep->next=NULL;
		tep->dat=data;
		ll=tep;**这里就是上面的优化,不需要移动头结点去添加新的节点了**
	}
	ll=head2;
	while(scanf("%d",&data),data!=-1)
	{
		node *tep;
		tep=(node*)malloc(sizeof(node));
		ll->next=tep;
		tep->next=NULL;
		tep->dat=data;
		ll=tep;
	}
	int flag=get_merge(head1,head2);
	if(flag==1)
	{
		if(head1==NULL)
		{
			dis_link(head2);
			free_node(head2);
		}
		else
		{
			dis_link(head1);
			free_node(head1);
		}
	}
	else if(flag==0)
	{
		printf("NULL\n");
		free_node(head1);
		free_node(head2);
	}
	else
	{
		dis_link(headp);
		free_node(headp);
	}
	return 0;
}

收获:讲得好不如做得好,代码自己实现起来,能够加深印象。
链表不同于数组,如果此题用数组,开三个。而链表开两个链表,然后在开一个控表头,把其他的数据块链接到空表头后面即可。不需要再开空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值