快速排序算法详解:Hoare法、挖坑法、前后指针法及非递归实现
创作时间:
作者:
@小白创作中心
快速排序算法详解:Hoare法、挖坑法、前后指针法及非递归实现
引用
CSDN
1.
https://m.blog.csdn.net/weixin_64099089/article/details/137792497
**快速排序是一种非常高效的排序算法,由C. A. R. Hoare在1960年提出。它采用分治法策略,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。本文将详细介绍快速排序的多种实现方式,包括Hoare法、挖坑法、前后指针法以及非递归实现(栈和队列)。
1. Hoare法
快速排序的核心思想是选择一个基准元素(通常选择序列的第一个元素),通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
单趟排序步骤:
- 选定一个基准元素(key),初始化左右指针L和R
- R从右向左查找比key小的元素
- L从左向右查找比key大的元素
- 交换L和R位置的元素
- 重复步骤2-4,直到L和R相遇
- 最后将基准元素与相遇位置的元素交换
单趟排序的意义:
- 基准元素被放置到正确的位置
- 将序列分割成两个子区间,左侧元素都小于基准元素,右侧元素都大于基准元素
单趟排序实现:
void PartSort(int* a, int begin, int end) {
if (begin >= end)
return;
int keyi = begin;
int key = a[keyi];
int Left = begin;
int Right = end;
while (Left < Right) {
while (Left < Right && a[Right] >= key)
Right--;
while (Left < Right && a[Left] <= key)
Left++;
Swap(&a[Left], &a[Right]);
}
Swap(&a[keyi], &a[Left]);
}
快速排序递归实现:
void QuickSort(int *a, int begin, int end) {
assert(a);
if (begin >= end)
return;
int meet = PartSort(a, begin, end);
QuickSort(a, begin, meet - 1);
QuickSort(a, meet + 1, end);
}
2. 挖坑法
挖坑法是快速排序的另一种实现方式,其核心思想是通过"挖坑填数"的方式进行元素交换,可以减少代码中的边界条件判断,使代码更加简洁。
单趟排序步骤:
- 选择一个基准元素(key),将其位置设为"坑"
- R从右向左查找比key小的元素,找到后填入"坑"中,当前位置变成新的"坑"
- L从左向右查找比key大的元素,找到后填入"坑"中,当前位置变成新的"坑"
- 重复步骤2-3,直到L和R相遇
- 最后将基准元素填入相遇位置的"坑"中
单趟排序实现:
int QuickPastSort2(int* a, int begin, int end) {
assert(a);
int keyi = GetMidIndex(a, begin, end);
int key = a[keyi];
Swap(&a[keyi], &a[begin]);
keyi = begin;
int hole = begin;
int left = begin;
int right = end;
while (left < right) {
while (left < right && a[right] >= key)
right--;
a[hole] = a[right];
hole = right;
while (left < right && a[left] <= key)
left++;
a[hole] = a[left];
hole = left;
}
a[hole] = key;
return hole;
}
3. 前后指针法
前后指针法是快速排序的另一种实现方式,其核心思想是使用两个指针(prev和cur)进行元素交换,可以进一步简化代码逻辑。
单趟排序步骤:
- 初始化prev指向基准元素,cur指向基准元素的下一个位置
- prev和cur同时向前移动,直到prev的下一个位置是比基准元素大的数
- prev停在比基准元素大的数前面,cur继续向后查找比基准元素小的数
- cur找到比基准元素小的值后,prev先++,然后prev和cur位置的数交换
- 最后cur越界时,key与prev指向的位置交换
单趟排序实现:
int QuickPartSort3(int* a, int begin, int end) {
assert(a);
int keyi = GetMidIndex(a, begin, end);
Swap(&a[keyi], &a[begin]);
int key = a[begin];
keyi = begin;
int prev = begin;
int cur = begin + 1;
while (cur <= end) {
if (a[cur] < key && ++prev != cur)
Swap(&a[cur], &a[prev]);
cur++;
}
Swap(&a[begin], &a[prev]);
return prev;
}
4. 快排的非递归实现
快速排序的递归实现可能会导致栈溢出问题,特别是在数据量较大时。因此,可以使用栈或队列来实现非递归版本的快速排序。
4.1 栈实现快排非递归
使用栈实现非递归快速排序时,可以按照前序遍历的顺序,先处理左子区间,再处理右子区间。
void StackQuickSort(int* a, int n) {
assert(a);
ST st;
STInit(&st);
StackPush(&st, n - 1);
StackPush(&st, 0);
while (!StackEmpty(&st)) {
int begin = StackTop(&st);
StackPop(&st);
int end = StackTop(&st);
StackPop(&st);
if (begin >= end)
continue;
int meet = QuickPastSort1(a, begin, end);
StackPush(&st, end);
StackPush(&st, meet + 1);
StackPush(&st, meet - 1);
StackPush(&st, begin);
}
STDestroy(&st);
}
4.2 队列实现快排非递归
使用队列实现非递归快速排序时,可以按照层序遍历的顺序,依次处理每个子区间。
void QueueQuickSort(int* a, int n) {
assert(a);
Queue q;
QueueInit(&q);
QueuePush(&q, 0);
QueuePush(&q, n - 1);
while (!QueueEmpty(&q)) {
int begin = QueueFront(&q);
QueuePop(&q);
int end = QueueFront(&q);
QueuePop(&q);
if (begin >= end)
continue;
int meet = QuickPastSort1(a, begin, end);
QueuePush(&q, begin);
QueuePush(&q, meet - 1);
QueuePush(&q, meet + 1);
QueuePush(&q, end);
}
QueueDestroy(&q);
}
使用栈和队列实现非递归快速排序时,空间复杂度为O(1),但在实际应用中,递归实现更为简洁和方便。
热门推荐
计算机科学与技术专业主要学些什么 开设课程有哪些
立冬:岁暮轻寒 万物归藏
日本动画产业的发展现状及未来趋势
国家能源集团非煤运输提前实现“硬过半”
清明节踏青传承文化,手抄报展示清明节的由来、习俗与历史
团队的凝聚力如何提高
睡觉总是不自觉地张开嘴?可能是这7个原因引起的!
一氧化二氢是什么?
Win11显卡功率在哪里查看?如何实时监控显卡功耗?
2024年以来南宁市电信网络诈骗案件立案数同比下降37%
清明时节:传统与现代的交融,如何过一个有意义的节日?
手机租赁系统全面解析 提升效率与安全保障的创新解决方案
《盲派八字实战秘籍:精准命理解析之道》
日照岚山区:“南茶北引”地 “一叶”兴“一业”
国内可以办的国际银行卡:如何选择与申请指南
湖南13个茶叶产地全攻略:从安化黑茶到君山银针,品茗赏景两相宜
木门选购指南:烤漆门 vs 免漆门,哪个更适合你?
灵芝和树舌的区别(认识中草药,从灵芝和树舌说起)
无名指断一节算几级伤残鉴定?头部受伤和骨折的伤残等级如何评定?
乌干达麦克雷雷大学孔子学院举行成立十周年庆典
女性去黑头容易陷入哪些误区
12306积分可以兑换车票?怎么兑换?教程来了→
街亭之战:马谡的战术选择是否正确?
牛肉各部位老嫩等级与烹饪指南
无糖饮料也会影响血糖吗?
眼视神经萎缩最佳治疗方法
诵读·地名背后山西史 | 临汾:不叫平阳也合适
中国十大著名音乐节:领略音乐节的独特魅力
铁路盈利问题的解决思路有哪些?这些思路的实施难度如何?
北歐四國是哪四國?北歐四國在哪裡