快速排序作爲很經典的一種排序方法,我們怎麼能不掌握呢?
首先讓我們來理清快速排序的思路:
現在有一個數組如下:
int[] nums = {4,1,6,2,3,7,9,8,0,5} ;
我們要使用快速排序使這個數組變的有序,從小到大或者從大到小的順序進行排列。其思路就是每次選擇數組中的一個數作爲”基數“,以這個”基數“作爲標準,將數組分爲兩個部分,例如:將小於等於這個”基數“的數放在”基數“的左邊,而把大於”基數“的數放在基數的右邊,這樣就可以讓數組變成一個”相對有序”的狀態,然後繼續分別對這兩個部分重複之前的操作直到所劃分的部分只有一個元素的時候,整個數組就是有序的了,這樣看文字的描述確實不夠清楚,下面讓我們通過數據變化的過程來理解一下(例子是上面數組):
選擇4作爲基數,將數組分爲小於等於4的和大於4的兩個部分
0 1 3 2 4 7 9 8 6 5
對於小於等於4的部分,選擇0作爲基數,沒有比0小的了,所以數組沒有變化
0 1 3 2 4 7 9 8 6 5
對於大於0,小於等於4的部分,選擇1作爲基數,沒有比1小的了,所以數組沒有變化
0 1 3 2 4 7 9 8 6 5
對於大於1,小於等於4的部分,選擇3作爲基數,2放到3的前面,至此,0->4部分的數已經完全有序了
0 1 2 3 4 7 9 8 6 5
選擇7作爲基數:
0 1 2 3 4 5 6 7 8 9
選擇5作爲基數:
0 1 2 3 4 5 6 7 8 9
選擇8作爲基數:
0 1 2 3 4 5 6 7 8 9
看完整個快速排序的過程,相信大家就已經很清楚快速排序的思想了,那麼我們緊接着使用代碼來將這個思路實現吧!
public void quickSort(int[] nums,int s,int e) {
if (s >= e) {
return;
}
int partitionFlag = partition(nums,s,e);
quickSort(nums,s,partitionFlag-1);
quickSort(nums,partitionFlag+1,e);
}
private int partition(int[] nums,int s,int e) {
//優化:選擇一個相對來說是中間大小的數作爲基數
int mid = s + (e-s>>1);
if (nums[s] > nums[e]) {
swap(nums,s,e);
}
if (nums[mid] > nums[e]) {
swap(nums,mid,e);
}
if (nums[s] < nums[mid]) {
swap(nums,s,mid);
}
int temp = nums[s];
System.out.print("選擇"+temp+"作爲基數:"+"\n");
while (s < e) {
//找小於等於基數的數
while (nums[e] > temp && s < e) {
e--;
}
if (s < e) {
nums[s++] = nums[e];
}
//找大於基數的數
while (nums[s] <= temp && s < e) {
s++;
}
if (s < e) {
nums[e--] = nums[s];
}
}
//將基數放在合適的位置
nums[s] = temp;
for (int i : nums) {
System.out.print(i + " ");
}
System.out.println();
return s;
}
private void swap(int[] nums,int x,int y) {
int temp = nums[x];
nums[x] = nums[y];
nums[y] = temp;
}
其中有個優化的點可以注意一下,之前我們是選擇基數是直接使用的第一個數,這樣帶來的問題就是,選擇的基數可能已經是索要判斷的部分的最大或者最小的值了,這會導致這一輪的排序沒有任何的變化,比如我們之前的看到的選擇0和1作爲基數時數組都沒有任何改變。那麼如果我們每次選擇的基數都是一個相對“中間”的數,那麼我們的每一輪排序都會有效很多,這樣可以提高不少效率!
如果我寫的有問題的地方,還望各位指正,歡迎大家跟我交流。