算法——分治和快速排序

Posted 代码综合征

tags:

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

分治也是一种递归式问题解决方法。快速排序是使用分治法的一种排序算法。

分治

分治一般有两个步骤:找出基线条件,不断将问题分解,直到符合基线条件。

例子:比如计算数组[2,4,6]中所有元素的和,可以使用循环,也可以使用分治递归。

接受一个列表,如果列表为空,就返回0.

否则,计算列表中除第一个数字外的其他数字的综合,将其与第一个数字相加,再返回结果。

设计数组的递归函数,基线条件通常是数组为空或只包含一个元素。

快速排序

快速排序的原理:

首先从数组中选择一个元素,这个元素被称为基准值。

接下来找出比基准值小的元素以及比基准值大的元素,这被称为分区。

得到了一个由所有小于基准值的数字组成的子数组,一个由所有大于基准值的数字组成的子数组,以及基准值。

再对子数组进行同样的分组排序的操作,最后组合起来就是有序的数组。

下面是快速排序的代码:

 
   
   
 
  1. def quicksort(array):

  2.    if len(array) < 2:

  3.        return array

  4.    else:

  5.        pivot = array[0]

  6.        less = [i for i in array[1:] if i <= pivot]

  7.        greater = [i for i in array[1:] if i > pivot]

  8.        return quicksort(less) + [pivot] + quicksort(greater)

  9. print quicksort([10, 5, 2, 3])

关于复杂度

实际上函数O(n)表示运行时间是c*n,c是算法所需的固定时间量。

比如对于简单查找和二分查找来说,简单查找的运行时间是 10ms*n,而二分查找的运行时间是 1s*log n

虽然看起来是简单查找的时间常量小,单数如果n非常大的情况下,二分查找的速度几乎没有变化,比简单查找快得多。

每个算法的复杂度都有个平均情况和最糟情况。比如针对快速排序,基准值的选择对复杂度的影响就很大。

如果基准值选择一直选择第一个的话,调用栈非常长,但是如果每次都选择中间那个的话,调用栈可以很短。

在最糟情况下,栈长为O(n),而在最佳情况下,栈长为O(log n)。而每一层所需时间为O(n)。

在最佳情况下,整个算法需要的时间为O(n) * O(log n) = O(n log n)。在最糟情况下,该算法的运行时间为O(n) * O(n) = O(n2)。

小结

  • 分治将问题逐步分解。使用分治处理列表时,基线条件很可能是空数组或只包含一个元 素的数组。

  • 实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。

  • 大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。

  • 比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n) 快得多。


以上是关于算法——分治和快速排序的主要内容,如果未能解决你的问题,请参考以下文章

分治算法-归并排序快速排序

算法学习---分治法和快速排序

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

算法--排序--分治与快速排序

分治算法的完美使用----归并排序

归并排序和快速排序(算法系列)