将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解这题之前看到一篇讲链表基本使用的文章,写的很详细。后面代码部分也是参考的这篇文章,可以看一下:
https://www.jb51.net/article/214771.htm
虽然题目的意思是合并两个有序链表,但是要完全实现题目的意思首先我们需要先生成两个有序链表。一种简单的方式是建立两个链表然后手动有序赋值。但是感觉这样不是很好,所以这里我选择随机生成然后自动排序的方式生成两个链表。:
void InitList(Node*& head) {
head = new Node();
head->value = 0;
head->next = NULL;
}
//插入函数
bool Listinsert(Node*& head, int i) {
//插入到前面的方法
int value;
value = rand() % 10, 1;
int j = 0;
Node* L = head;
//如果插入的位置不合法,直接返回错误提示
if (i<1 || i>head->value + 1)return false;
//得到插入位置的前一个结点
while (j < i - 1) {
L = L->next;
++j;
}
//s是一个临时结点
Node* s = new Node();
s->value = value; //先对临时结点赋值
s->next = L->next; //让临时结点下一个位置指向当前需要插入前一个结点的下一个位置
L->next = s; //让前一个结点下一个位置指向临时结点,完成
//线性表的长度加一
++head->value;
return true;
}
InitList是初始化一个链表。Listinsert是向该链表中插入一定的数据。数据长度由int i决定。
链表的排序在上面的那个链接中大佬给出了三种方式,这里我使用了他其中最简单的我们最常用的排序方式:冒泡排序
void Listsort(Node*& head) {
int i = 0;
int j = 0;
//用于变量链表
Node* L = head;
//作为一个临时量
Node* p;
Node* p1;
//如果链表为空直接返回
if (head->value == 0)return;
for (i = 0; i < head->value - 1; i++) {
L = head->next;
for (j = 0; j < head->value - i - 1; j++) {
//得到两个值
p = L;
p1 = L->next;
//如果前面的那个比后面的那个大,就交换它们之间的是数据域
if (p->value > p1->value) {
Elemtype temp = p->value;
p->value = p1->value;
p1->value = temp;
}
L = L->next;
}
}
}
将两个升序链表合并为一个新的升序链表并返回。
这个方法有两种,今天自己尝试了写了一下花费了点时间但是最后还是实现了其中一种:
void combination(Node*& head, Node*& list, Node*& list3)
{
Node* L1 = head;
Node* L2 = list;
Node* L3 = list3;
L1 = L1->next;
L2 = L2->next;
//L3 = L3->next;
while (L1 != NULL || L2 != NULL)
{
L3->next = new Node();
L3 = L3->next;
if (L1 != NULL && L2 != NULL)
{
if (L1->value > L2->value)
{
L3->value = L2->value;
L2 = L2->next;
}
else
{
L3->value = L1->value;
L1 = L1->next;
}
}
else if (L1 == NULL && L2 != NULL)
{
L3->value = L2->value;
L2 = L2->next;
/* if (L2 != nullptr)
{
L3->next = new Node();
L3 = L3->next;
}*/
}
else
{
L3->value = L1->value;
L1 = L1->next;
/*if (L1 != nullptr)
{
L3->next = new Node();
L3 = L3->next;
}*/
}
//print(list3);
//L3 = L3->next;
}
}
这个方法比较简单也比较好理解,就是从两个链表中顺序取数,然后比较大小。小的数字存入第三个链表,大的数字保留。然后从小的数字那个链表中重新取下一个数字过来比较。循环直到结束。
这里唯一需要注意的是考虑到最后几位的比较。因为有可能一个链表数字取完了另一个链表中仍然存在一定的数据。所以这里要判断一下是否一个链表为空而另一个链表不为空的情况。
完整代码实现:
#include
#include
#include
//#include
#include
using namespace std;
typedef int Elemtype;
//链式结构,我们打算在链表中添加一个
//保存长度的头结点,加入这个结点可以方便我们对结点做一些
//基本的操作,结点保存的是线性表的长度
struct Node
{
//结点的值,如果是头结点,保存是链表的长度
Elemtype value;
//下一个结点的地址
Node* next;
};
//创建一个空链表,每个头结点就代表一个链表
void InitList(Node*& head) {
head = new Node();
head->value = 0;
head->next = NULL;
}
//插入函数
bool Listinsert(Node*& head, int i) {
//插入到前面的方法
int value;
value = rand() % 10, 1;
int j = 0;
Node* L = head;
//如果插入的位置不合法,直接返回错误提示
if (i<1 || i>head->value + 1)return false;
//得到插入位置的前一个结点
while (j < i - 1) {
L = L->next;
++j;
}
//s是一个临时结点
Node* s = new Node();
s->value = value; //先对临时结点赋值
s->next = L->next; //让临时结点下一个位置指向当前需要插入前一个结点的下一个位置
L->next = s; //让前一个结点下一个位置指向临时结点,完成
//线性表的长度加一
++head->value;
return true;
}
//线性表的排序,采用冒泡排序,直接遍历链表
void Listsort(Node*& head) {
int i = 0;
int j = 0;
//用于变量链表
Node* L = head;
//作为一个临时量
Node* p;
Node* p1;
//如果链表为空直接返回
if (head->value == 0)return;
for (i = 0; i < head->value - 1; i++) {
L = head->next;
for (j = 0; j < head->value - i - 1; j++) {
//得到两个值
p = L;
p1 = L->next;
//如果前面的那个比后面的那个大,就交换它们之间的是数据域
if (p->value > p1->value) {
Elemtype temp = p->value;
p->value = p1->value;
p1->value = temp;
}
L = L->next;
}
}
}
void combination(Node*& head, Node*& list, Node*& list3)
{
Node* L1 = head;
Node* L2 = list;
Node* L3 = list3;
L1 = L1->next;
L2 = L2->next;
//L3 = L3->next;
while (L1 != NULL || L2 != NULL)
{
L3->next = new Node();
L3 = L3->next;
if (L1 != NULL && L2 != NULL)
{
if (L1->value > L2->value)
{
L3->value = L2->value;
L2 = L2->next;
}
else
{
L3->value = L1->value;
L1 = L1->next;
}
}
else if (L1 == NULL && L2 != NULL)
{
L3->value = L2->value;
L2 = L2->next;
}
else
{
L3->value = L1->value;
L1 = L1->next;
}
}
}
void print(Node*& head);
//线性表的排序,采用冒泡排序,直接遍历链表
//线性表的排序,交换结点
void print(Node*& head) {
//输出我们只需要传入头结点,然后循环判断当前结点下一个结点是否为空,
//这样就可以输出所有内容
Node* L = head;
while (L->next) {
L = L->next;
cout << L->value << " ";
}
cout << endl;
}
int main() {
//链表的头结点,不存放任何值,首先初始化头结点
Node* head;
Node* list;
Node* list3;
srand((int)time(NULL)); //每次执行种子不同,生成不同的随机数
//创建一个链表
InitList(head);
InitList(list);
InitList(list3);
int i;
cout << "请输入需要插入元素个数" << endl;
int n;
cin >> n;//5
//cout << "请输入" << n << "个值" << endl;
for (i = 0; i < n; i++) {
Elemtype temp;
temp = rand() % 10, 1;
if (!Listinsert(head, i + 1)) {
cout << "插入元素失败" << endl;
}
if (!Listinsert(list, i + 1)) {
cout << "插入元素失败" << endl;
}
}
print(head);
print(list);
cout << "冒泡排序" << endl;
Listsort(head);
Listsort(list);
//cout << list << endl;
print(head);
print(list);
cout << "合并链表" << endl;
combination(head, list, list3);
print(list3);
//mergeTwoLists(head, list);
//system("pause");
return 0;
}
这里还有另外一种看起来比较简洁的方法:递归
Node* mergeTwoSortedLinkListWithRecursion(Node* head1, Node* head2) {
//如果head1 和 head2有一个为空 则直接返回另一个
if (!head1) {
printf("!head1");
return head2;
}
if (!head2) {
printf("!head2");
return head1;
}
//递归可以理解为之后的情况都处理好了 只需要解决好当前这步就行了
if (head1->value < head2->value) {
head1->next = mergeTwoSortedLinkListWithRecursion(head1->next, head2);
return head1;
}
else {
head2->next = mergeTwoSortedLinkListWithRecursion(head1, head2->next);
return head2;
}
}
这个代码没具体实现。这个方法应该是可行的。
参考:
https://www.jb51.net/article/193132.htm
https://blog.csdn.net/qq_42673507/article/details/91360021
https://www.jb51.net/article/214771.htm
https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/