快排序算法(下)

简介: 快排序算法(下)

最后一个数是5

大于5的区域的第一个数是6

6和5交换

image.png

5就不用动了 在数组中固定下来

这一个过程就是partition分层过程

再在小于等于5的区域上拿最后一个数重复此过程

大于5区域上拿最后一个数重复此过程

左侧递归下去

右侧递归下去

总能让左右2个区域都有序

在一个范围上总拿这个范围的最后一个数做划分

然后把最后一个数放到小于等于区域的最后一个位置

然后让小于等于区域做递归

让大于区域也做递归

因为每次都能排好一个数

所以总有整体都有序的时候

每个区域的最后一个值可能都不一样 上面是以5为例做的说明

快排2.0基于荷兰国旗


image.png

拿最后一个数做划分 比如是5

让前面的分三个区域 小于5 等于5 大于5区域

把5和大于5区域的第一个数做交换

等于5的区域就靠在一起了

整个数组就变成 等于5的区域在中间

大于5的区域在右边

等于5的区域就不用动了

在小于5的区域上做递归

在大于5的区域上做递归

每一次递归搞定的是一批等于划分值的数

所以总有有序的时候

快排2.0版本比1.0版本快一些

因为它一次搞定一批数

举例说明

原数组

image.png

小于5区域

等于5区域

大于5区域

最后一个元素5和大于区域的第一个元素6做交换

image.png

等于5的区域在整个数组中的位置固定了

接下来在左侧区域 4301上以最后一个元素1做划分重复该行为

image.png

0继续做递归是0

4 3区域 以3做划分

总有都变成有序的时候

在右侧区域 786上 以6做划分重复该行为

image.png

左侧和右侧做递归总有都排好的时候

快排1.0和2.0时间复杂度都是O(N^2)

拿最差的例子说明

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

以9做划分 没有右侧区域

只有左侧区域

划分的过程就是partition

partition过了9个数

在左侧区域拿8做划分 没有右侧区域

只有左侧区域

partion过了8个数

每次只搞定一个

所以等差数列

所以是O(N^2)的算法

最差情况原因只有一个 划分值打的很偏

先看什么时候是好情况

image.png

好情况是划分值打在几乎中间的位置

左侧递归的规模和右侧递归的规模都是差不多的

此时的master公式是

T(N)=2 T(N/2) + O(N)

除了调用递归之外(就是partition过程)的时间复杂度是O(N)

整体的时间复杂度是 O(N*LogN)

这种是最好的情况

划分值打偏就会逐渐退化成N^2的算法

image.png

左侧很小 右侧规模很大 最差情况就是没有左侧部分 只有右侧部分

或者 右侧很小 左侧规模很大 最差情况就是没有右侧部分 只有左侧部分

不管哪一种都是O(N^2)的算法

因为总是拿数组的最后一个位置做划分

所以差情况没法避免

可以人为构建差的例子

快排3.0

在数组L~R范围上

拿谁做划分

随机选择一个数

随机选了一个数之后 拿它和最后位置上的数做交换

然后拿这个新的最后位置的数做划分

既然是随机选的

好情况和差情况就是概率事件

随机选的可能是最坏的情况 事件复杂度是O(N^2)

也可能是1/5处


image.png

image.png

master公式是

T(N)=T(4/5)+T((1/5) * N)+O(N)

每一位置都是等概率事件

每一种情况都是1/N的权重

把所有的master公式做概率累加

再求数学期望 得到的结果是O(N logN)的算法

代码

image.png

第一步等概率随机选择一个位置

把它跟最右侧位置做交换

在L~R这个范围上 拿最后位置的数即选出来的这个随机数

做partition

返回一个数组 长度一定为2

指的是划分值等于区域的左右边界

image.png

原数组最后一个数是5

按照5进行partition划分

等于5的区域是下标12和13的位置

返回的这个数组就是[12,13]

表示划分值等于区域的左右边界

p[0]就是等于区域的左边界

p[0]-1 为小于区域的右边界

然后在小于区域上递归

p[1]是等于区域的右边界

p[1]+1是大于区域的第一个数的位置

在右侧范围上递归

image.png

相关文章
|
3月前
|
搜索推荐 索引
排序算法详解
本文介绍了多种排序算法,包括插入排序(如直接插入排序和希尔排序)、选择排序(如直接选择排序和堆排序)、交换排序(如冒泡排序和快速排序)以及归并排序和计数排序。插入排序通过构建有序序列逐步插入元素;选择排序通过不断选择最小元素放置于序列起始;交换排序通过元素间的交换达到排序目的;归并排序采用分治法将序列分解再合并;计数排序则通过统计元素出现次数来排序。文章详细阐述了各种排序算法的原理及其实现方法。
52 7
|
7月前
|
搜索推荐 算法 C语言
c排序算法
c排序算法
45 0
|
6月前
|
搜索推荐 算法 Python
排序算法1
排序算法1
|
6月前
|
搜索推荐 算法 Python
其他常见的排序算法
其他常见的排序算法
|
7月前
|
搜索推荐
常见的几种排序算法
常见的几种排序算法
63 1
|
7月前
|
搜索推荐
直接选择排序算法
直接选择排序算法
46 0
|
搜索推荐 C++
89 C++ - 常用排序算法
89 C++ - 常用排序算法
41 0
|
算法 搜索推荐 Java
TimSort——最快的排序算法
TimSort 算法是 Tim Peters 于 2001 年为 Python 语言创建的。该算法建立在插入排序和归并排序的基础之上,兼具插入排序和归并排序的优点。TimSort 的平均时间复杂度为 O(nlog(n)) ,最好情况 O(n) ,最差情况 O(nlog(n)) 。空间复杂度 O(n) ,是一个稳定的排序算法。
1623 0
TimSort——最快的排序算法
|
算法 搜索推荐 Java
常见排序算法详解(2)
(1) 算法过程 比较相邻的元素。如果第一个比第二个大(升序),就交换它们两个; 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,最后的元素应该会是最大的数;
100 0
|
算法 搜索推荐
排序算法的简单认识
在进行很多便捷算法之前总是要实现对象的有序化,而这就将使用到排序相关的算法,即使目前诸多高级语言已然完成对于排序算法的封装,用户只需导入对应库文件即可调用排序算法完成排序,无需手写排序算法,但具体的排序算法的选择就必须对于排序算法有所认识。本文就将介绍两个简单的排序算法:选择排序与冒泡排序。 选择排序 为什么称为选择排序? 该算法每次都是对于未排序的关键字进行比较,选择出最小或最大的关键字,再对其交换位置,实现一次排序,需进行多次比较。 选择排序法是一种不稳定的排序算法。它的工作原理是每一次从待排序的数据元
80 0