C++ 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

解这题之前看到一篇讲链表基本使用的文章,写的很详细。后面代码部分也是参考的这篇文章,可以看一下:

https://www.jb51.net/article/214771.htm

虽然题目的意思是合并两个有序链表,但是要完全实现题目的意思首先我们需要先生成两个有序链表。一种简单的方式是建立两个链表然后手动有序赋值。但是感觉这样不是很好,所以这里我选择随机生成然后自动排序的方式生成两个链表。:

1.随机生成一个链表

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决定。

2.链表排序

链表的排序在上面的那个链接中大佬给出了三种方式,这里我使用了他其中最简单的我们最常用的排序方式:冒泡排序

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;
        }
    }
}

3.链表合并

将两个升序链表合并为一个新的升序链表并返回。

这个方法有两种,今天自己尝试了写了一下花费了点时间但是最后还是实现了其中一种:

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<iostream>
#include<ctime>
#include<cstdlib>
//#include<windows.h>
#include<algorithm>
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/

  • 10
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一叶执念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值