排序算法之——快速排序多方案实现

快速排序概述


快速排序是我们最常用的一种排序方法之一,它使用了分治思想。快速排序是对冒泡排序的一种改进。

原理

  1. 通过一趟排序,将原数据分割为独立的2个部分,其中一部分的所有数据均比另一部分的所有数据小。
  2. 然后,再按照此方法对这两部分的数据进行快速排序,整个排序过程可以递归进行。
  3. 最终,整个数据编程有序序列。

复杂度

时间复杂度:最好情况是O(nlogn),最差情况是O(n²),它的平均时间复杂度为O(nlogn)。

快速排序的平均性能非常好,通常是实际排序应用中最好的选择。

空间复杂度:快速排序是一种原址排序,只需要一个很小的栈作为辅助空间,它的空间复杂度为O(logn),所以适合在数据集比较大的时候使用。

步骤

快速排序的三步分治过程:

  • 分解:数组A[s…e]被划分为2个子数组A[s…q-1]和A[q+1…e],使得A[s…q-1]中的每个元素都小于等于A[q],而A[q]也小于等于A[q+1…e]中的每个元素。其中计算下标q也是划分过程的一部分。
  • 解决:通过递归调用对子数组进行排序。
  • 合并:因为子数组都是原址排序,所以不需要合并操作。

快速排序的实现


这里介绍2个方案,我们来看。

方案一

public static void quickSort(int[] arr, int s, int e){
    if(s

方案一的具体实现逻辑请看注释,这里简单归纳一下:

  1. quickSort方法负责快速排序过程,参数为数组arr,数组起始元素位置s,数组结尾元素位置e。
  2. 当s
  3. 以数组尾部元素为主元,找出主元在一轮排序完成后的正确位置,这里执行方法partition来完成。
  4. 最后递归调用,对主元素左侧和右侧执行快速排序过程。
  5. partition中,以数组尾部元素为主元,i是小于主元的数组边界,通过一个for循环遍历,查找小于主元的值,依次添加到当前i+1的位置,并且扩展小于主元的数组边界i。循环结束后,将主元位置放在正确的地方,然后返回当前位置即可。

方案二

public static void quickSort(int[] arr, int s, int e){
    int i,j;//i为小于主元边界,j为大于主元的边界
    int base = arr[s];//主元(对比的基值)
    int t;//临时变量
    if(s>e){
        return;
    }
    i = s;
    j = e;
    while(i= arr[i]&&i

方案二中,思想和方案一是类似的,但是我们使用了2个标记为指针来指示小于主元边界和大于主元边界,最后执行递归完成排序过程。

总结


  1. 快速排序是我们最常用的一种排序方法之一,它使用了分治思想。快速排序是对冒泡排序的一种改进。
  2. 通过一趟排序,将原数据分割为独立的2个部分,其中一部分的所有数据均比另一部分的所有数据小。然后,再按照此方法对这两部分的数据进行快速排序,整个排序过程可以递归进行。最终,整个数据编程有序序列。
  3. 快速排序的时间复杂度:最好情况是O(nlogn),最差情况是O(n²),它的平均时间复杂度为O(nlogn)。
  4. 快速排序是一种原址排序,只需要一个很小的栈作为辅助空间,它的空间复杂度为O(logn),所以适合在数据集比较大的时候使用。
  5. 快速排序的平均性能非常好,通常是实际排序应用中最好的选择。
  6. 最后我们在实战中,使用了2种方式,实现了快速排序的过程。

你可能感兴趣的:(算法)