数组快排 链表归并

什么是数组快排

快速排序是一种:

分治思想的排序算法

平均时间复杂度 O(n log n)

原地排序(不需要额外数组)

实际中 非常快(STL sort 的核心思想之一)

核心一句话:

选一个 " 基准值 " ,把数组分成 " 比它小的 " " 比它大的 " ,递归排序

快排的直觉理解

假设有数组:

5, 1, 6, 2, 4, 3

选一个基准值

一般选:

第一个元素

最后一个元素

或中间元素

比如选 5作为基准值

一趟划分

目标是:

左边 <= 5 | 5 | >= 5 右边

执行完一趟后,5 会到它最终该在的位置

结果可能变成:

3, 1, 4, 2\] 5 \[6

注意:

左右两边不一定有序

5 的位置已经确定,不会再动

递归排序左右两部分

对左边 [3,1,4,2] 再做快排

对右边 [6] 不用排

快排的核心: 划分

常见做法:左右指针法(最经典)

假设:

pivot = a[l]

i = l

j = r

步骤:

  1. 从右往左找 < pivot 的
  2. 从左往右找 > pivot 的
  3. 交换它们
  4. 重复,直到 i == j
  5. 把 pivot 放到中间位置

代码:

cpp 复制代码
void quickSort(int a[], int l, int r)
{
    if (l >= r) return;
int pivot = a[l];
    int i = l, j = r;
while (i < j)
    {
        // 从右往左找比 pivot 小的
        while (i < j && a[j] >= pivot) j--;
        // 从左往右找比 pivot 大的
        while (i < j && a[i] <= pivot) i++;
if (i < j)
            swap(a[i], a[j]);
    }
// pivot 放到正确位置
    swap(a[l], a[i]);
quickSort(a, l, i - 1);
    quickSort(a, i + 1, r);
}

时间复杂度

|-----------|------------|
| 情况 | 复杂度 |
| 平均 | O(n log n) |
| 最坏(已排序数组) | O(n²) |

为了避免最坏情况,实际中会:

随机选 pivot

或三数取中

链表归并排序核心思想

:用快慢指针把链表从中间断开

:递归排序左右两条链表

:合并两个有序链表

完美适配链表结构。

链表节点定义

cpp 复制代码
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

主函数:链表归并排序

cpp 复制代码
ListNode* mergeSortList(ListNode* head)
{
    // 递归结束条件
    if (!head || !head->next)
        return head;
//  快慢指针找中点
    ListNode* slow = head;
    ListNode* fast = head->next;
while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
// 断开链表
    ListNode* mid = slow->next;
    slow->next = nullptr;
//  递归排序左右部分
    ListNode* left = mergeSortList(head);
    ListNode* right = mergeSortList(mid);
// 合并两个有序链表
    return mergeTwoLists(left, right);
}

合并两个有序链表

cpp 复制代码
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
    ListNode dummy(0);
    ListNode* tail = &dummy;
while (l1 && l2)
    {
        if (l1->val <= l2->val)
        {
            tail->next = l1;
            l1 = l1->next;
        }
        else
        {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }
// 接上剩余部分
    tail->next = l1 ? l1 : l2;
return dummy.next; 
}

复杂度分析(面试必说)

|--------|-------------------|
| 项目 | 复杂度 |
| 时间复杂度 | O(n log n) |
| 空间复杂度 | O(log n)(递归栈) |
| 是否稳定 | 稳定 |
| 是否原地 | (不新建节点) |

为什么链表「一定选归并排序」

三大理由:

不需要随机访问

合并链表天然 O(n)

稳定排序、实现简洁

相关推荐
skywalker_114 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
_日拱一卒5 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾5 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio
计算机安禾5 小时前
【数据结构与算法】第35篇:归并排序与基数排序
c语言·数据结构·vscode·算法·排序算法·哈希算法·visual studio
专注API从业者5 小时前
淘宝商品详情 API 与爬虫技术的边界:合法接入与反爬策略的技术博弈
大数据·数据结构·数据库·爬虫
汀、人工智能6 小时前
[特殊字符] 第66课:跳跃游戏
数据结构·算法·数据库架构·图论·bfs·跳跃游戏
汀、人工智能6 小时前
[特殊字符] 第70课:加油站
数据结构·算法·数据库架构·图论·bfs·加油站
favour_you___6 小时前
2026_4_8算法练习题
数据结构·c++·算法
汀、人工智能6 小时前
[特殊字符] 第57课:搜索旋转排序数组
数据结构·算法·数据库架构·图论·bfs·搜索旋转排序数组
夏乌_Wx7 小时前
剑指offer | 2.4数据结构相关题目
数据结构·c++·算法·剑指offer·c/c++