數組的快速排序算法,和並歸排序步驟基本相似。javascript
都是先拆分,後合併。並歸排序是:拆分容易,合併難。 快速排序是:拆分難,合併容易java
要理解快速排序,首先要理解拆分邏輯算法
要素:找一個基準點,經過操做使得數列的左邊所有都是小於他的數,右邊所有都是大於他的數;數組
一、選中基準點,開始索引 i ,結束索引 j函數
二、從數列右邊開始往左邊找,找到比基準點小的,交換位置 i++優化
三、從數列左邊開始往右邊找,找到比基準點大的,交換位置 j--ui
四、循環執行二、3,直到,i 不是小於 jcode
例如: 有數組 var arr = [30,24,5,58,18,36,12,42,39];blog
開始索引 i = 0; 結束索引 j = arr.length-1; 基準點 pivot = arr[i] 即爲30排序
則有以下代碼
var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, j = arr.length-1,pivot = arr[i]; while(i < j ){ //當最後結束時 i = j //從右往左找,找到比基準點小等的就交換,交換後,基準點的索引變爲 j while(i < j && arr[j] > pivot ) j--; //排除已經知足條件的點 if(i < j ){ swap(i++,j,arr); } //從左往右找,找到比基準點大的就交換,交換後,基準點的索引變爲 i while(i < j && arr[i] <= pivot) i++; //排除已經知足條件的點 if(i < j ){ swap(i,j--,arr); } } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } console.log(i,arr); //基準點i,處理好的arr
以上代碼就是快速排序的核心,若是將數列,不斷以上面方式細分,直到分爲單個元素。即最後的結果就是一個有序的數列
下面給出完整代碼
var arr = [30,24,5,58,18,36,12,42,39]; function Partition(arr,low,high){ var i = low,j = high,pivot = arr[i]; while(i < j ){ //從右往左找 while(i < j && arr[j] > pivot ) j--; if(i < j ){ swap(i++,j,arr); } //從左往右找 while(i < j && arr[i] <= pivot) i++; if(i < j ){ swap(i,j--,arr); } } return i; //返回基準元素位置 } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } function QuickSort(arr,low,high){ var mid; if(low < high){ mid = Partition(arr,low,high); //返回基準元素位置 QuickSort(arr,low,mid-1); //左邊快速排序 QuickSort(arr,mid+1,high); //右邊快速排序 } } QuickSort(arr,0,arr.length-1); console.log(arr);
優化擴展:
上面的Partition函數中,無論是從右往左,仍是從左往右。都是跟pivot基準元素交換。。實際上,能夠先直接左邊和右邊交換,最後再和基準元素交換,減小交換次數。代碼以下
var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, j = arr.length-1,pivot = arr[i]; var mid; while(i < j ){ //當最後結束時 i = j //從右往左找 while(i < j && arr[j] > pivot ) j--; //排除已經知足條件的點 //從左往右找 while(i < j && arr[i] <= pivot) i++; //排除已經知足條件的點 //找到兩個點,就相互交換 if(i < j ){ swap(i++,j--,arr); } } //最後將中間點和基準點交換 if(arr[i] > pivot){ mid = i-1; swap(0,mid,arr); }else{ mid = i; swap(0,mid,arr); } function swap(a,b,arr){ console.log(a,b,arr[a],arr[b]) var temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } console.log(mid,arr); //基準點mid,處理好的arr
使用js的數組方法 , unshift 和push
使用unshift 和push實現,將數列的基準元素,左邊所有小於他,右邊所有大於他
var arr = [30,24,5,58,18,36,12,42,39]; var i = 0, pivot = arr[0], arr2 = [pivot]; for(var j = 1; j < arr.length; j++ ){ if(arr[j] > pivot){ arr2.push(arr[j]); }else{ arr2.unshift(arr[j]); i++; } } console.log(i,arr2);
使用 unshift和push實現的快速排序
var arr = [30,24,5,58,18,36,12,42,39]; function Partition(arr,low,high){ var i = low,pivot = arr[i]; var arr2 = [pivot]; for(var j = low+1; j <= high; j++){ if(arr[j] > pivot){ arr2.push(arr[j]); }else{ arr2.unshift(arr[j]); i++; } } j = 0; for(var k = low ; k <= high ; k++){ arr[k] = arr2[j++]; } return i; //返回基準元素位置 } function QuickSort(arr,low,high){ var mid; if(low < high){ mid = Partition(arr,low,high); //返回基準元素位置 QuickSort(arr,low,mid-1); //左邊快速排序 QuickSort(arr,mid+1,high); //右邊快速排序 } } QuickSort(arr,0,arr.length-1); console.log(arr);