快速排序算法

快速排序思想:

先把數列的最後一個數挑選出來,作爲一種中間值,然後分別從數列的兩端向中間靠近,從左向右遍歷時,遇到比中間值大的數則把這個數的索引leftPtr先下來,然後再從右往左遍歷,遇到比中間值小的數,就把這個數的索引rightPtr也記錄下來,最後讓leftPtr和rightPtr出的數交換,然後再分別從兩端接着遍歷,按照這個交換規則,最終可以讓所以比中間值小的數放到數列的左邊,所有比中間值大的數都放在右邊,然後再把這個中間值(也就是數列的最後一個數)與中間位置上的數(索引爲 數組長度/2 的數)交換這樣這一層排序算是完成。當然快速排序也稱爲分段排序,所以,在這一層排序完之後,會把左右兩端的數從中間分開看作是兩個子數列,然後再分別對兩個子數列按照如上規則進行排序,然後兩個子數列要再分成更短的兩個數列,就這樣不停的分下去最後知道它們不可分位置。最終從整體到局部形成一個順序的數列。

/**
	 * 快速分段排序  準備階段
	 * @param arr 
	 * @param left 表示這個子數列在這個數列的開始位置索引
	 * @param right 表示這個子數列在這個數列的結束位置索引
	 * @param point 中間數索引
	 * @return
	 */
	public static int partition(int[] arr,int left,int right,int point){
		int leftPtr=left-1;
		int rightPtr=right;
		while(true){
			/**
			 * 數組先從左向右遍歷,如果left>right則停止遍歷,如果在左邊
			 * 遇到比關鍵數大的數,就停止,並記錄當前遍歷的到數leftPtr,然後
			 * 進行從右往左遍歷,如果left>right則停止遍歷,如果在右邊遇到比
			 * 關鍵數小的數就停止,並記錄當前遍歷到額數rightPtr,這時兩個遍
			 * 歷都完成後,將leftPtr與rightPtr處的數進行交換,這樣就可以
			 * 不斷將較大的數放在關鍵數右邊,將較小的數放在關鍵數左邊。
			 */
			while(leftPtr<rightPtr&&arr[++leftPtr]<point);
			while(leftPtr<rightPtr&&arr[--rightPtr]>point);			
			if(leftPtr>=rightPtr){
				break;
			}else{
				int temp;
				temp=arr[leftPtr];//交換數據
				arr[leftPtr]=arr[rightPtr];
				arr[rightPtr]=temp;
			}
			
		
		}
		/**
		 *一次分段排序後,關鍵數左與左右兩邊的數順序已經排好,這時,就可以把在
		 *最右邊的數(關鍵數),放在中間,與左右形成正確的順序,然後把中間那個
		 *數換到最右邊,進行下一次分段排序。
		*/	
		int temp=arr[leftPtr];
		arr[leftPtr]=arr[right];
		arr[right]=temp;
		return leftPtr;
	}
	
	/**
	 * 快速排序法(分段)
	 * @param arr
	 * @param left
	 * @param right
	 */
	public static void sort(int[] arr,int left,int right){
		if(left>right){
			return;
		}
		int point=arr[right];//始終把最右端的的數挑出來當作中間數
		int partition=partition(arr,left,right,point);//返回交換後的中間數索引
		sort(arr,left, partition-1);//對左端進行排序
		sort(arr,partition+1, right);//對右端進行排序
	}
	
	public static void main(String[] args) {
		int[] m={2,11,2,5,7,0,3,-1,8,4,6,12};
		sort(m,0,m.length-1);
		for(int i=0;i<m.length;i++){
			System.out.print(m[i]+" ");
		}
	}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章