合并两个有序的单链表,合并后依然有序

分析过程:

 首先我要合并有序的链表,合并后依然有序。我就要有两个指针,分别指向两个链表,观察所给的两个链表是升序还是降序的来确定合并后的链表是否有序。(这里默认的认为链表时升序的)
 用指针分别指向两个链表的第一个节点,比较大小,那个大,将元素尾插进入我所要返回的新链表中去。一次比较循环往复,直至某一个链表为空为止。但有可能会出现一个链表为空,另一个链表不为空。我们就要在最后检测,将不为空链表的全部挂在我要返回元素的后面。因为要不停的给新链表尾插。所以我用一个指针,将新链表的尾部标记。

代码如下所示
//合并两个有序链表,合并后依然有序的测试
SLinkList* MergeLinkList(SLinkList* pHead1, SLinkList* pHead2)
{
	SLinkList* New = NULL;//合并后的链表
	SLinkList* tail = NULL;//标记合并后链表的尾部,方便尾插
	SLinkList* cur1 = pHead1;
	SLinkList* cur2 = pHead2;
	SLinkList* nxt = NULL;//用来保存链表的后续节点

	while (cur1 != NULL && cur2 != NULL)
	{
		if (cur1->_data <= cur2->_data)
		{
			nxt = cur1->_pNext;//保存cur1后面的节点
			//应取链表1的结点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
			if (New == NULL)
			{	//合并的链表为空
				New = cur1;//将cur1指向的结点挂在新链表上
			}
			else
			{	//合并链表不为空
				tail->_pNext = cur1;
			}
			cur1->_pNext = NULL;//尾插,链表的最后一个元素应为空
			//保存新链表的最后一个节点
			tail = cur1;
			cur1 = nxt;
		}
		else
		{
			nxt = cur2->_pNext;//保存cur1后面的节点
			//应取链表1的结点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
			if (New == NULL)
			{	//合并的链表为空
				New = cur2;//将cur1指向的结点挂在新链表上
			}
			else
			{	//合并链表不为空
				tail->_pNext = cur2;
			}
			cur2->_pNext = NULL;//尾插,链表的最后一个元素应为空
			//保存新链表的最后一个节点
			tail = cur2;
			cur2 = nxt;
		}
	}
	//一个链表空了,但要判断里另一个链表为不为空
	if (cur1 == NULL)
	{
		tail->_pNext = cur2;
	}
	if (cur2 == NULL)
	{
		tail->_pNext = cur1;
	}
	return New;
}

由于这个代码有许多重复的步骤,优化可得

SLinkList* MergeLinkListOP(SLinkList* pHead1, SLinkList* pHead2)
{
	SLinkList* New = NULL;//合并后的链表
	SLinkList* tail = NULL;//标记合并后链表的尾部,方便尾插
	SLinkList* cur1 = pHead1;
	SLinkList* cur2 = pHead2;
	SLinkList* nxt = NULL;//用来保存链表的后续节点
	SLinkList* node = NULL;
	while (cur1 != NULL && cur2 != NULL)
	{
		if (cur1->_data <= cur2->_data)
		{
			node = cur1;//应取链表1的结点
		}
		else
		{
			node = cur2;
		}
		//保存cur1后面的节点:将cur1指向的结点从链表1上取下来,挂在新链表上,后序的链表应该保存下来,否则程序会奔溃
		nxt = node->_pNext;
		if (New == NULL)
		{	//合并的链表为空
			New = node;//将cur1指向的结点挂在新链表上
		}
		else
		{	//合并链表不为空
			tail->_pNext = node;
		}
		node->_pNext = NULL;//尾插,链表的最后一个元素应为空
		//保存新链表的最后一个节点
		tail = node;
		//已经将节点挂在新链表上,循环应该让cur1 和 cur2如改变,因此在这里应该让cur前进
		if (node == cur1)
		{
			cur1 = nxt;
		}
		else
		{
			cur2 = nxt;
		}
	}	
	//一个链表空了,但要判断里另一个链表为不为空
	if (cur1 == NULL)
		tail->_pNext = cur2;
	if (cur2 == NULL)
		tail->_pNext = cur1;

	return New;
}
链表结构、测试代码、运行结果
typedef int DataType;

typedef struct ListNode
{
	DataType _data;					//当前节点中所保存的元素
	struct ListNode* _pNext;	//指向链表中下一个结点

}SLinkList, SListNode;
void Test_MergeLinkList()
{
	SLinkList* pHead1 = NULL;
	SLinkList* pHead2 = NULL;

	PushBack(&pHead1, 2);
	PushBack(&pHead1, 4);
	PushBack(&pHead1, 5);
	PushBack(&pHead1, 7);

	PushBack(&pHead2, 1);
	PushBack(&pHead2, 3);
	PushBack(&pHead2, 5);
	PushBack(&pHead2, 6);

	printf("链表1:");
	PrintSLinkList(pHead1);
	printf("链表2:");
	PrintSLinkList(pHead2);

	SLinkList* pHead3 = MergeLinkList(pHead1, pHead2);
	printf("新链表:");
	PrintSLinkList(pHead3);
	
	SLinkList* pHead3OP = MergeLinkListOP(pHead1, pHead2);
	printf("优化后的新链表:");
	PrintSLinkList(pHead3);
}

这里写图片描述

要创建两个有序单链表并将它们合并成一个有序单链表,我们可以按照以下步骤进行: 1. 定义单链表的节点结构。通常,节点包含数据域和指向下一个节点的指针。 2. 创建两个有序单链表有序意味着链表中的节点按照一定的顺序排列,例如升序或降序。 3. 实现合并函数,该函数将遍历两个单链表的节点,并按照有序的规则(比如升序)逐个选择较小的节点链接到新链表上,直到两个链表中的节点都被合并完毕。 以下是合并两个有序单链表的伪代码示例: ``` class ListNode: def __init__(self, value=0, next=None): self.value = value self.next = next def mergeTwoLists(l1, l2): # 创建一个哑节点作为合并后链表的起始节点 dummy = ListNode() # tail用于指向合并链表的最后一个节点 tail = dummy while l1 and l2: if l1.value < l2.value: tail.next = l1 l1 = l1.next else: tail.next = l2 l2 = l2.next # 更新tail为合并链表的最后一个节点 tail = tail.next # 如果l1还有剩余节点,将其接到合并链表的末尾 if l1: tail.next = l1 # 如果l2还有剩余节点,将其接到合并链表的末尾 elif l2: tail.next = l2 return dummy.next ``` 在上述代码中,`ListNode`类定义了链表节点,`mergeTwoLists`函数接收两个有序链表的头节点`l1`和`l2`,然后通过比较节点的值来决定哪个节点应该被添加到新链表中。`dummy`节点是为了简化代码逻辑而引入的一个辅助节点,它的`next`指针最终指向合并后链表的第一个节点。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值