算法简介

快速排序(Quicksort)是对冒泡排序的一种改进算法。由C. A. R. Hoare在1960年提出。该算法使用广泛、效率很高,是最重要的排序算法之一。

该算法的实现基本可分为以下几步:

  1. 在数组中选一个基准数(通常为数组第一个)。
  2. 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边
  3. 对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序。

示例有一数组为4 1 8 3 7 5,依上面的思路排序过程为

  1. 选第一个基准元素

4 1 3 6 7 5

  1. 以基准元素为中心将数组分成两个子集

3 1 4 6 7 5

  1. 将两个子集重复以上操作,直到全部有序

1 3

5 6 7

  1. 得到有序的集合

1 3 4 5 6 7

以上是快速排序的基本思路,这里比较重要的是第2点,如何将一个数组以基准数为中心分为两部分呢?

快排是这样解决的,假设做正序排序:

在数组的头部和尾部分别设置一个哨兵,同时向对方走去。尾部的哨兵如发现有比基准数小的数,停下。头部的哨兵如发现有比基准数大的数,停下。交换两个数。再重新走重复前面的交换过程。直到两个哨兵相遇,交换基准数和尾哨兵。

有一数组为6 1 2 7 9 3 4 5 10 8,带着这样做为什么可以的态度来看一下演示。

  1. 6为基准数,设i,j为两哨兵,目前指向首尾两个数(加粗部分)。

    6 1 2 7 9 3 4 5 10 8

  2. 两哨兵分别走向对方,直到遇到交换条件,并做交换。

6 1 2 7 9 3 4 5 10 8
6 1 2 5 9 3 4 7 10 8

  1. 此时来观察交换后的队列,除去基准数,是不是哨兵走过的位置都已部分有序了呢? 左边1 2 5都比基准数小,右边7 10 8都比基准数大。

1 2 5 9 3 4 7 10 8

  1. 继续走直到相遇,基准数复位。

6 1 2 5 9 3 4 7 10 8
6 1 2 5 4 3 9 7 10 8
6 1 2 5 4 3 9 7 10 8
3 1 2 5 4 6 9 7 10 8

这样就完美地将一个数组以一个基准数为中心分为两个子集。然后重复这个过程即可实现快速排序。

有一点需特别注意:若以第一个元素为基准数(就如上面的示例),在哨兵互走过程需右边的哨兵先走。 原因很好理解,看上面过程解析就会明白:哨兵互走交换的过程就是不断排序的过程。若右边的哨兵先走,不管走多少次,最后相遇时的那个数是小于基准数的。这时与基准数交换,正好分为两个序列。可若是左边的先走,相遇在大于基准数上就不好办了。

算法实践

以java演示一遍

   public void quickSort(int[] arr, int low, int high) {// low,high 为每次处理数组时的首、尾元素索引//当low==high是表示该序列只有一个元素,不必排序了if (low >= high) {return;}// 选出哨兵元素和基准元素。这里左边的哨兵元素也是基准元素int i = low, j = high, base = arr[low];while (i < j) {//右边哨兵从后向前找while (arr[j] >= base && i < j) {j--;}//左边哨兵从前向后找while (arr[i] <= base && i < j) {i++;}swap(arr,i,j);  //交换元素}swap(arr,low,j);  //基准元素与右哨兵交换//递归调用,排序左子集合和右子集合quickSort(arr,low,j-1);  quickSort(arr,j+1,high);}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}

ForkJoinTask与快速排序

Fork/Join框架是Java7提供了的一个用于并行执行任务的框架。它可以充分利用多核CPU的优势,将一个大任务切割成多个足够小的任务并行执行(fork),等所有子任务执行完毕后合并结果(join),流程图类似下面:

图片来自文章聊聊并发(八)——Fork/Join框架介绍。

这样来看,fork/join的处理模式与quickSort算法
倒很相似,都是不断分割任务以进行处理。而事实上,两者都是分治算法的实践者。我们可以将上述排序改成并发版的快速排序。

class SortTask extends RecursiveAction{private int[] arr;private int low;private int high;public SortTask(int[] arr,int low,int high) {this.arr = arr;this.high = high;this.low = low;}@Overrideprotected void compute() {if(low<high){int i=low,j=high,base = arr[low];while (i<j){while (arr[j]>=base&& i<j){j--;}while (arr[i] <= base && i < j) {i++;}swap(arr,i,j);}swap(arr,low,j);SortTask leftTask =new SortTask(arr,low,j-1);SortTask rightTask =new SortTask(arr,j+1,high);//分割成子任务并执行,join()方法会再次调用compute()方法。leftTask.fork();rightTask.fork();leftTask.join();leftTask.join();}}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}
}

测试结果

    @Testpublic  void test()throws Exception {ForkJoinPool forkJoinPool = new ForkJoinPool();int[] arr = {4, 1, 8, 6, 7, 9, 3, 2};SortTask sortTask = new SortTask(arr,0,arr.length-1);ForkJoinTask<Void> task =  forkJoinPool.submit(sortTask);task.get();Arrays.stream(arr).forEach(e->System.out.print(e+" "));// 1 2 3 4 6 7 8 9}

快速排序(QuickSort)算法介绍相关推荐

  1. 快速排序(quicksort)算法实现

     快速排序(quicksort)是分治法的典型例子,它的主要思想是将一个待排序的数组以数组的某一个元素X为轴,使这个轴的左侧元素都比X大,而右侧元素都比X小(从大到小排序).然后以这个X在变换后数组的 ...

  2. 快速排序quicksort算法优化

    1.基本想想 快速排序使用分治的思想 通过一趟排序将待排序列分割成两部分,其中一部分所有元素均比基准大,另一部分均比基准小 分别对这两部分元素继续进行排序,以达到整个序列有序 2.快排的步骤 1.选择 ...

  3. 快速排序quicksort算法细节优化(一次申请内存/无额外内存排序)

    文章目录 1.只申请一次内存,避免多次递归调用时反复的申请和释放内存,提高程序运行效率 2.不申请内存,在原数组上直接排序 优化比较总结 对链接中快速排序进行代码优化 https://blog.csd ...

  4. quicksort算法_QuickSort算法–用C,Java,Python实现

    quicksort算法 介绍 (Introduction) Quicksort algorithm is one of the fastest internal sorting algorithms ...

  5. 理解快速排序 | 打通算法学习的任督二脉

    本文作者胡光 前百度高级算法研发工程师,ACM 国际大学生程序设计大赛亚洲区金牌获得者 具体内容来自他在极客时间开设的免费公开课<常用算法 25 讲> 排序算法在工作中最常用,也是学习很多 ...

  6. 反汇编算法介绍和应用——递归下降算法分析

    上一篇博文我介绍了Windbg使用的线性扫描(linear sweep)反汇编算法.本文我将介绍IDA使用的递归下降(recursive descent)反汇编算法.(转载请指明来源于breaksof ...

  7. 改进型 clock 页面置换算法实现_ID生成算法雪花算法介绍及实现

    1. SnowFlake 算法介绍 雪花算法是由 Twitter 公司开源的可在分布式系统中产生一个全局唯一 ID 的算法.最初 Twitter 把存储系统从 MySQL 迁移到 Cassandra, ...

  8. 五子棋html游戏代码与算法介绍

    五子棋html游戏代码与算法介绍 运行图片 目录路径 五子棋.html 五子棋算法 进行下一个游戏的开发! 注意事项 我会把html文件.css文件提供下载地址,文件夹路径也展示给大家.但是图片就没法 ...

  9. HTML五子棋游戏代码介绍,五子棋html游戏代码与算法介绍

    五子棋html游戏代码与算法介绍 我会把html文件.css文件提供下载地址,文件夹路径也展示给大家.但是图片就没法一一放在博客里面了. 大家有需要的话,加博主QQ:2864144286,全天在线. ...

最新文章

  1. 编程有多可怕 | 每日趣闻
  2. linux sheet脚本去掉m,linux下的文本dos格式转unix格式,去除^M符号
  3. 《深入剖析Tomcat》一2.2 应用程序 1
  4. elasticsearch 索引存储深入详解
  5. 【Linux】一步一步学Linux——talk命令(238)
  6. react table里跳转页面_react路由配置基础篇:react-router4.0及以上
  7. BootStrap笔记-Model(模式对话框)样式修改
  8. ★☆★cf D. Petya and Array
  9. mysql中索引创建 查看和删除语句_MySQL如何创建和删除索引?
  10. 如果数组最后一项为空删除最后一项和去前面的逗号_手写数组方法
  11. [Springboot]SpringCache + Redis实现数据缓存
  12. IDEA下项目打包成jar,并通过cmd命令调用
  13. 跟“网址”有关的$_SERVER[ ]变量
  14. STM8S 低功耗(1)
  15. linux下QQ配置文件路径,Linux下QQ的使用并手动设置QQ文件保存路径
  16. 转载_tolua之wrap文件的原理与使用_写的非常好!
  17. Windows 7精简版(2019.04.10)
  18. Linux(Ubuntu)中对音频批量转换格式MP3转WAV/PCM转WAV
  19. 计算机房应配置灭火器,下列哪种灭火器配置是正确的?
  20. walking与Matlab入门教程-控制walking机器人移动

热门文章

  1. Java 10块钱 换 1元和0.5元
  2. SRPG游戏开发(四十)第九章 战斗系统 - 二 计算战斗数据(Calculate Combat Data)
  3. 第十三届蓝桥杯大赛软件类决赛Java大学B组C题——左移右移
  4. 【微信小程序】基于SpringBoot开发后端
  5. Java8和Java1.8
  6. Linux离线安装Kafka(超级精简亲测安装)
  7. 来看看移动端小程序技术的前世今生!小白也能看明白
  8. Windows 下编译使用 TCMalloc
  9. 记录一下 KVM服务器的bbr加速
  10. 网络协议-补充(笔记)