递归与快速排序

Posted 南北技术笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与快速排序相关的知识,希望对你有一定的参考价值。




今天我们要说的是快速排序,快速排序也是使用了分治法的一个典型的算法,通过每次选取一个元素作为中间元素,将比这个元素小的放在元素的一侧,比中间元素大的放在另一侧,一直重复上述操作,直到中间元素的两侧都只有1个元素或者没有元素的时候,中间元素和两侧元素的一个组成就是有序的了。






1.排序原理

  • 选取一个元素作为中间元素(我们默认选取待排序序列的第一个元素),将待排序序列中比中间元素小的放在左侧,比中间序列大的放在右侧。

  • 一直重复第1步操作,将分割出的左右两个序列,继续按照第1步的原则进行分割,直到左侧或者右侧元素个数<=1,结束分割。

  • 合并左侧元素,中间元素,右侧元素为一个新的已排序序列。

  • 一直重复第3步操作,直到数据完全有序。


2.举例

待排序数组:[8,4,5,7,1,3,6,2]

  • 第一次分组,得到middle等于8,得到左子组[4,5,7,1,3,6,2]和右子组[]。

    • 判断左子组元素个数不<=1,继续对左子组进行分组,得到middle=4,得到左子组[1,3,2]和右子组[5,7,6]。

    • 左子组元素个数依然不为1,继续对左子组进行分组,得到middle=1,得到左子组[]和右子组[3,2],此时左子组元素个数<1,不再进行分组,对右子组[3,2]进行分组,得到middle=3,左子组[2]和右子组[]。

    • 对左子组[]、middle中间元素3、右子组[]进行合并得到[2,3]。

    • 对左子组[]、middle中间元素1、右子组[2,3]进行合并得到[1,2,3]。

    • 对右子组[5,7,6]进行分组,得到middle=5,左子组[]和右子组[7,6],左子组元素<1,不再进行分组。

    • 对右子组[7,6]进行分组,得到middle=7,左子组[6]和右子组[],此时左子组和右子组元素个数都<=1,不再进行分组。

    • 合并左子组[6]、middle中间元素7,右子组[]得到[6,7]。

    • 合并左子组[]、middle中间元素[5]、右子组[6,7]得到[5,6,7]。

    • 合并左子组[1,2,3]、middle中间元素4、右子组[5,6,7]得到[1,2,3,4,5,6,7]。

    • 合并左子组[1,2,3,4,5,6,7]、middle中间元素8、右子组[]得到[1,2,3,4,5,6,7,8]。



3.排序实现

<?php
function quickSort($arr){ //递归结束的条件 if (count($arr) <= 1) { return $arr; } $preset = $arr[0];//设定第一个数组的值为整个数组用来分界的分界值 $left = $right = [];
for ($i = 1; $i < count($arr); $i++) { if ($arr[$i] < $preset) { $left[] = $arr[$i]; } else { $right[] = $arr[$i]; } }
$left = quickSort($left); $right = quickSort($right); return array_merge($left, [$preset], $right);}
$arr = [8,4,5,7,1,3,6,2];print_r(quickSort($arr));


4.算法分析

   快速排序某种角度上和归并排序是类似的,都是将数组分割成一个个的小的序列,再对小的序列进行排序,不过和归并排序不同的点在于,归并排序是将两个小的序列在进行合并,合并的时候,会再进行排序操作,而对于快速排序来说,因为有个中间元素的设置,当两个小的序列时,归并排序中的合并操作就不需要了,因为这次需要合并完成的大的序列也就是有序的了。


5.时间复杂度分析

最坏情况下时间复杂度为O(n²)最好时间复杂度为O(nlogn)。平均时间复杂度为O(nlogn)。

快速排序时间复杂度推算比较复杂,数学较差,就不在这件事情上花时间了,有兴趣的可以参考这几篇文章了解下。

https://www.zhihu.com/question/22393997,(深巷明朝卖杏花的回答)

https://www.jianshu.com/p/45efd93fadae

    

6.快速排序的优缺点

    快速排序也是使用了分治思想的排序算法,但是相比归并排序来说,他在合并时不再需要对需要合并的序列进行排序,快速排序的主要操作都在分这个操作上,他在分的时候就做了判断,将小于中间元素的放在一侧,大于中间元素的放在另一侧。同样因为不再需要合并的时候对两个序列左排序操作,它也不需要重新申请额外的内存空间去处理,在空间复杂度上比归并排序要好。

    快速排序的缺点在于它是一种不稳定的排序,同时算法的复杂度依赖于分区元素的选择,如果不能很好的选择中间元素,算法的时间复杂度可能会降为O(n²)




递归与快速排序

点个 在看 你最好看



以上是关于递归与快速排序的主要内容,如果未能解决你的问题,请参考以下文章

快速排序:递归与非递归

算法设计与分析分治法--快速排序的递归和非递归实现

数据结构大量数据(20万)的快速排序的递归与非递归算法三数取中思想

排序2-冒泡排序与快速排序(递归加非递归讲解)

数据结构与算法(19)——快速排序

快速排序 递归与非递归