快速排序及其变体
创始人
2024-03-22 05:36:39
0

快速排序(Quick Sort)

原理解析

对于要排序的区间,先定一个基准数p(基准数可随机指定,可指定区间两端,或者区间中心的数为基准数)。然后将区间中小于p的数放到p之前,大于p的数放在p之后,最后使用分治策略,分别对p之前的子区间和p之后的子区间递归并排序。

该算法平均时间复杂度O(N×logN)O(N\times log N)O(N×logN),最坏O(N2)O(N^2)O(N2)。

有多种方法可以实现上述以p为界的区间划分,下面以升序排序为例介绍一种较为常用的方法:

  1. 新建两个指针,分别指向区间的左右两端。并取区间左端的值为基准数p(此时视为将p抽离原区间,区间最左端为空)。

  2. 右指针左移,直到找到比p小的数,然后将该数填充至左指针指向位置(也就是区间最左端空置的位置)。

  3. 左指针右移,直到找到比p大的数,然后将该数填充至右指针指向位置(原来右指针的指向的值在步骤2中被移动到区间最左端,此时其指向的位置也可以视为空置)。

  4. 重复步骤2、3,直到两指针相交或越界,此时将p放置于左指针所指位置。

  5. 遍历完整个区间后,对p这单个元素的排序已完成,p此时被放置到未来数组有序时p应该处于的位置。在p前面的数都比它小,在p后面的数都比它大,此时开始分治递归p之前的区间和p之后的区间,重复1至5步。

代码

void QuickSort(int* a, int lef, int rig){if (lef >= rig)return;int p = a[lef], i = lef, j = rig;while (i < j) {  while (i=p)j--;a[i] = a[j];  while (i



快速排序稳定化改造

上述方法可较快地实现以p为界的区间划分,但无法保证排序的稳定性。下面介绍一种稳定化的快速排序方法:

对于给定的区间,确定基准数p后,新建两个数组a1和a2,其中a1用于存储区间中所有比p小的数,a2存储所有比p大的数,对于原区间中与p相等的数,若其位置在p之前,则按位置顺序先后存入a1,若位置在p之后,则按位置顺序先后存入a2。然后按a1, p, a2的顺序将三者覆盖回原来的区间,之后同样用分治策略递归排序a1部分和a2部分。

void QuickSort(int* a, int lef, int rig){if (lef >= rig) return;int n = rig-lef+1;int a1[n], a2[n], n1 = 0, n2 = 0;int mid = lef+(rig-lef)/2;int p = a[mid];for (int i=lef; i<=rig; i++) if (i != mid) {if (a[i]p) a2[n2++] = a[i];else {if (i



Quick Select算法

一种用于从无序数组中找第k大(小)元素的算法。由于快速排序中,对区间扫描后,基准数会被放置到正确的位置,其前面的数都比它小,后面的数都比它大,基于该性质,Quick Select的算法步骤如下:(假设要找第k小的元素)

  1. 和快速排序一样,在给定区间中确定基准数p,并以同样的方式扫描区间并移动元素,令p前面的数都比它小,在p后面的数都比它大。

  2. 假设此时p前面有n1个元素,p之后有n2个元素,如果n1=k-1,说明基准数即为目标;如果n1>k-1,则说明目标元素在p之前,因此重复1、2两步,在前n1个元素中递归寻找第k小元素;如果n1

该算法平均时间复杂度O(N)O(N)O(N),最坏O(N×logN)O(N\times log N)O(N×logN)。

int QuickSelect(int* a, int lef, int rig, int k){int p = a[lef], i = lef, j = rig;while (i < j) {  while (i=p)j--;a[i] = a[j];  while (i k-1)return QuickSelect(a, lef, i-1, k);return QuickSelect(a, i+1, rig, k-n1-1);
}



参考资料

稳定版快速排序算法

Stable QuickSort

【算法】Quick Select

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...