点击上方蓝色 “铁匠学编程” 关注我,让我们一起学习!

前天给大家分享了归并排序,但是它不是原地排序算法,需要消耗额外的内存空间,今天给大家分享的是江湖无人不知无人不晓的"快排"--快速排序。

快排是小生接触开发学会的第一个排序算法?

快速排序原理

快排也用到了分治思想。快排的核心思想是:如果要排序的数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为分区点 pivot。

我们遍历p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。经过这一步之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于 pivot 的,中间是 pivot ,后面的 q+1 到 r 之间都是大于 pivot 的。

如下图:

根据分治、递归的处理思想,我们可以用递归排序从下标 p 到 q-1 之间的数据和下标从 q+1 到 r 之间的数据,直到区间缩小为1,就说明所有的数据都有序了。快排不需要归并那样做合并,也不需要额外的存储空间,在时间复杂度一样的情况下有着比归并更好的空间复杂度表现。

快排首先找到分区点,一般我们会将数组第一个或最后一个元素作为 pivot,我们以最后一个作为分区点 pivot,然后通过两个变量 i 和 j 作为下标来循环数组,当下标 j 对应数据小于 pivot 时,交换 i 和 j 对应数据,并且将 i往前移动一位,否则 i 不动,下标 j 始终是往前移动的, j 到达终点后,将 pivot 与下标 i 对应数据交换,这样最终将 pivot 置于数组中间,[0...i-1]区间的数据都比 pivot 小,[i+1...j] 之间的数据都比 pivot 大,我们以递归的方式循环处理,最终整个数组都会变成有序的,如下图:

因为分区的过程涉及交换操作,如果数组中有两个相同的元素,比如序列 7, 9,5,7,3,6 经过第一次分区操作之后,两个 7的相对先后顺序会改变。所以,快速排序并不是一个稳定的排序算法。

代码示例

Go语言:

package mainimport "fmt"func main() {  arr := []int{8, 3, 4, 5, 9, 2, 1}  QuickSort(arr)  fmt.Println(arr)}func QuickSort(arr []int) {  separateSort(arr, 0, len(arr)-1)}func separateSort(arr []int, start, end int) {  if start > end {    return  }  i := partition(arr, start, end)  separateSort(arr, start, i-1)  separateSort(arr, i+1, end)}func partition(arr []int, start, end int) int {  pivot := arr[end]  var i = start  for j := start; j < end; j++ {    if arr[j] < pivot {      if !(i == j) {        arr[i], arr[j] = arr[j], arr[i]      }      i++    }  }  arr[i], arr[end] = arr[end], arr[i]  return i}

PHP示例:

function quick_sort($nums){    if (count($nums) <= 1) {        return $nums;    }    quick_sort_c($nums, 0, count($nums) - 1);    return $nums;}function quick_sort_c(&$nums, $p, $r){    if ($p >= $r) {        return;    }    $q = partition($nums, $p, $r);    quick_sort_c($nums, $p, $q - 1);    quick_sort_c($nums, $q + 1, $r);}// 寻找pivotfunction partition(&$nums, $p, $r){      $pivot = $nums[$r];    $i = $p;    for ($j = $p; $j < $r; $j++) {        // 原理:将比$pivot小的数丢到[$p...$i-1]中,剩下的[$i..$j]区间都是比$pivot大的        if ($nums[$j] < $pivot) {            $temp = $nums[$i];            $nums[$i] = $nums[$j];            $nums[$j] = $temp;            $i++;        }    }    // 最后将 $pivot 放到中间,并返回 $i    $temp = $nums[$i];    $nums[$i] = $pivot;    $nums[$r] = $temp;    return $i;  }  $nums = [4, 5, 6, 3, 2, 1];  $nums = quick_sort($nums);  print_r($nums);

JS示例:

const swap = (arr, i, j) => {    const temp = arr[i]    arr[i] = arr[j]    arr[j] = temp}// 获取 pivot 交换完后的indexconst partition = (arr, pivot, left, right) => {    const pivotVal = arr[pivot]    let startIndex = left    for (let i = left; i < right; i++) {        if (arr[i] < pivotVal) {            swap(arr, i, startIndex)            startIndex++        }    }    swap(arr, startIndex, pivot)    return startIndex}const quickSort = (arr, left, right) => {    if (left < right) {        let pivot = right        let partitionIndex = partition(arr, pivot, left, right)        quickSort(arr, left, partitionIndex - 1 < left ? left : partitionIndex - 1)        quickSort(arr, partitionIndex + 1 > right ? right : partitionIndex + 1, right)    }}

性能分析

最后我们看下快速排序的性能和稳定性:

  1. 时间复杂度:是O(nlogn),同样要优于冒泡和插入排序

  2. 空间复杂度:不需要额外的空间存放排序的数据,是原地排序

  3. 算法稳定性:涉及数据交换,可能破坏原来相等元素的位置排序,所以是不稳定的排序算法

加个关注吧!

加油!不仅自己~还有你~

快速排序算法_常用排序算法之快速排序相关推荐

  1. 快速排序算法_常用排序算法专题—快速排序

    黑客技术点击右侧关注,了解黑客的世界! Linux编程点击右侧关注,免费入门到精通! 程序员严选甄选正品好物,程序员生活指南! 作者丨就是彬彬呀https://www.jianshu.com/p/17 ...

  2. 冒泡和快速排序的时间复杂度_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  3. c++ 快速排序_常用排序算法之快速排序

    前天给大家分享了归并排序,但是它不是原地排序算法,需要消耗额外的内存空间,今天给大家分享的是江湖无人不知无人不晓的"快排"--快速排序. 快排是小生接触开发学会的第一个排序算法 快 ...

  4. 解释什么是快速排序算法?_解释排序算法

    解释什么是快速排序算法? Sorting algorithms are a set of instructions that take an array or list as an input and ...

  5. golang 排序_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  6. 选择排序算法流程图_常用排序算法之选择排序

    前两天给大家分享了冒泡排序和插入排序(没关注的同学,可以关注后查看历史消息),今天继续给大家分享另一种常用的排序算法--选择排序. 选择排序 选择排序和插入排序很相似,也区分已排序区间和未排序区间,选 ...

  7. python常见的排序算法_常见排序算法之python实现

    1. 冒泡排序 时间复杂度为O(n^2), 稳定的排序算法 思路:一开始比较的区间是[0,n-1],依次比较相邻两数,哪个数大哪个数就放在后面,这样一次遍历数组后,最大的数会在数组的最后一个位置,然后 ...

  8. java常见的排序算法_常见排序算法及Java实现

    先上个总图↓: ①.直接插入排序 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并 ...

  9. java实现apriori算法_各种排序算法的分析及java实现(一)

    阅读本文约需要7分钟 大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈).上次老师跟大家分享了下用Navicat for Mysql导入.sql文件的 ...

最新文章

  1. 只有 DBA 才能导入由其他 DBA 导出的文件
  2. centos7加固手册
  3. 根据文法画出语法树_几种常用的英语教学法误导了语法教学
  4. javaone_JavaOne和OOW 2015总结
  5. 千兆网综合布线系统的线缆选型
  6. ddos应急处理_当遇到DDOS攻击的几种应对措施
  7. 幽默度识别第一名解决方案代码及说明
  8. use makefile in wn10
  9. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第3节 综合案例_文件上传_5_综合案例_文件上传案例优化...
  10. [源]云计算技术堆栈系列——鸟瞰
  11. java jibx,JiBx:BindGen命令行--通过Java POJO对象产生bind.xml和xsd文件
  12. growup怎么读_growup_grow 和grow up 的区别
  13. HTML5期末大作业:商城网站设计——仿天猫商城(9页) HTML+CSS大作业: 网页制作作业_疫情防控网页设计...
  14. maven本地有包但是引不进来 已解决
  15. IntelliJ配置jenkins服务的Crumb Data
  16. Linux环境中第一行dpa,nvdimm
  17. 【Derivation】正态分布特征函数证明-X~N(a,sigma^2)
  18. chalk.js(node终端样式库)
  19. u盘数据恢复的原理_U盘格式化了怎么恢复数据?恢复原理和方法你了解吗
  20. php汉字转区位码,PHP里实现汉字转区位码的示例代码_php

热门文章

  1. C#基础知识整理:基础知识(5) 方法的重载
  2. VC6中根据需要显示滚动条
  3. 最全面详细讲解Oracle入门
  4. 【Linux学习】epoll详解
  5. ACE proactor example
  6. OpneCV3——使用SURF、SVM、BOW对图像进行分类
  7. 基于机器学习的捡球机器人设计与实现(探索)第6篇——另一种高效追踪网球思路
  8. PHP和OneNet平台交互
  9. (1110, “Column ‘arriveTime‘ specified twice“)
  10. 按键精灵文字识别插件_按键精灵——如何实现办公自由(二)