快速排序和三向切分的快速排序

前言

快速排序應該是應用最廣泛的排序算法了,它實現簡單,一般情況下比其他算法都要快。快速排序算法用到了遞歸的方法,它將數組的一個元素作爲參照物,然後小於該元素的數據放到該元素的左邊,大於該元素的數據放到該元素的右邊,再以相同的方法對左邊的數據和右邊的數據進行操作,最後實現整個數組的有序

1,快速排序

下面的代碼是普通的快速排序代碼
代碼:

import java.util.Scanner;

public class QuickSort {

	public static void Quick(int data[],int s,int t) {
		int i=s;
		int j=t;
		int temp;
		
		if(s<t) {
			temp=data[s];
			while(i!=j) {
				while(j>i && data[j]>temp) j--;
				data[i]=data[j];
				while(i<j && data[i]<temp) i++;
				data[j]=data[i];
			}
			data[i]=temp;
			Quick(data,s,i-1);
			Quick(data, i+1, t);
		}
	}
	
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		int num=s.nextInt();
		int data[] = new int[num];
		
		for(int i=0;i<num;i++) {
			data[i] = s.nextInt();
		}
		
		Quick(data,0,num-1);
		
		for(int i=0;i<num;i++) {
			System.out.print(data[i]+" ");
		}
	}
}

分析:
然後我在想該怎麼說呢
。。。
算了,直接寫一段排序過程更直接

  • 這裏我們輸入十個數,然後以第一個數也就是6爲參照元素temp,i 指向6,j 指向5
  • 第一次while循環,從 j 開始,此時 j 指向的5是小於temp的,所以 j 不變,將 j 指向的值5賦值給 i 所在的位置,然後此時i指向的值就是5了,5是小於temp的,所以i++,此時 i 指向8,大於temp,所以 i 不變,把 i 指向的值8賦值給 j 所在的位置,這樣第一次while循環就結束了,結果如第二行所示。
  • 後面還會有幾個while循環,和上面的操作都是一樣的,當 i==j 時,while循環結束,講temp賦值給 i 或者 j 所在的位置,這樣快速排序的第一步就完成了。
  • 此時 temp的左邊都是小於他的數,對它們也進行上面的操作,於是就有了Quick(data,s,i-1); 同樣的Quick(data, i+1, t);對右邊的數排序
    在這裏插入圖片描述

2,三向切分的快速排序

上面的快速排序確實很簡單,但是有一個問題,那就是如果數據有很多重複的元素,那麼上面的算法就會浪費很多時間對相同的元素進行排序,三向切分的快速排序是對快速排序的一種優化,適合處理含有重複元素的數據

public static void Quick2(int data[],int s,int t) {
		int i=s;
		int j=t;
		int k=s+1;
		int temp=data[s];
		
		if(t>s) {
			while(k<=j) {
				//change(int data[],int a,int b)
				//將數組下標爲a和b的元素互換
				if(data[k]<temp) change(data,i++,k++);
				else if(data[k]>temp) change(data,k,j--);
				else k++;
			}
			
			Quick2(data, s, i-1);
			Quick2(data, j+1, t);
		}
		
	}