快速排序的原理及其实现(C++及Java版)浅析

快速排序原理

时间复杂度:O(nlog n),最坏情况下是n^2。值得一提的是对于所有基于比较的排序,其能取得的最好时间复杂度为O(nlog n),可以从数学上证明它。而不基于比较的排序(如桶排序),可以突破这个极限。

快速排序是一种不稳定的排序算法。

基于二分的思想,先随机选定一个基准数(比如最左边的),然后从一个指针从最右边找比基准数小的数,一个指针从最左边找比基准数大的数,然后两数交换位置,重复找并交换的过程,最终在两个指正相碰时,该位置就是基准数在最终排好序时的结果,将基准数和该位置上的数交换位置,即可。然后根据基准数的位置二分,在两边依次使用快速排序。

终止条件:划分到只有1或0个元素时即可终止。

为什么该位置是基准数在最终排好序时的位置

因为此时,该位置的右边都是小于或等于基准数的数,左边都是大于或等于基准数的数。观察如下排序前和排序后的数组:

4 2 4 5 3 1

1 2 4 3 4 5

对于已经排好序的数组中的每一个数,其左边的数都小于等于它,右边的数都大于等于它。

C++版

/*
快速排序
*/
#include <stdio.h>
using namespace std;
void swap(int &a, int &b){
  a ^= b;
  b ^= a;
  a ^= b;
} 
void quicksort(int *p, int left, int right){
  if(left >= right)return;
  int i = left, j = right, tmp = p[left];
  while(i < j){
    while(i < j && p[j] >= tmp)j--;
    while(i < j && p[i] <= tmp)i++;
    if(i != j){
      swap(p[i], p[j]);
    }
  }
  p[left] = p[i];
  p[i] = tmp;
  quicksort(p, left, i - 1);
  quicksort(p, i + 1, right);
}
void sort(int *p, int len){
  quicksort(p, 0, len - 1);
}
int main(){
  
}

Java版

import java.security.SecureRandom;
import java.util.Arrays;

class Scratch {
    public static void main(String[] args) {
        //测试代码
        int[] array = new int[14];
        SecureRandom secureRandom = new SecureRandom();
        for (int i = 0; i < array.length; i++) {
            array[i] = secureRandom.nextInt(15);
        }
        int[] cArray = array.clone();

        System.out.println("before");
        System.out.println(Arrays.toString(array));
        QuickSort.quickSort(array, 0, array.length - 1);
        System.out.println("after");
        System.out.println(Arrays.toString(array));

        System.out.println();
        System.out.println("final");
        Arrays.sort(cArray);
        System.out.println(Arrays.toString(cArray));
    }
}

class QuickSort {
    public static void swap(int[] array, int posA, int posB) {
        int t = array[posA];
        array[posA] = array[posB];
        array[posB] = t;
    }

    public static void quickSort(int[] array, int left, int right) {
        if (left >= right) {//也可left > right,但是效率更低。当只有1个及以下时就不需要再排序了
            return;
        }

        int i = left;
        int j = right;
        int tmp = array[left];//基准数
        while (i < j) {
            while (i < j && array[j] >= tmp) j--;//找比基准数小的,即:略过大于等于基准数的数
            while (i < j && array[i] <= tmp) i++;//找比基准数大的,即:略过小于等于基准数的数
            if (i != j) {
                swap(array, i, j);
            }
        }//跳出这个循环时,i=j,此时i代表基准数在最终排序结果中的位置

        swap(array, left, i);//此时(小于i的位置的数都小于等于基准数,大于i的位置的数都大于等于基准数)

        quickSort(array, left, i - 1);//二分,由于基准数已经有序,所以根据基准数划分成2半依次排序
        quickSort(array, i + 1, right);//二分
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章