快速排序:冒泡的進化版,根據某一值key, 將大於key 的往後放,將小於key的往前放;通俗結果就是最後key值左邊的比key都小,key值右邊的比key都大;在對兩側的序列單獨進行key值比較交換,依次類推...
代碼的實現與理解:
int a[] = {5, 3, 4, 8, 9, 1, 7, 0, 2, 6};
sort(a, 0, a.length - 1);
for (int h = 0; h < a.length; h++) {
Log.i("chy1234", "==結果數據===" + a[h]);
}
/*********************************************************************/
private void sort(int a[], int leftBound, int rightBound) {
if (leftBound >= rightBound) {
// 如果左節點 >= 右節點, 說明此次遍歷結束
return;
}
// 獲取第一輪快排後的key 的位置
int mid = partition(a, leftBound, rightBound);
// 針對前半段進行快速排序
sort(a, leftBound, mid-1);
// 針對後半段進行快速排序
sort (a, mid +1, rightBound);
}
/********************************************************************/
/**
* 快排處理
*
* @param a
* @param leftBound
* @param rightBound
* @return 返回排完之後key的位置
*/
private int partition(int a[], int leftBound, int rightBound) {
int pivot = a[leftBound]; // 設定key值爲左邊第一個值
int left = leftBound + 1; // 從左邊第二個位置開始
int right = rightBound; // 尾結點
/**
* 循環結束點===>當左節點大於等於右節點則結束循環
*
* 關於 left = right 情況的解釋:(本人對於這個比較迷惑,所以記錄一下)
* 當存在數列中僅有兩個數比較時,例如leftBound = 0, rightBound = 1 ;
* 會出現上面的 left = right;
* 例如(5, 3)比較, left = 1, right = 1;
* 不會進入循環,最後與key值交換時,出現的的是 5 和 5 交換,(5, 3)不符合預期效果
* 所以此處循環應該有left = right的情況; 這樣以 5 爲基準,
* 則left在進入循環後會變成 left = 2;right = 1;
* 這樣在最後的 key 值位置校正時,就是 5 與 3 進行交換了,符號預期效果
*
*/
while (left <= right) {
/**
* 先從左邊開始遍歷數組,找到第一個大於pivot的值,
* 如果有那麼此時值爲 a[left]
*
* 循環條件: 左節點不能大於右節點 並且 值要比 pivot 小的,
* 纔可以繼續循環;直到遇到left > right 情況或者
* a[left] > pivot的情況,則循環終止
*/
while (left <= right && a[left] <= pivot) left++;
/**
* 從右邊邊開始遍歷數組,找到第一個小於 pivot 的值,
* 如果有那麼此時值爲 a[right]
*
* 循環條件: 左節點不能大於右節點 並且 值要比 pivot大的,
* 纔可以繼續循環;直到遇到left > right 情況或者
* a[right] < pivot的情況,則循環終止
*/
while (left <= right && a[right] >= pivot) right--;
/**
* 如果跳出以上循環的條件不是因爲節點關係,那麼默認找到了一組最大值和最小值
* 此時需要交換最大值和最小值的位置,以便完成大的放後邊,小的放前面的規則
* 如果滿足交換條件 left < right 則可知 a[left] > key; a[right] < key
*/
if (left < right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
}
/**
* 校正 key 的位置
*
* 等待循環結束後,除卻第一個值(第一個值被認作key值)
* 後面的數列以某一節點爲分界點,分界點前面的都小於key,
* 分界點後邊的都大於key;
* 此時需要矯正 key 的位置,把他放到分界點上
* =====分界點的位置在哪裏呢?====-----此處代碼針對分界點我們依賴於left的位置--------
* 上面外層循環結束的條件是 left > right && a[left] > pivot
* 所以 left 本身的位置應該是(以key爲分界點)數列右半部分的第一個值
* 因爲這裏處理的是key 與 首位進行交換, 所以取 a[left - 1]爲 key 的位置
*/
int temp = a[leftBound];
a[leftBound] = a[left - 1];
a[left - 1] = temp;
return left -1;
}
快速排序: