合并两个有序链表是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));//创建一个头节点newheadwhile (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()
{//链表List1LNode* n1 = (LNode*)malloc(sizeof(LNode));//创建3个节点LNode* n2 = (LNode*)malloc(sizeof(LNode));LNode* n3 = (LNode*)malloc(sizeof(LNode));LNode* plist1 = n1;//指向List1的头指针plist1n1->data = 1;//给每个节点都赋值n2->data = 2;n3->data = 4;n1->next = n2;//手动构建链表n2->next = n3;n3->next = NULL;//链表List2LNode* n4 = (LNode*)malloc(sizeof(LNode));//创建3个节点LNode* n5 = (LNode*)malloc(sizeof(LNode));LNode* n6 = (LNode*)malloc(sizeof(LNode));LNode* plist2 = n4;//指向List2的头指针plist2n4->data = 1;//给每个节点都赋值n5->data = 3;n6->data = 4;n4->next = n5;//手动构建链表n5->next = n6;n6->next = NULL;printf("List1:");Print(plist1);//打印链表1printf("\nList2:");Print(plist2);//打印链表2printf("\n合并后:");LNode* newhead = mergeTwoLists(plist2, plist1);//合并函数Print(newhead);//打印合并后的链表return 0;
}
运行结果:
结语:
合并链表的方法如上,希望本文可以对你起到帮助!! ( ̄︶ ̄)↗