排序算法 快速排序【详细步骤图解】

  • 快速排序
    • 主要思想
    • 图解
      • 第一轮分割序列
      • 第二轮分割序列 --- 左子序列
        • 小结
      • 第三轮分割序列 --- 右子序列
    • C++实现
    • 总结

快速排序

给定一个序列:22 33 49 47 33' 12 68 29

进行快速排序

主要思想

  • 从序列中,任选一个记录k作为轴值 pivot

    选择策略:

    • 第一个元素
    • 最后一个元素
    • 中间元素
    • 随机选择
  • 将剩余的元素,分割成 左子序列 L右子序列 R

  • L 中所有元素都 < k, R 中所有元素都 > k

  • 对 L 和 R递归进行快排,直到子序列中有 0 个 或者 1 个元素,退出

图解

初始数组:

选定47为轴值pivot

pivot与最后一个值29进行交换(pivot放到最后面

接下来,以pivot=47为界,分成左子序列 L和右子序列 R

47大的都放在右边,比47小的都放在左边(用的交换)

遍历数组

  • 两个指针leftright
  • left != right的时候
    • arr[left]的,小于等于pivot,且left < right的时候,left右移

      • 如果leftright未相遇,把left的值赋给right对应的值
      • arr[right] = arr[left]
      • left指针停止移动,轮到right移动
    • arr[right]的值,大于等于pivot,且right > left的时候,right左移
      • 如果leftright未相遇。把right的值赋给left对应的值
      • arr[left] = arr[right]
      • right指针停止移动,轮到left移动
  • 注意:轴值用pivot保存

第一轮分割序列


pivot=47和最后一个值互换

22 <= 47left向右移动

33 <= 47left向右移动

49 > 47,不满足arr[left] <= pivot

left的值赋给right

arr[right] = arr[left]

赋值过后,left不动,right向左移动

68 >= 47,right向左移动

12 < 47,不满足arr[right] >= pivot

right的值赋给left

arr[left] = arr[right]

赋值过后,right不动,left向右移动

29 < 47left向右移动

33' < 47left向右移动

向右移动后,left == right,退出循环

pivot赋给arr[left]

至此,第一轮分割序列完成

第二轮分割序列 — 左子序列

经过第一轮分割,47左边的是左子序列,右边是右子序列

第二轮对左子序列分割,选择中间值作为pivot

12和33'进行交换

22 > 12,不满足arr[left] <= pivot

arr[left]赋给arr[right]

arr[right] = arr[left]

赋值过后,left不动,right向左移动

29、33'、33都比12大,所以right一直移动到下图位置

33 > 12,right继续向左移动

此时right == left,终止循环

pivot赋给arr[left]

至此,左子序列1也分割完成了

小结

快排就是一个递归的过程,分割得到左子序列

再对左子序列进行快排分割,得到左子序列的左子序列…

处理完左边,再去处理右边的右子序列

第三轮分割序列 — 右子序列

右子序列只有47、68、49,选择48作为轴值 pivot

pivot和最后一个值交换

47、49都比pivot=68小,left一直向右移动,直到left == right

分割之后,只剩下左子序列:47、49

47、49,选49作为轴值,得到左子序列47

子序列只剩下一个元素47,就不必排序了,右边排序结束

结果:47、49、68

C++实现

选择中间的值作为轴值

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <stack>
#include <cmath>
#include <map>using namespace std;/**** @param arr   待分割的序列* @param left  左边界* @param right 右边界* @return      分割后轴值的位置*/template<class T>
int PartitionArr(vector<T>& arr, int left, int right) {T temp = arr[right];while (left != right) {while (arr[left] <= temp && left < right) {left++;}if (left < right) {arr[right] = arr[left];// 赋值后,left不动,right向左移right--;}while (arr[right] >= temp && right > left) {right--;}if (left < right) {arr[left] = arr[right];// 赋值后,right不动,left向右移left++;}}// 当left == right,把轴值放回left上arr[left] = temp;return left;
}/**** @param arr   待排序数组* @param left  左边界* @param right 右边界*/
template<class T>
void quickSort(vector<T>& arr, int left, int right) {// 子序列剩下0或1个元素,排序结束if (right <= left) {return;}//  选择数组中间作为轴值int pivot = (left + right) / 2;// 把轴值放到数组最后面swap(arr[right], arr[pivot]);// 分割后轴值的位置// 分割后,左边值 < 轴值 < 右边值pivot = PartitionArr(arr, left, right);quickSort(arr, left, pivot - 1);quickSort(arr, pivot + 1, right);
}int main() {vector<int> arr = { 22,33,49,47,33,12,68,29 };for (auto& i : arr) {cout << i << ' ';}cout << endl << endl;quickSort(arr, 0, arr.size() - 1);for (auto& i : arr) {cout << i << ' ';}cout << endl << endl;system("pause");return 0;
}

总结

  • 快排是不稳定的排序算法

    • 33 33'排序后可能变成33' 33
  • 时间复杂度:

    • 平均: O ( N l o g N ) O(Nlog_N) O(NlogN​)
    • 最差: O ( N 2 ) O(N^2) O(N2),退化为冒泡排序
  • 空间复杂度:

    • 递归调用消耗栈空间
    • 最优: O ( l o g N ) O(log_N) O(logN​)
    • 最差: O ( N ) O(N) O(N),退化为冒泡排序

如有错漏不实之处,欢迎补充纠正。

排序算法 快速排序【详细步骤图解】相关推荐

  1. 【图解算法】排序算法——快速排序

    简介 首先还是得简单的介绍一下快速排序这个算法. 快速排序(Quicksort),又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出.在平均状况下, ...

  2. 排序算法 | 快速排序,算法的图解、实现、复杂度和稳定性分析与优化

    今天讲解一下快速排序算法的原理以及实现.复杂度和稳定性分析与优化 目录 1 快速排序的原理 2 快速排序代码实现 3 复杂度和稳定性分析.优化 4 习题练习 1 快速排序的原理 快速排序是所有内部排序 ...

  3. 十大经典排序算法-快速排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  4. 排序算法 快速排序 python 0913

    排序算法 快速排序 python 0913 快速排序 思路 定义快排方法 接收参数:原始列表,起始位置,终止位置 判断是否符合快排条件,当起始下标与终止下标相等时,代表只有一个元素,无法排序,退出 一 ...

  5. mysql安装详细步骤图解:

    Mysql安装详细步骤图解: 分享是一种美(Sharing is a beauty) [本文转自http://blog.csdn.net/fanyunlei/article/details/21454 ...

  6. mysql安装详细步骤图解

    mysql安装详细步骤图解 本文转自http://blog.csdn.net/fanyunlei/article/details/21454645 别看图多,其实mysql的安装十分简单,一路next ...

  7. JavaScript的排序算法——快速排序

    排序算法(Sorting algorithm)是计算机科学最古老.最基本的课题之一.要想成为合格的程序员,就必须理解和掌握各种排序算法. 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排 ...

  8. 12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用

    0.前言 从这一部分开始直接切入我们计算机互联网笔试面试中的重头戏算法了,初始的想法是找一条主线,比如数据结构或者解题思路方法,将博主见过做过整理过的算法题逐个分析一遍(博主当年自己学算法就是用这种比 ...

  9. 【路径规划】Dijkstra算法——超详细原理图解

    Dijkstra算法详解 1. Dijkstra算法原理  1.1. 有向图的Dijkstra算法  1.2. 无向图和栅格网络的拓展   1.2.1. 无向图   1.2.2. 栅格网络 2. Di ...

最新文章

  1. 互联网1分钟 |0104
  2. linux如何卸载virtualbox,如何在Mac上卸载VirtualBox | MOS86
  3. 读者诉苦:Redis 宕机,数据丢了,老板要辞退我
  4. HTML在日期单元格添加小图片,如何给图片添加上文字、日期和自己名字的小水印呢?...
  5. STC学习:便携式温度采集器
  6. qq批量登录软件_QQ账号永久冻结
  7. 【2021亲测有效】彻底解决Google地球、Google Earth、谷歌地球启动无法连接到登录服务器、启动黑屏、无法查看历史影像图的方法
  8. 2019.4 sigfox EMC
  9. 打开html文件是文字模式,为什么我打开的有些网页成了全文字格式的?
  10. php5时区,PHP5 时区设置方法详解
  11. 云端虚拟机规格参数快速对比说明
  12. Maven下载及安装教程详解
  13. chroot用法详解
  14. 雨季花月,回忆似金。登轼高望,志在远方。【记妙妙的OI生涯】
  15. Swift实战-豆瓣电台(四)歌曲列表的展现
  16. antv G2 折线图遇到的坑
  17. EP10W2A02N05方向阀导压操作插装阀
  18. elasticsearch analysis模块 自定义分词 拼音分词 同义词 停词
  19. 里程计模型(1):两轮差分底盘和三轮全向底盘
  20. DL4J实战之三:经典卷积实例(LeNet-5)

热门文章

  1. Java 获取当前年 、当前月
  2. Android-自定义preference和PreferenceFragment实例详解
  3. Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks(理解)
  4. 2022最常用且好用的IDEA插件
  5. 从输入 URL 到浏览器接收的过程中发生了什么事情
  6. 1.2 Activity 的基本用法大全
  7. c语言中如何用sqar函数,简易函数信号发生器设计_毕业论文.doc
  8. STM32之蜂鸣器实验
  9. jdk 1.8安装教程
  10. VMware卸载重装心得