【算法】合并两个有序链表(C++)

文章目录

  • 前言
  • 一、链表是什么?
  • 二、题目讲解
    • 1.解题思路
    • 2.代码实现
  • 总结


前言

LeetCode #21 Easy 合并两个有序链表
题目链接 [LeetCode] merge-two-sorted-lists


一、链表是什么?

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到 O ( 1 ) O(1) O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要 O ( n ) O(n) O(n)的时间,而线性表和顺序表相应的时间复杂度分别是 O ( log ⁡ n ) O(\log n) O(logn) O ( 1 ) O(1) O(1)

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。


二、题目讲解

1.解题思路

首先设置一个新的节点 p r e h e a d prehead prehead,赋值为 − 1 -1 1。我们需要维护一个 p r e v prev prev指针,即调整它的 n e x t next next指针 ( p r e v − > n e x t ) (prev->next) (prev>next)。取两个链表的头节点,存放在 p 1 p1 p1 p 2 p2 p2,然后重复以下操作:如果 p 1 p1 p1所在节点的值小于等于 p 2 p2 p2所在节点的值,我们就把 p 1 p1 p1当前的节点接在 p r e v prev prev节点的后面,同时将 p 1 p1 p1指针后移一位。否则,我们对 p 2 p2 p2做同样的操作。然后将 p r e v prev prev指针后移一位。

当一条链表终止的时候, p 1 p1 p1 p 2 p2 p2至多有一个是非空的。由于两个链表都是有序的,所以无论哪个链表非空,它剩下部分包含的所有元素都比前面已经合并链表中的所有元素都要大。所以我们只需要将非空链表接在合并链表的后面,并返回合并链表。
【算法】合并两个有序链表(C++)_第1张图片
【算法】合并两个有序链表(C++)_第2张图片
【算法】合并两个有序链表(C++)_第3张图片

以此类推,最终可以得到排列好的链表


2.代码实现

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
    	// 如果list1是空的,返回list2,反之亦然
        if(!list1) return list2;
        if(!list2) return list1;
        // 设定一个新的节点,赋值为-1
        ListNode* preHead = new ListNode(-1);
        // 初始化prev
        ListNode* prev = preHead;
        // 分别取list1和list2的头节点
        ListNode* p1 = list1;
        ListNode* p2 = list2;
        // 当p1和p2都不为空
        while(p1 && p2){
            if(p1->val < p2->val){
            	// 平行移动两个指针
                prev->next = p1;
                p1 = p1->next;
            }
            else{
            	// 平行移动两个指针
                prev->next = p2;
                p2 = p2->next;
            }
            prev = prev->next;
        }
        // 如果p1为空,则连接p2; 反之连接p1
        prev->next = !p1 ? p2 : p1;
        // 注意返回链表的头节点,而不是新建的节点
        return preHead->next;
    }
};

总结

以上为作者总结的合并两个有序链表的解题思路,有需要的读者可以收藏本篇。
题目链接 [LeetCode] merge-two-sorted-lists

你可能感兴趣的:(算法,c++,数据结构,链表)