合并两个有序链表是c语言数据结构中比较经典的问题,首先两个链表都是有序的,即节点的顺序是按照各个节点中的值从小到大排序,而且合并之后的新链表中的各个节点顺序也要满足从小到大的排序,具体如下图所示。
思路:用malloc申请一个哨兵位的头节点NewHead,作为合并之后新链表的头节点(注意此头节点的作用是作为一个哨兵,最后用完要将其释放)。再定义三个指针,指针1用来遍历链表1中的节点,指针2遍历链表2中的节点,指针3则用来维护合并之后的新链表。将指针1指向的节点与指针2指向的节点进行值的比较,小的一方则把节点“给到”NewHead节点的下一个节点,并且移动指针3往后走,继续维护下一个节点。
若List1和List2中有一个指针已经遍历到空,则直接将另一条链表剩余节点都连接到tail指向的节点后面,也就是将没有指向空的指针给到了tail维护的节点的next。
最后合并链表的任务完成后,对newhead哨兵位的头节点进行释放,并且要记住newhead节点的下一个节点的位置,因为该位置才是合并后链表的真正意义上的头节点的地址。
测试代码实现如下(代码包括创建链表、打印链表、测试合并链表的功能):
#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode //创建节点结构体
{
int data;
struct ListNode* next;
}LNode;
void Print(LNode* phead)//打印函数
{
LNode* cur = phead;
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL");//模拟链表最后指向的是NULL
}
LNode* mergeTwoLists(LNode* list1, LNode* list2) {
LNode* head = NULL;//记住合并后链表的头节点
LNode* tail = NULL;//用于遍历合并后的链表
head = tail = (LNode*)malloc(sizeof(LNode));//创建一个头节点newhead
while (list1 && list2)//若有一个指针为空,则跳出循环
{
if (list1->data > list2->data)//数据小的节点给到tail
{
tail->next = list2;
list2 = list2->next;
}
else
{
tail->next = list1;
list1 = list1->next;
}
tail = tail->next;//更新tail的位置,以便下一次节点的插入
}
if (list1)//若list1指针不为空则说明list2指针为空,则直接将list1指向的节点给到tail
{
tail->next = list1;
}
else//反之,若list2指针不为空则说明list1指针为空,则直接将list2指向的节点给到tail
{
tail->next = list2;
}
LNode* poi = head;//记住头节点的位置,因为准备释放申请的头节点的空间,
//因为最终返回是不带哨兵位节点的链表
head = head->next;//head指向哨兵位节点的下一个节点,该节点才是合并链表后真正的头节点
free(poi);//释放申请的空间
return head;//返回合并后链表的头节点的地址
}
int main()
{
//链表List1
LNode* n1 = (LNode*)malloc(sizeof(LNode));//创建3个节点
LNode* n2 = (LNode*)malloc(sizeof(LNode));
LNode* n3 = (LNode*)malloc(sizeof(LNode));
LNode* plist1 = n1;//指向List1的头指针plist1
n1->data = 1;//给每个节点都赋值
n2->data = 2;
n3->data = 4;
n1->next = n2;//手动构建链表
n2->next = n3;
n3->next = NULL;
//链表List2
LNode* n4 = (LNode*)malloc(sizeof(LNode));//创建3个节点
LNode* n5 = (LNode*)malloc(sizeof(LNode));
LNode* n6 = (LNode*)malloc(sizeof(LNode));
LNode* plist2 = n4;//指向List2的头指针plist2
n4->data = 1;//给每个节点都赋值
n5->data = 3;
n6->data = 4;
n4->next = n5;//手动构建链表
n5->next = n6;
n6->next = NULL;
printf("List1:");
Print(plist1);//打印链表1
printf("\nList2:");
Print(plist2);//打印链表2
printf("\n合并后:");
LNode* newhead = mergeTwoLists(plist2, plist1);//合并函数
Print(newhead);//打印合并后的链表
return 0;
}
运行结果:
结语:
合并链表的方法如上,希望本文可以对你起到帮助!! ( ̄︶ ̄)↗