快速排序算法思想:
(1)輸入的數據信息:輸入一個待排序的數組a[n],利用QuickSort算法實現此數組的排序任務。
(2)快速排序的思想:找待排序數組a[n]中a[0]或者a[n-1]作為參考flag,例如找flag=a[n-1],然后兩個指針一個從left=0開始向右索引,一個指針從right=n-2開始向左索引,left指針尋找大于flag的元素,right指針尋找小于flag的元素,如果都找不到,則left++或right--,繼續索引,當left>=right時,終止此循環,然后把flag與此時left指針索引的元素交換,最后輸出left,實現數據分割,即left指針左邊的數據元素小于flag,left指針右邊的數據元素大于flag。
(3)遞歸實現算法:輸入待排序的數組a[n]和需要對此數組排序的索引范圍(left,right),因為我們不可能獨立把數組分成兩部分,所以實現的方式就是在原數組上進行處理,利用交換實現空間復雜度不變。
快速排序Java編程:
public class QuickSortTest {
public static void QuickSort(int[] arr, int left, int right){
if(left < right){
int medium = Partition(arr, left, right);
QuickSort(arr, left, medium-1);
QuickSort(arr, medium+1, right);
}
}
public static int Partition(int[] arr, int left, int right){
int pivot = arr[left];
while (left < right) {
while (left < right && arr[right] >= pivot)
right--;
if (left < right)
arr[left++] = arr[right];
while (left < right && arr[left] <= pivot)
left++;
if (left < right)
arr[right--] = arr[left];
}
arr[left] = pivot;
return left;
}
public static void main(String[] args) {
int[] arr = {6,9,8,6,4,3,9,10,52,82,12,36,14};
int left = 0;
int right = arr.length - 1;
QuickSort(arr,left,right);
for(int i : arr){
System.out.print(i);
System.out.print(' ');
}
}
}
輸出結果:3 4 6 6 8 9 9 10 12 14 36 52 82
快速排序的遞歸算法本質上就是一個二叉樹的先序遍歷過程,先處理當前根節點,然后依次處理左右部分(左子樹和右子樹)。
將快速排序遞歸算法轉換為非遞歸相當于將二叉樹先序遍歷遞歸算法轉為非遞歸算法。
時間復雜度和空間復雜度計算
1.時間復雜度:
①問題描述
快速排序將規模為n的問題分解為2個子問題,每個子問題的規模為n/2,每個子問題繼續遞歸實現重復操作。
②公式定義:
T(n) = 2T(n/2) + f(n) = 2T(n/2) + O(n)
公式說明:T(n)表示總的時間復雜度,T(n/2)為分一次得到的子問題的時間復雜度,f(n)表示執行一次分裂需要做多少次操作,快速排序左右索引依次向中間走,總共需要遍歷n次,所以f(n) = O(n)。
③求解T(n)的方法:
首先理解一個數組通過二分法對半分,一直到每一個數據都被分開隔離需要多少次?
答案:2^k = n,所以 k = lgn (以2為底的對數)
④生成函數法求解T(n)
T(n)=2T(n/2)+n
=2[2T(n/4)+n/2]+n = 4T(n/4) + 2n
=4[2T(n/8)+n/4]+2n = 8T(n/8) + 3n
=16T(n/16)+4n
=……
=(2^k) * T(n/(2^k)) + kn
=(2^lgn) * T(n/(2^lgn)) + nlgn
=nT(1)+nlgn
2.空間復雜度
①問題描述
a. 借用的輔助空間的大小
b. 遞歸時壓入棧的數據所占用的空間。
②最壞情況:完全逆序
待續