排序算法:快速排序算法

文章目录

一、快速排序算法简介

快速排序(Quick Sort) 是一种基于分治思想(Divide & Conquer) 的高效排序算法,它的原理:是选一个基准值(pivot),把数组分成"比它小的"和"比它大的"两部分,然后递归排序。

为什么快速排序这么快?

核心原因有两点

  1. 每一轮都把问题规模一分为二
  2. 元素基本在"正确方向"移动,不做无效交换

平均情况下:

  • 每一层处理 n 个元素
  • 递归深度约为 log n

二、核心思想(分治法)

快速排序分为三步:

  1. 选基准(pivot)
  2. 分区(partition)
  3. 递归排序左右两边

示意:

cpp 复制代码
[  < pivot  |  pivot  |  > pivot  ]

pivot 只做一件事,把数组"一刀切";每一层递归,pivot 都在"最终位置"

  • pivot 左边:永远不会再跑到右边
  • pivot 右边:永远不会再跑到左边

图示解析

假设数组:

cpp 复制代码
[8, 3, 1, 7, 0, 10, 2, 12, 13, 16]

初始状态

cpp 复制代码
索引:  0  1  2  3  4  5   6   7   8   9
数组: [8, 3, 1, 7, 0, 10, 2, 12, 13, 16]
  • pivot = 8
  • 左指针 i = 0
  • 右指针 j = 9

第一轮分区(pivot = 8)

右指针向左找 < pivot 的数

cpp 复制代码
16 > 8  ←
13 > 8  ←
12 > 8  ←
2  < 8  ✅ 停

把 2 填到 pivot 的位置(0 号位)

cpp 复制代码
[2, 3, 1, 7, 0, 10, _, 12, 13, 16]
            ↑ 原来 2 的位置成"坑"

左指针向右找 > pivot 的数

cpp 复制代码
3 < 8 →
1 < 8 →
7 < 8 →
0 < 8 →
10 > 8 ✅ 停

把 10 填到刚才的坑里

cpp 复制代码
[2, 3, 1, 7, 0, _, 10, 12, 13, 16]
                   ↑ 新坑

右指针继续向左

cpp 复制代码
10 > 8 ✔

左右指针相遇,结束循环,把 pivot 放入最终位置:

cpp 复制代码
[2, 3, 1, 7, 0, 8, 10, 12, 13, 16]
              ↑ pivot 就位

第一轮结果

cpp 复制代码
[2, 3, 1, 7, 0]  8  [10, 12, 13, 16]

pivot = 8 已在最终正确位置

递归处理左半部分 [2, 3, 1, 7, 0]

选择 pivot = 2

cpp 复制代码
[2, 3, 1, 7, 0]

从右找 < 2 → 0

cpp 复制代码
[0, 3, 1, 7, _]

从左找 > 2 → 3

cpp 复制代码
[0, _, 1, 7, 3]

从右找 < 2 → 1

cpp 复制代码
[0, 1, _, 7, 3]

指针相遇,放回 pivot:

cpp 复制代码
[0, 1, 2, 7, 3]

左半结果

cpp 复制代码
[0, 1] 2 [7, 3]

递归处理 [7, 3]

pivot = 7

cpp 复制代码
[7, 3]

从右找 < 7 → 3 放回 pivot:

cpp 复制代码
[3, 7]

右半部分 [10, 12, 13, 16]

pivot = 10

cpp 复制代码
[10, 12, 13, 16]

全部都 > 10,pivot 不动

继续递归:

  • 12, 13, 16

  • pivot = 12 → 有序
  • pivot = 13 → 有序

最终排序完成

cpp 复制代码
[0, 1, 2, 3, 7, 8, 10, 12, 13, 16]

全过程结构图(总结版)

cpp 复制代码
                    [8,3,1,7,0,10,2,12,13,16]
                              |
                ----------------------------------
                |                                |
      [2,3,1,7,0]                            [10,12,13,16]
           |                                         |
     ---------------                           已有序
     |             |
 [0,1]           [3,7]

三、完整示例

Hoare 分区法(效率高,工程常用)

cpp 复制代码
int partition(int arr[], int left, int right)
{
    int pivot = arr[left];
    int i = left - 1;
    int j = right + 1;

    while (true)
    {
        do { i++; } while (arr[i] < pivot);
        do { j--; } while (arr[j] > pivot);

        if (i >= j)
            return j;

        swap(arr[i], arr[j]);
    }
}

递归:

cpp 复制代码
void quickSort(int arr[], int left, int right)
{
    if (left < right)
    {
        int p = partition(arr, left, right);
        quickSort(arr, left, p);
        quickSort(arr, p + 1, right);
    }
}
相关推荐
那个村的李富贵8 小时前
CANN加速下的AIGC“即时翻译”:AI语音克隆与实时变声实战
人工智能·算法·aigc·cann
power 雀儿8 小时前
Scaled Dot-Product Attention 分数计算 C++
算法
琹箐8 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
renhongxia19 小时前
如何基于知识图谱进行故障原因、事故原因推理,需要用到哪些算法
人工智能·深度学习·算法·机器学习·自然语言处理·transformer·知识图谱
坚持就完事了9 小时前
数据结构之树(Java实现)
java·算法
算法备案代理9 小时前
大模型备案与算法备案,企业该如何选择?
人工智能·算法·大模型·算法备案
赛姐在努力.9 小时前
【拓扑排序】-- 算法原理讲解,及实现拓扑排序,附赠热门例题
java·算法·图论
野犬寒鸦11 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
霖霖总总11 小时前
[小技巧66]当自增主键耗尽:MySQL 主键溢出问题深度解析与雪花算法替代方案
mysql·算法
rainbow688911 小时前
深入解析C++STL:map与set底层奥秘
java·数据结构·算法