1. 程式人生 > >劍指offer——快速排序

劍指offer——快速排序

        快速排序是目前所有排序中效能較好的一種演算法,最好情況和平均情況下時間複雜度均為O(nlogn),最壞的情況下時間複雜度為O(n^2)。快速排序採用遞迴,用空間換取時間。由於使用了遞迴,因此需要額外的儲存空間。

快速排序由三個函式構成,分別為QuickSort(int[] arr)、QuickSort(int[] arr,int start,int end)、partition(int[] arr,int start,int end)。其中partition函式能夠從當前待排序序列中找出一個主元,並使得主元左側的元素均小於主元,主元右側的元素均大於主元。Partition函式完成對待排序序列的分割後,交給QuickSort(int[] arr,int start,int end)處理,QuickSort分別將被Partition分隔的兩個子序列進行快速排序。QuickSort(int[] arr)是整個快速排序的入口函式,使用者只需傳入待排序陣列即可。

下面為java實現的快速排序,若有bug歡迎拍版

/**
 * 實現快速排序 
 * @author chibozhou
 */
public class QuickSort {
	
	/**
	 * 本函式實現一趟快速排序,以陣列的第一個元素為主元,
	 * 本函式執行結束後使得主元左側的元素小於主元,主元右側的元素大於主元。
	 * @param arr 待排序的陣列
	 * @return 返回經一趟排序後主元的下標
	 */
	private static int partition(int[] arr,int start,int end){
		//健壯性判斷
		if(arr.length<=0){
			System.out.println("陣列為空!");
			return -1;
		}
		if(start<0 || end<0 || start>end){
			System.out.println("start、end非法!");
			return -1;
		}
		
		//i指向陣列頭、j指向陣列尾
		int i=start+1,j=end;
		//選擇陣列第一位為主元
		int key = arr[start];
		//若i與j未相遇,則執行以下迴圈
		while(i<j){
			//i從左向右掃描,直到當前元素大於主元時停下
			while(arr[i]<=key && i<end){
				i++;
			}
			//j從右向左掃描,直到當前元素小於主元時停下
			while(arr[j]>=key && j>start){
				j--;
			}
			//i、j停下有兩種情況:1.
			if(i<j)
				swap(arr,i,j);
		}
		//將主元與j交換
		swap(arr,start,j);
		System.out.println("某一趟排序結果:"+printArray(arr));
		//返回新的主元下標
		return j;
	}
	
	
	
	/**
	 * 快速排序入口函式
	 * @param arr 待排序陣列
	 * @return 返回有序的陣列
	 */
	public static void QuickSort(int[] arr){
		//健壯性判斷
		if(arr==null || arr.length<=0){
			System.out.println("陣列為空!");
			return;
		}
		
		//通過遞迴進行快速排序
		QuickSort(arr,0,arr.length-1);
	}
	
	
	
	/**
	 * 快速排序的遞迴函式
	 * @param arr 待排序陣列
	 * @param start 陣列的起始下標
	 * @param end 陣列的結束下標
	 * @return 返回當前有序子序列
	 */
	private static void QuickSort(int[] arr,int start,int end){
		if(start<end){
			//獲取主元
			int key = partition(arr,start,end);
			//對主元左側的序列進行快速排序
			QuickSort(arr,start,key-1);
			//對主元右側的序列進行快速排序
			QuickSort(arr,key+1,end);
		}
	}
	
	
	/**
	 * 實現i與j位置的元素交換
	 * @param arr 陣列
	 * @param i 下標
	 * @param j 下標
	 */
	private static void swap(int[] arr,int i,int j){
		//健壯性判斷
		if(arr==null || arr.length<=0){
			System.out.println("陣列為空!");
			return;
		}
		
		//定義臨時變數temp實現交換
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	
	
	
	/**
	 * 輸出陣列元素
	 * @param arr
	 * @return
	 */
	private static String printArray(int[] arr){
		if(arr==null){
			System.out.println("陣列為空!");
			return null;
		}
		
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<arr.length;i++){
			sb.append(arr[i]);
		}
		
		return sb.toString();
	}
}


相關推薦

offer 快速排序

tac temp string define src div star ide bsp   題目鏈接: 劍指offer   題目描述: 快速排序   解題思路: 快速排序   代碼: #include <iostream> #include <cst

offer 快速排序

1.快速排序,0,1,2..n-1,   選出樞紐元index,交換a[index]與a[n-1],將小於a[n-1]的元素放在左邊,大於的元素放在右邊,遞迴分別對兩組進行排序 #include<iostream> using namespace std; #i

offer——快速排序

        快速排序是目前所有排序中效能較好的一種演算法,最好情況和平均情況下時間複雜度均為O(nlogn),最壞的情況下時間複雜度為O(n^2)。快速排序採用遞迴,用空間換取時間。由於使用了遞迴,因此需要額外的儲存空間。 快速排序由三個函式構成,分別為QuickSor

offer-快速排序

package case99_QuickSort; public class QuickSortOpt { /** * 對快排進行優化 優化1:三數取中優化 優化2:優化小陣列時的排序方案 優化3:優化遞迴 * * @param args */ public static void

offer快速排序

快速排序 歡迎關注作者部落格 簡書傳送門   今天介紹快速排序,這也是在實際中最常用的一種排序演算法,速度快,效率高。就像名字一樣,快速排序是最優秀的一種排序演算法。 思想   快速排序採用的思想是分治思想。   快速排序是找出一個元素(理論上可以隨便找一個)作為基準(pivot

offer】—— 快速排序

兩個輔助函式: // 生成區間內的隨機整數 int RandInRange(int s, int e, unsigned seed=time_t(0)) { srand(seed);

offer——面試題11:快速排序

() value out val small break name space alt 1 #include"iostream" 2 #include"random" 3 using namespace std; 4 5 /* 6 void Swap(in

Offer》題目:合並兩個排序的鏈表

合成 sorted 合並 邊界情況 logs pub st2 next null 題目描述:輸入兩個單調遞增的鏈表list1,list2,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。 題目分析: 1.對於鏈表題目,首先考慮邊界情況,即鏈表為空的情況,

offer十六之合並兩個排序的鏈表

gif 虛線 tno 合並鏈表 -- class sed net isp 一、題目   輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。 二、思路   註:鏈表1和鏈表2是兩個遞增排序的鏈表,合並這兩個鏈表得到升序鏈表為鏈表3.

offer-合並兩個排序的鏈表

tno ide next val spa blog view offer 註意 從小的開始作為頭結點,然後比較選擇較小的進行鏈接 需要註意頭結點確定的時候就要保存下來,因為後面會一直變化往後鏈接新元素 /* struct ListNode { int

Offer 合並兩個排序的鏈表

合成 rank st2 listnode 代碼 .cn style inter 有一個   題目描述:輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。   題目鏈接:合並兩個排序的鏈表   思路:類似於2路歸並排序的合並操作,先取

Offer--合並兩個排序鏈表

鏈表 int == clas 規則 我們 st2 輸出 步驟 問題描述:輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。 思路:首先比較兩個鏈表的頭結點,如果鏈表1的頭結點小於鏈表2的頭結點,鏈表1的頭結點將是合並後鏈表的頭結點。

pythonoffer 合並兩個排序的鏈表

write 合並 offer 兩個 class head 題目 ext HERE 題目描述 輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。 # -*- coding:utf-8 -*- # class ListNode: #

offer之統計一個數字在排序陣列中出現的次數。

1.題目描述 統計一個數字在排序陣列中出現的次數。 2.問題分析 方法一: 因為是排序的陣列,首先在陣列中找到第一個值為k的位置begin,之後從begin找下一個不等於值k的位置end,則,次數為end - begin。 例如:1 2 2 3 3 3 5,k = 3

offer -- 數字在排序陣列中出現的次數

題目描述 統計一個數字在排序陣列中出現的次數。 解題思路 因為題目給出的陣列是排序了的,所以我們想到了二分查詢。利用二分查詢找到一個數字在陣列中第一次出現的位置和最後出現的位置即可。 AC程式碼 public class Solution { public int

offer程式設計題python實現(第16題)合併兩個排序的連結串列

劍指offer程式設計題python實現(第16題)合併兩個排序的連結串列 題目描述 輸入兩個單調遞增的連結串列, 輸出兩個連結串列合成後的連結串列, 當然我們需要合成後的連結串列滿足單調不減規則。 '''題目描述 輸入兩個單調遞增的連結串列, 輸出兩個連結串列合成後的連結串列, 當然我們需

offer:(38)知識遷移 :數字在排序陣列中出現的次數

統計一個數字在排序陣列中出現的次數。 思路:排序陣列一定要想到二分法查詢       package co.com.jianzhioffer; import java.io.ObjectInputStream.GetField; public class

Offer】14合併兩個排序的連結串列

題目描述 輸入兩個單調遞增的連結串列,輸出兩個連結串列合成後的連結串列,當然我們需要合成後的連結串列滿足單調不減規則。 時間限制:1秒;空間限制:32768K;本題知識點:連結串列 解題思路 # -*- coding:utf-8 -*- # class ListNode: #

offer系列(十一)二叉搜尋樹與雙向連結串列, 字串的排序

二叉搜尋樹與雙向連結串列 題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 解題思路: 由於輸入的一個二叉搜尋樹,其左子樹小於右子樹的值,這位後面的排序做了準備,因為只需要中序遍歷即可,將所有 的節點儲存

offer系列(十三)陣列中的逆序對,兩個連結串列的第一個公共結點,數字在排序陣列中出現的次數

陣列中的逆序對 題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 輸入描述: 題目保證輸入的陣列中沒有的相同的數字