本文提供三种方法合并两个有序(从小到大)的单向链表。合并后保持有序。
#include <stdio.h>
#include <stddef.h>
//
// List definition
//
typedef struct rListNode {
int val;
struct rListNode *next;
}ListNode;
//
// List print
//
void ListPrint(ListNode *l)
{
while(l) {
printf("%d\n", l->val);
l = l->next;
}
}
//
// Insert #n into a sorted list #l
//
ListNode *ListSortInsert(ListNode *l, ListNode *n)
{
if (n == NULL) return l;
if (l == NULL) return n;
ListNode *cur = l;
ListNode *nxt = l->next;
if (n->val < cur->val) {
n->next = cur;
return n;
}
while (nxt != NULL && n->val > nxt->val) {
// printf("i val=%d\n", nxt->val);
cur = nxt;
nxt = nxt->next;
}
cur->next = n;
n->next = nxt;
return l;
}
//
// merge two sorted lists to a new sorted list
// 循环遍历其中一个list, 每次插入一个Node到另一个list中
//
ListNode *MergeTwoList(ListNode *l1, ListNode *l2)
{
if (l1 == NULL) return l2;
if (l2 == NULL) return l1;
ListNode *cur = l2;
ListNode *nxt = l2->next;
while(cur) {
// printf("m val=%d\n", cur->val);
l1 = ListSortInsert(l1, cur);
cur = nxt;
if (nxt == NULL) break;
nxt = nxt->next;
}
return l1;
}
//
// merge two sorted lists to a new sorted list
// 同时循环遍历两个list, 每次从两个list中选一个小值到一个新的list中
//
ListNode *MergeTwoList1(ListNode *l1, ListNode *l2)
{
if (l1 == NULL) return l2;
if (l2 == NULL) return l1;
//
// 新list头为head, 为取一个单元到新的list中
//
ListNode *head, *tail;
if (l1->val > l2->val) {
head = tail = l2;
l2 = l2->next;
}
else {
head = tail = l1;
l1 = l1->next;
}
//
// 同时循环遍历两个list, 每次从两个list中选一个小值到一个新的list中
//
while(l1 && l2) {
if (l1->val < l2->val) {
tail->next = l1;
tail = l1;
l1 = l1->next;
}
else {
tail->next = l2;
tail = l2;
l2 = l2->next;
}
}
if (l1==NULL) tail->next = l2;
else if (l2==NULL) tail->next = l1;
return head;
}
//
// merge two sorted lists to a new sorted list
// idea同上,每次选一段,而不是一个单元到新的list
//
ListNode *MergeTwoList2(ListNode *l1, ListNode *l2)
{
if (l1 == NULL) return l2;
if (l2 == NULL) return l1;
ListNode *head = l1;
if (l1->val > l2->val) {
head = l2;
l2 = l1;
l1 = head;
}
// printf("head val=%d\n", head->val);
ListNode *t1 = l1, *t2 = l2;
ListNode *pre;
while(l1 && l2) {
while (l1 && l1->val < l2->val) {
// printf("l1 val=%d\n", l1->val);
pre = l1;
l1 = l1->next;
}
pre->next = l2;
if (!l1) break;
while (l2 && l2->val < l1->val) {
// printf("l2 val=%d\n", l2->val);
pre = l2;
l2 = l2->next;
}
pre->next = l1;
}
return head;
}
//
// 测试
//
int main()
{
// init list1 and list2
ListNode t1[] = {
{1, &t1[1]},
{3, NULL}};
ListNode t2[] = {
{2, &t2[1]},
{4, &t2[2]},
{8, NULL}};
printf("list1:\n");
ListPrint(t1);
printf("list2:\n");
ListPrint(t2);
// 三种方法都测试okay
printf("merge result:\n");
ListPrint(MergeTwoList(t1, t2));
// ListPrint(MergeTwoList1(t1, t2));
// ListPrint(MergeTwoList2(t1, t2));
return 0;
}