快排序算法(下)

简介: 快排序算法(下)

最后一个数是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

相关文章
|
7月前
|
搜索推荐 C++
7大排序算法C++实现
7大排序算法C++实现
72 0
|
3月前
|
搜索推荐 索引
排序算法详解
本文介绍了多种排序算法,包括插入排序(如直接插入排序和希尔排序)、选择排序(如直接选择排序和堆排序)、交换排序(如冒泡排序和快速排序)以及归并排序和计数排序。插入排序通过构建有序序列逐步插入元素;选择排序通过不断选择最小元素放置于序列起始;交换排序通过元素间的交换达到排序目的;归并排序采用分治法将序列分解再合并;计数排序则通过统计元素出现次数来排序。文章详细阐述了各种排序算法的原理及其实现方法。
49 6
|
2月前
|
搜索推荐 Java Go
深入了解选择排序算法
深入了解选择排序算法
30 4
|
7月前
|
存储 搜索推荐 算法
常见排序算法实现(一)
常见排序算法实现(一)
80 0
|
搜索推荐 算法
|
算法 搜索推荐 C++
|
搜索推荐 程序员 C语言
常见的排序算法(上)
时间如流水,今天就到初阶数据结构最后一个知识章节了,常见的排序算法!在进入这期之前,程爱打篮球的程序猿想说一句,如果有不懂的地方可以反复观看我之前的内容,再还有不懂可以直接找我,帮你安排的妥妥的!
常见的排序算法(上)
|
存储 算法 搜索推荐
【C++】常见的几种排序算法
【C++】常见的几种排序算法
73 0
|
搜索推荐
带你了解排序算法
带你了解排序算法
139 0
带你了解排序算法
|
搜索推荐 Java
常用排序算法总结
在计算器科学与数学中,一个排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定排序方式进行排列的一种算法。本文将总结几类常用的排序算法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序,分别使用Java代码实现,简要使用图例方式介绍其实现原理。
6794 0

热门文章

最新文章