C 单链表 --“原地”合并两个单链表

问题:

将两个单链表原来的空间交叉合并,比如
单链表LA=(a1, a2,…,am)
单链表LB=(b1, b2, …, bn)
m与n不一定相等

合并后的单链表LC=(a1, b1, a2, b2, …,am, bm, bm+1, bm+2,…,bn) (m<n)
或者LC = (a1, b1, a2, b2, …,an, bn, an+1, an+2, …, am) (m>n)

思路

  • 首先需要两个指针p,q分别做遍历LA, LB使用
    在这里插入图片描述
  • 然后遍历依次将q结点链接在p结点之后
q->next = p->next;
p->next = q;

在这里插入图片描述

注意:
如果我们只是做上图这样的链接,那么就会产生一个问题,LB中q结点的后继结点无法再找到,因为q的后继我们已经修改为LA的p结点的后继,所以在操作前我们需要设置一个结点n先取到q的后继节点

n = q->next;

在这里插入图片描述

  • 然后将p和q分别在其所在的原链表中后移,达到遍历目的
p = q->next;
q = n;

在这里插入图片描述

  • 当LA比LB长度更长,由于LB遍历完成之后p结点依然是LA的结点,所以不需要做任何处理。当LA比LB短时,我们需要将LB剩余的结点链接至LA最后。通过分析,如下图:
  • 在这里插入图片描述
    按照我们之前的逻辑,最后p会指向NULL,显然不能把LB的后继结点链接上,所以我们还需要一个指针f来保留q移动到n前的位置(绿色的q结点),如果出现LB比LA长,只需要让p结点指向这个f结点
f = q;

在这里插入图片描述

	if(q)    // 若LA遍历完后LB还有后继结点,将后继的第一个结点链接在f后,因为此时f保存的就是已经完成合并后的最后一个结点 
	{
		f->next = q;
	}
	

整体实现代码

#include<stdio.h>
#include<malloc.h>
// ** 兔子骑士叫旺仔原创 **

// 单链表的结点结构体,并重命名为Node,对应指针命名为LinkList 
typedef struct Node{
	int data;
	struct Node *next;
}Node, *LinkList;

// 尾插法建立单链表 
LinkList RearInsertCreat()
{
	LinkList L;
	Node *p, *rear;
	int x;
	
	L = (LinkList)malloc(sizeof(LinkList));
	L -> next = NULL;

	rear = L;

	scanf("%d", &x);
	while(x != -1)
	{
		p = (Node *)malloc(sizeof(Node));
		p->data = x;
		p->next = rear->next;
		rear->next = p;	
		//rear指针后移,保证始终指向最后一个结点 
		rear = p;
		scanf("%d", &x);
	}
	rear->next=NULL;
	return L; 
 } 
// 在原空间交叉合并两个单链表 
LinkList MergeUp(LinkList LA, LinkList LB)
{
	Node *p, *q, *n, *f;	// p指针遍历链表LA,q指针遍历链表LB,n指针指向链表LB中q的下一个结点, f指针指向q指针指向的结点 
	p = LA->next;
	q = LB->next;
	n = NULL;
	f = NULL;
	while(p && q)    //当p和q指针都不为空时 ,将LB中q指针指向的结点连接在LA中p指针指向的结点后,然后将此时的p结点更新至q的后继(LA中p的下一个结点) 
	{
		//if(p->data <= q->data)
		//{
			n = q->next;
			q->next = p->next;
			p->next = q;
			p = q->next;
			f = q;
			q = n;
		//}
	}
	if(q)    // 若LA遍历完后LB还有后继结点,将后继的第一个结点链接在f后,因为此时f保存的就是已经完成合并后的最后一个结点 
	{
		f->next = q;
	}
	
	return LA;
}

void ViewList(LinkList L, Node *p)
 {
 	p = L->next;
	while(p)
	{
		printf("--%d",p->data);
		p = p->next;
	}
 }
 
main()
{
	LinkList LA, LB, LC;
	Node *p;
	LA = (LinkList)malloc(sizeof(LinkList));
	LB = (LinkList)malloc(sizeof(LinkList));
	LA = RearInsertCreat();
	LB = RearInsertCreat(); 
	LC = MergeUp(LA,LB);
	p = LC->next;
	ViewList(LC, p);
}

综上,问题解答完毕。

不过我们可以进一步实现有序单链表在原空间合并后仍为有序单链表,大家可以多多交流学习,一起进步。加油!

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值