经典排序算法(2)——快速排序算法详解


快速排序(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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经典排序算法(3)——直接插入排序算法详解

直接插入排序&#xff08;Insertion Sort&#xff09;是一种插入排序算法&#xff0c;通过不断地将数据元素插入到合适的位置进行排序。 一、算法基本思想 &#xff08;1&#xff09;基本思想 直接插入排序的基本思想是&#xff1a;顺序地把待排序的序列中的各个元素按其关键字…

[ASP.NET Core 3框架揭秘] 异步线程无法使用IServiceProvider?

标题反映的是上周五一个同事咨询我的问题&#xff0c;我觉得这是一个很好的问题。这个问题有助于我们深入理解依赖注入框架在ASP.NET Core中的应用&#xff0c;以及服务实例的生命周期。一、问题重现我们通过一个简单的实例来模拟该同事遇到的问题。我们采用极简的方式创建了如…

经典排序算法(4)——折半插入排序算法详解

折半插入排序&#xff08;Binary Insertion Sort&#xff09;是一种插入排序算法&#xff0c;通过不断地将数据元素插入到合适的位置进行排序&#xff0c;在寻找插入点时采用了折半查找。 一、算法基本思想 &#xff08;1&#xff09;基本思想 折半插入排序的基本思想是&#x…

经典排序算法(5)——希尔排序算法详解

希尔排序&#xff08;Shell Sort&#xff09;是一种典型的插入排序算法&#xff0c;通过对原始序列进行分组进行排序。 一、算法基本思想 &#xff08;1&#xff09;基本思想 希尔排序是基于插入排序的以下两点性质而提出改进方法的&#xff1a; 插入排序在对几乎已经排好序的…

程序员修神之路--容器技术为什么会这么流行(记得去抽奖)

菜菜哥&#xff0c;你上次讲的kubernetes我研究了一下&#xff0c;你再给我讲讲docker呗docker可很流行呀kubernetes是容器编排技术&#xff0c;容器不就是指的docker吗&#xff1f;docker可不等于容器哦&#xff0c;docker只算是容器的一种吧&#xff0c;算了容器的典型代表容…

经典排序算法(6)——直接选择排序算法详解

直接选择排序&#xff08;Straight Select Sort&#xff09;是一种典型的选择排序算法&#xff0c;通过不断选择序列中最大&#xff08;小&#xff09;的元素。 一、算法基本思想 &#xff08;1&#xff09;基本思想 直接选择排序的基本思想就是&#xff1a;不断从未排序队列中…

一篇文章看懂Git是什么以及如何简单的上手Git

本文来自DotNET技术圈作者&#xff1a;显杰1.Git是什么Git是目前世界上最先进的分布式版本控制系统什么是版本控制系统&#xff1f;好比设计师从开始设计第一个版本的设计稿开始&#xff1a;Demo > Demo1 > Demo2 > ... >Demo1001 > Demo最终版本 > Demo最终…

[翻译] 使用 Serverless 和 .NET Core 构建飞速发展的架构

作者&#xff1a;Samuele RescaServerless 技术为开发人员提供了一种快速而独立的方式将实现投入生产。这种技术在企业的技术栈中日益流行&#xff0c;自 2017 年以来&#xff0c;它一直是 ThoughtWorks 技术雷达的实验级别的技术[译注&#xff1a;技术雷达是 ThoughtWorks 每半…

经典排序算法(7)——堆排序算法详解

堆排序&#xff08;Heap sort&#xff09;是指利用堆&#xff08;最大堆、最小堆&#xff09;这种数据结构所设计的一种排序算法。堆是一个完全二叉树的结构&#xff0c;并同时满足如下性质&#xff1a;即子结点的键值或索引总是小于&#xff08;或者大于&#xff09;它的父节点…

经典排序算法(8)——归并排序算法详解

归并排序&#xff08;Merge sort&#xff09;&#xff0c;是创建在归并操作上的一种有效的排序算法&#xff0c;效率为O(nlog n)。该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用&#xff0c;且各层分治递归可以同时进行。 一、算法基本思…

祝贺王远当选为中国区第二位 Teams MVP

今天一上班就传来喜讯&#xff0c;Microsoft Teams 大中华区技术社区专家委员会成员之一的王远成功当选了2020-2021年度微软最有价值专家&#xff08;MVP)&#xff0c;这是对他在基于Office 365的音视频会议系统&#xff08;尤其是在Microsoft Teams&#xff09;方面的深入研究…

经典排序算法(9)——桶排序算法详解

桶排序&#xff08;Bucket sort&#xff09;或所谓的箱排序&#xff0c;并不是比较排序&#xff0c;它不受到 O(nlogn) 下限的影响。 一、算法基本思想 &#xff08;1&#xff09;基本思想 桶排序工作的原理是将数组分到有限数量的桶子里&#xff0c;每个桶子再个别排序&#x…

[原]排错实战——使用process explorer替换任务管理器

前言 一般&#xff0c;我们会使用任务管理器查看系统中有哪些进程在运行&#xff0c;强制杀掉某个进程。可是系统自带的任务管理器功能有限&#xff0c;process explorer是一个功能更强大的工具。它可以让我们查看更多更详细的信息&#xff08; 比如查看某个进程的父进程&#…

ABP vNext中使用开源日志面板 LogDashboard

ABP vNext 使用 logdashboard本文示例源码&#xff1a;https://github.com/liangshiw/LogDashboard/tree/master/samples/abpvnextABPABP是aspnetcore3.0的开源web应用程序框架&#xff0c;非常适合现代web应用程序。有关ABP的更多内容可以查看官方文档Logdashboard可以直接在基…

经典排序算法(10)——基数排序算法详解

基数排序&#xff08;Radix sort&#xff09;是一种非比较型整数排序算法&#xff0c;其原理是将整数按位数切割成不同的数字&#xff0c;然后按每个位数分别比较。 一、算法基本思想 &#xff08;1&#xff09;基本思想 基数排序是基于桶排序来实现。通过键值的部分信息&#…

经典排序算法(11)——计数排序算法详解

计数排序&#xff08;Counting sort&#xff09;是一个非基于比较的排序算法&#xff0c;该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时&#xff0c;它的复杂度为Ο(nk)&#xff08;其中k是整数的范围&#xff09;&#xff0c;快于任何比较…

GitHub Actions,卧槽!牛批!

“ 阅读本文大概需要 19 分钟。 ”前段时间我更新了我的分布式爬虫管理框架—— Gerapy&#xff08;话都说到这儿了打个广告&#xff0c;跟繁琐的命令行说拜拜&#xff01;Gerapy分布式爬虫管理框架来袭&#xff01;&#xff0c;哇&#xff0c;哇&#xff0c;就是&#xff0c;哇…

平衡二叉树AVL详解

一、平衡二叉树的定义 平衡二叉树&#xff08;Balanced Binary Tree&#xff09;又被称为AVL树&#xff0c;它且具有以下性质&#xff1a; &#xff08;1&#xff09;它是一棵空树或它的左右两个子树的高度差的绝对值不超过1&#xff1b; &#xff08;2&#xff09;并且左右两个…

【壹个小技巧】一看就会的CI/CD :Github Actions

什么是 CI/CD?我这里先不说概念&#xff0c;先说一个平时开发的场景问题&#xff1a;我们平时开发一个项目&#xff0c;经常会遇到这些“小”问题&#xff1a;就是如何保证自己的项目是正确的&#xff0c;至少拿给别人的时候&#xff0c;可以编译运行的&#xff1f;或者说多人…

Hyper-V虚拟机自动添加检查点和导出备份

背景说明笔者使用Hyper-V在内部搭建了大量的环境和系统&#xff0c;比如&#xff1a;k8s内部集群Azure Devops Server(TFS>VSTS>Azure Devops Server)SharePoint…大部分基本上都是用于内部研究、测试等场景&#xff0c;但是为了避免很多麻烦&#xff0c;必要的备份还是必…