惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Cloudflare Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
小众软件
小众软件
J
Java Code Geeks
V
Visual Studio Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
美团技术团队
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
博客园 - 叶小钗
N
Netflix TechBlog - Medium
月光博客
月光博客
aimingoo的专栏
aimingoo的专栏
大猫的无限游戏
大猫的无限游戏
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Cisco Talos Blog
Cisco Talos Blog
Hacker News: Ask HN
Hacker News: Ask HN
Hacker News - Newest:
Hacker News - Newest: "LLM"
AWS News Blog
AWS News Blog
Webroot Blog
Webroot Blog
The Last Watchdog
The Last Watchdog
T
Threatpost
I
Intezer
T
Tenable Blog
L
LINUX DO - 热门话题
T
Tailwind CSS Blog
Scott Helme
Scott Helme
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cybersecurity and Infrastructure Security Agency CISA
Engineering at Meta
Engineering at Meta
S
Schneier on Security
Recent Announcements
Recent Announcements
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs
腾讯CDC
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Troy Hunt's Blog
量子位
H
Hacker News: Front Page
V2EX - 技术
V2EX - 技术
Google Online Security Blog
Google Online Security Blog
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
博客园 - Franky
www.infosecurity-magazine.com
www.infosecurity-magazine.com

Louis C Deng's Blog

CS231n Lecture Note: Generative Models CS231n Lecture Note: Self-Supervised Learning CS231n Lecture Note: Large Scale Distributed Training 自動微分 | DIY 實現自己的 PyTorch From RNNs to Transformers CS231n Lecture Note VII: Recurrent Neural Networks Uncovering Batch & Layer Normalization CS231n Lecture Note VI: CNN Architectures and Training CS231n Lecture Note V: Convolution Neural Networks Basics Demystifying Softmax Loss: A Step-by-Step Derivation for Linear Classifiers Backpropagation: A Vector Calculus Perspective CS231n Lecture Note IV: Neural Networks and Backpropagation CS231n Lecture Note III: Optimization CS231n Lecture Note II: Linear Classifiers CS231n Lecture Note I: Image Classification CSAPP Cache Lab II: Optimizing Matrix Transposition CSAPP Cache Lab I: Let's simulate a cache memory! CS188 Search Lecture Notes III CS188 Search Lecture Notes II How to Use TouchID for Sudo Commands on macOS CS188 Search Lecture Notes I RECAP2025: 留白 CSAPP Bomb Lab 解析 x64 暫存器速查表 CSAPP Data Lab 解析 矩陣的 Modified Gram Schmidt 方法 聊一聊位掩碼(Bit Mask) 整數溢位與未定義行為 等待 記夢(DeepSeek 輔助創作) 午夜飛行 橋樑 黎明 或 2012 RECAP2024: 水檻臥聽雨 太陽、潮落 RECAP2023: 泡沫 題解 P1622 釋放囚犯 題解 P5888 傳球遊戲 殘陽似火 再會 飢餓藝術家 卡夫卡 Python 中的 zip() 和 enumerate() 泡沫 “救救孩子……”——談魯迅和《狂人日記》 想念 淺灘 蟬 · 夏 微風 觀星 浮塵 復活 【摘錄 | 轉載】普魯斯特 《追憶似水年華》第一卷 《在斯萬家那邊》(一) Time - Pink Floyd - The Dark Side of the Moon 【轉載】靜夜思變調 高樓 幻夢 冰 RECAP2022: 流星雨 清夜 割點 Tarjan 演算法 P3147 USACO16OPEN 262144 P 題解 P3354 Riv 河流 題解 馬拉車演算法 夜雨 層霧 從愚人節玩笑到真的玩笑(bushi): 淺談 lsnotes I made my own Hexo theme 題解 紀念品分組 題解 導彈攔截 如何高效使用搜尋引擎 用 GitHub Actions 格式化 C/C++ 程式碼 四季的天空 洛谷 7 月月賽 Div.2 總結 題解 最近公共祖先 (LCA) 用簡單的物理方法證明牛頓萊布尼茨公式 簡評榮耀手環6 海上生明月,天涯共此時。 我為什麼重新拿出了 iPod Swift 中的 SharedPreferance —— UserDefaults 凝視那一輪明月 用 GitHub Actions 部署 Hexo 部落格 遲來的日誌 - WWDC 2020 獎學金 vcpkg - 方便的 C/C++ 庫管理器 vimrc 配置指南 NextCloud - DIY NAS 解決方案 sudo shutdown -r now sudo shutdown -r now
快速排序 幾種劃分方法討論
Louis C Deng · 2025-09-11 · via Louis C Deng's Blog

最近在複習資料結構與演算法,聊聊快速排序的幾種劃分演算法。

快速排序思路

快速排序是一種基於分治策略的排序演算法。

對於待排序陣列,其核心操作是:

  1. 選取一個基準數pivot
  2. 將陣列分為兩塊,一塊小於等於基準數,另一塊大於等於基準數(注意 基準數作為分界點)
  3. 遞迴地對於分出來的兩個數字再次進行快速排序

不斷地進行劃分,遞迴,最後能保證整個陣列有序。

基準數的選取

一般來說,基準數有幾種選取方法:

  1. 選取第一個數或者最後一個數:這樣做,如果陣列已經排好序,則每次劃分都是基準數和剩餘數,時間複雜度升至O(n^2)
  2. 隨機選擇一個數
  3. 選取中位數:這樣做始終能對原陣列進行等分,尋找中位數是線性時間的。

下面以最無腦的方法1為例。

幾種劃分方法

主要的劃分方法有:

  1. 樸素劃分
  2. Lomuto 劃分
  3. Hoare 劃分

中國大陸教材中經常出現的是第三種,即 Hoare 劃分,也叫哨兵劃分。

樸素劃分

思路很無腦。直接開一個新陣列,把比 pivot 小的放左邊,比 pivot 大的放右邊,最後把陣列複製回到原陣列。需要 O(n) 的額外空間。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const int N; 
int A[N];
int tmp[N];
int Native_Partition(int left, int right) {
int pivot = A[left];

int idx = left;

for (int i = left; i <= right; i++) {
if (A[i] < pivot)
tmp[idx++] = A[i];
}

int pid = idx;
tmp[idx++] = pivot;

for (int i = left; i <= right; i++) {
if (A[i] > pivot)
tmp[idx++] = A[i];
}

for (int i = left; i <= right; i++) {
A[i] = tmp[i];
}

return pid;
}

Lomuto 劃分

Lomuto 劃分即使用單個指標,從左到右掃描陣列,交換,維持劃分順序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int Lomuto_Partition(int left, int right) {
int pivot = A[right];

int i = left - 1;


for (int j = left; j <= right - 1; j++) {
if (A[j] < pivot) {
i++;
swap(A[i], A[j]);
}
}


swap(A[i + 1], A[right]);
return i + 1;
}

Hoare 劃分

Hoare 劃分採用雙指標,進行交換。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int Hoare_Partition(int left, int right) {
int pivot = A[left];
int pid = left;
while (left < right) {
while (left < right && A[right] >= pivot) {
right--;
}
while (left < right && A[left] <= pivot) {
left++;
}
swap(A[left], A[right]);
}

swap(A[pid], A[left]);
return pid;
}

掃描順序對於結果有影響。pivot 在最左邊時,應該先從右往左掃描。

如果先從左往右掃,找第一個大於 pivot 的數 a,而第一個小於 pivot 的數在 a 左側,此時進行 pivot 和 A[left] 的交換,會導致交換錯誤。故應該優先保證 pivot 左側都小於等於 pivot,即先尋找第一個小於 pivot 的數,這樣交換是安全的。

快速排序演算法

對於某劃分函式 partition(int st, int end) -> pivot: int

1
2
3
4
5
6
7
8
9
10
11
12
const int N; 
int A[N];

void qsort(int st, int end){
if(st >= end) return;

int pivot = partition(st, end);


qsort(st, pivot-1);
qsort(pivot+1, end);
}