快速排序(Quick Sort)也是一种典型的交换排序算法,通过交换数据元素的位置进行排序。

一、算法基本思想

(1)基本思想

快速排序的基本思想就是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。快速排序采用了分治法来解决问题。

(2)运行过程

快速排序算法的运行过程如下::

1、从序列中挑出一个元素,称为“基准”(pivot)。一般是选取序列的第一个元素。

2、重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

4、直到序列的大小是0或1,也就是所有元素都已经被排序好了,递归结束。

(3)示例

1、一次快速排序过程

所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准的后面,最后找到基准元素的位置。

2、整个快速排序过程

二、算法实现(核心代码)

C++实现:

void swap(int *x, int *y) {int t = *x;*x = *y;*y = t;
}
void quick_sort_recursive(int arr[], int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(&arr[left], &arr[right]);}if (arr[left] >= arr[end])swap(&arr[left], &arr[end]);elseleft++;quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end);
}
void quick_sort(int arr[], int len) {quick_sort_recursive(arr, 0, len - 1);
}

Java实现:

class quick_sort {int[] arr;private void swap(int x, int y) {int temp = arr[x];arr[x] = arr[y];arr[y] = temp;}private void quick_sort_recursive(int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(left, right);}if (arr[left] >= arr[end])swap(left, end);elseleft++;quick_sort_recursive(start, left - 1);quick_sort_recursive(left + 1, end);}public void sort(int[] arrin) {arr = arrin;quick_sort_recursive(0, arr.length - 1);}
}

三、算法改进和变种

对于快速排序改进的方法,可以参考《大话数据结构这本书》。快速排序的优点在于,对于大量数据的时候,很容易将某个元素放到对应的位置。而快速排序的缺点也很明显:

一是如果原始数据就是有序的,那么快速排序过程中对序列的划分就十分不均匀,将序列分为了1和n-1的大小(而通常希望的最理想状态是二分);

二是对于小数组进行排序时,也需要递归进行几次才能将数据放到正确的位置;

三是排序快速是不稳定的,当重复数据很多时效率比较低。

针对快速排序的缺点,对于快速排序主要有以下三个改进方案:

(1)优化选取基准pivotkey — — 三数取中法

三数取中法的思想如下:选取序列左端、中间和右端三个数据元素,按大小进行排序,选择中间大小的元素作为基准。

(2)序列较小时使用插入排序代替快速排序

在递归过程,当排序的子序列小于预定的值M时,采用插入插入排序。

(3)重复元素较多使用三分区法

通过划分让相等的元素连续地摆放,然后只对左侧小于V的序列和右侧大于V对的序列进行排序。

如上图: 从左至右扫描数组,维护一个指针lt使得[lo…lt-1]中的元素都比v小,一个指针gt使得所有[gt+1….hi]的元素都大于v,以及一个指针i,使得所有[lt…i-1]的元素都和v相等。元素[i…gt]之间是还没有处理到的元素,i从lo开始,从左至右开始扫描:

1、如果a[i]<v::交换a[lt]和a[i],lt和i自增;

2、如果a[i]>v:交换a[i]和a[gt],,gt自减;

3、如果a[i]=v:i自增。

四、算法性能(时间复杂度、空间复杂度、稳定性分析)

快速排序是通常被认为在同数量级(O(nlog2n))的排序方法中平均性能最好的。

但若初始序列按关键字有序或基本有序时,快排序反而蜕化为冒泡排序,也就是说快速排序最坏情况下时间复杂度为O(n^2),空间复杂度为O(n)。

如果每次排序时所选的基准都能讲序列进行二分,那么此时的快速排序效果最好,也就是说快速排序在最好情况下的时间复杂度为O(nlogn),空间复杂度为O(logn)。

快速排序的平均时间复杂度为O(nlogn),空间复杂度为O(logn)。快速排序是一种不稳定的排序算法。

参考文献:

1、浅谈算法和数据结构: 四 快速排序 http://www.cnblogs.com/yangecnu/p/Introduce-Quick-Sort.html

2、快速排序算法及其改进算法实现 http://blog.csdn.net/lsjseu/article/details/9749587

3、快速排序及改进 http://flyingdutchman.iteye.com/blog/1863691

4、快速排序(2)算法改进--小的子文件、三者取中、重复关键字三路划分序及改进 https://www.zybuluo.com/quinn/note/78606

5、怎样让快速排序最快? http://blog.sina.com.cn/s/blog_4dff8712010136jh.html

经典排序算法(2)——快速排序算法详解相关推荐

  1. kmeans python interation flag_机器学习经典算法-logistic回归代码详解

    一.算法简要 我们希望有这么一种函数:接受输入然后预测出类别,这样用于分类.这里,用到了数学中的sigmoid函数,sigmoid函数的具体表达式和函数图象如下: 可以较为清楚的看到,当输入的x小于0 ...

  2. 操作系统:基于页面置换算法的缓存原理详解(下)

    概述: 在上一篇<操作系统:基于页面置换算法的缓存原理详解(上)>中,我们主要阐述了FIFO.LRU和Clock页面置换算法.接着上一篇说到的,本文也有三个核心算法要讲解.分别是LFU(L ...

  3. python实验原理_Python实现蒙特卡洛算法小实验过程详解

    蒙特卡洛算法思想 蒙特卡洛(Monte Carlo)法是一类随机算法的统称,提出者是大名鼎鼎的数学家冯·诺伊曼,他在20世纪40年代中期用驰名世界的赌城-摩纳哥的蒙特卡洛来命名这种方法. 通俗的解释一 ...

  4. 图解机器学习算法(6) | 决策树模型详解(机器学习通关指南·完结)

    作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/34 本文地址:https://www.showmeai.tech/article-d ...

  5. 天津理工大学《操作系统》实验二,存储器的分配与回收算法实现,代码详解,保姆式注释讲解

    天津理工大学<操作系统>实验二,存储器的分配与回收算法实现,代码详解,保姆式注释讲解 实验内容 1. 本实验是模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不 ...

  6. 用数据结构c语言写成绩排序,C语言数据结构 快速排序实例详解

    C语言数据结构 快速排序实例详解 一.快速排序简介 快速排序采用分治的思想,第一趟先将一串数字分为两部分,第一部分的数值都比第二部分要小,然后按照这种方法,依次对两边的数据进行排序. 二.代码实现 # ...

  7. Matlab中的FCM算法代码及中文详解

    Matlab中的FCM算法代码及中文详解 转自:http://xiaozu.renren.com/xiaozu/106512/336681453 function [center, U, obj_fc ...

  8. KMP算法之next数组详解

    KMP算法之next数组详解 KMP算法实现原理 KMP算法是一种非常高效的字符串匹配算法,下面我们来讲解一下KMP算如何高效的实现字符串匹配.我们假设如下主串和模式串: int i;//i表示主串的 ...

  9. SMART S7-200PLC流量累计算法实现(梯形图算法详解+优化)

    流量累计基于积分的原理,采用细分面积的方法近似计算瞬时流量的累加.离散上也就是累加求和.公式虽然简单但是流量累计仍有些需要注意的地方,下面一一和大家举例说明. 1.数值积分的通式 2.梯形积分公式 从 ...

  10. matlab中存档算法代码,Matlab中的FCM算法代码及中文详解

    Matlab中的FCM算法代码及中文详解 转自:http://xiaozu.renren.com/xiaozu/106512/336681453 function [center, U, obj_fc ...

最新文章

  1. 基于SSM的e律通管理系统
  2. windows10远程桌面连接及问题解决
  3. git提交输入密码_git提交到自己的服务器,每次都要输入密码
  4. GDCM:对dicom文件的简单Scanner的测试程序
  5. python——前端常用的标签
  6. java题库管理系统java试题管理系统java考试管理系统
  7. Unity中一个简单的显示FPS帧率小工具
  8. soem主站移植到rt thread smart操作系统
  9. 正在启动python的代码补全客户端_让 python 命令行也可以自动补全
  10. IsPostBack是什么意思,如何运用?
  11. recovery模式是什么意思?recovery模式怎么刷机?
  12. loss weight
  13. 如何实现业务流程集成
  14. 关于goole IO大会发布的android M和android studio1.3的更新
  15. DOS命令:assoc
  16. 科技业界10大最具争议成功决定:苹果iPhone
  17. 基于CAN总线步进电机驱动器设计
  18. android优化启动时间
  19. PMP证书备考攻略+PMP知识点汇总
  20. Android动态权限详解

热门文章

  1. Android之面试题精选,自己收藏下
  2. linux怎样测试tty,linux – 提示自定义:如何检测何时没有tty
  3. matlab的循环语句裁图,[MATLAB图像处理] 多幅图片处理的循环语句
  4. mysql分组查询和子查询语句_6.MySQL分组聚合查询,子查询
  5. 放寒假的硕博研究生将经历什么?
  6. 批作业是小学老师的一大乐趣 | 今日最佳
  7. 做题不如巧做题,初中数学题型解题技巧都在这!
  8. TensorFlow框架的这些操作你肯定不知道!
  9. 计算机表演赛新疆赛区,【图】第二十六届中国儿童青少年威盛中国芯HTC计算机表演赛“中国电信天翼杯”新疆赛区总决赛圆满结束_乌鲁木齐教育信息网...
  10. java if or android_RxJava switchIfEmpty操作符实现Android检查本地缓存逻辑判断