将两个非递增的有序链表合并为一个非递减的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据操作的名称和参数使用下列结构:La和Lb表示将要合并的链表,合并后的新表使用头指针Lc指向。
void MergeList(LinkList& La, LinkList& Lb, LinkList& Lc)
网上查到的大部分是两个非递减(即递增)的有序链表,书上的也是非递减链表合并成非递减(递增)链表,而题目要求的是非递增(即递减)的有序链表合并为递增。所以我打算合并为一个递减链表后再将链表逆序得到一个递增的链表以完成题目要求。
书上的两个非递减有序链表合并为一个非递减链表代码,参考用:
值得一提的是函数参数中的 &L 是c++独有的引用,相对于C的指针传参不但可以改变实参的值,而且引用初始化后不可以被更改,据说这样比指针操作更安全,目前我就当做和指针传参理解。
C++代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef struct Node *LinkList;
void InitList(LinkList &L); // 创建空链表和本题无关
void Creat_LinkList(LinkList &L, int len); // 通过输入指定数量的值创建链表
void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc); // 合并两个递减有序链表为一个
void reverse(LinkList &La); // 将递减的链表逆序为递增的
void showlinklist(LinkList &L); // 打印出链表
int main(int argc, char const *argv[])
{
LinkList La = 0, Lb = 0, Lc;
// puts("递减链表La"); // 5 4 3 2 1
Creat_LinkList(La, 5);
printf("La链表为:");
showlinklist(La);
// puts("\n递减链表Lb"); // 9 8 7 6 5
Creat_LinkList(Lb, 5);
printf("Lb链表为:");
showlinklist(Lb);
puts("\n合并为递增的有序链表:");
MergeList(La, Lb, Lc);
showlinklist(Lc);
return 0;
}
void InitList(LinkList &L)
{
L = new Node;
L->data = 66;
L->next = NULL;
}
void Creat_LinkList(LinkList &L, int len)
{
if (len <= 0)
{
printf("\n长度错误!");
exit(1);
}
Node *p;
//建立头结点
L = new Node;
L->next = NULL;
p = L;
printf("\n输入链表元素:");
for (int i = 1; i <= len; i++)
{
Node *New_LNode = new Node; //LNode* New_LNode;//程序出错
scanf("%d", &(New_LNode->data)); //note:之前在这里出了错,用的scanf("%d", New_LNode -> data);一定要加取址&
New_LNode->next = NULL;
p->next = New_LNode;
p = p->next;
}
}
// 3 3 1 ; 5 2 2 -> 1 2 2 3 3 5
void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc)
{
Node *pa = La->next;
Node *pb = Lb->next;
Lc = La;
Node *pc = Lc;
while (pa && pb)
{
if (pa->data <= pb->data)
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
else
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
}
pc->next = pa ? pa : pb;
reverse(Lc);
delete Lb;
}
void reverse(LinkList &La)
{
Node *temp = NULL;
Node *front = La->next;
Node *end = La->next->next;
while (end != NULL)
{
temp = end->next;
end->next = front;
front = end;
end = temp;
}
La->next->next = NULL;
La->next = front;
}
void showlinklist(LinkList &L)
{
Node *p = L->next;
while (p!=NULL)
{
printf("%d ",p->data);
p = p->next;
}
}
result:
输入链表元素:5 4 3 2 1
La链表为:5 4 3 2 1
输入链表元素:9 8 7 6 5
Lb链表为:9 8 7 6 5
合并为递增的有序链表:
1 2 3 4 5 5 6 7 8 9
以上便是 两个递减有序链表合并为一个递减有序链表 代码的实现,思路就是通过指针遍历两个链表对当前的表头做比较,大的放到Lc,一直遍历完其中一个表结束为止,得到一个有序的递减链表;
接着链表逆序的思路来着这篇blog:
https://blog.csdn.net/bingocoder/article/details/88761047
2021.2.2更新
合并两个有序链表为一个有序链表可以使用递归更简单实现,相对少一个函数参数
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
int val;
struct ListNode *next;
};
struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2); // 返回一个链表结点指针
int main(int argc, char const *argv[])
{
ListNode l1, l2, n1, n2, n3, n4;
// ListNode *n1_p, n2_p, n3_p, n4_p;
l1.val = 1;
l1.next = &n1;
n1.val = 2;
n1.next = &n2;
n2.val = 4;
n2.next = NULL;
l2.val = 1;
l2.next = &n3;
n3.val = 3;
n3.next = &n4;
n4.val = 4;
n4.next = NULL;
ListNode *l3 = mergeTwoLists(&l1, &l2);
return 0;
}
struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2)
{
if (l1 == NULL)
return l2;
if (l2 == NULL)
return l1;
if (l1->val < l2->val)
{
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}
else
{
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}