快速排序原理
时间复杂度: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);//二分
}
}