javascript資料結構與演算法--高階排序演算法
高階排序演算法是處理大型資料集的最高效排序演算法,它是處理的資料集可以達到上百萬個元素,而不僅僅是幾百個或者幾千個。現在我們來學習下2種高階排序演算法---- 希爾排序和快速排序。
一:希爾排序;
希爾排序的核心理念是:首先比較距離較遠的元素,而非相鄰的元素。
基本原理:通過定義一個間隔序列來表示在排序過程中進行比較的元素之間有多遠的間隔。
下面我們來看看陣列[0,9,1,8,7,6,2,3,5,4] 來使用希爾排序的原理;如下圖:
程式碼分析如下:
1. 執行 "間隔序列=3的步驟"
A. 那麼第一次執行 "間隔序列=3" 的步驟,那麼找到位置間隔3的元素為 0 , 8 , 2 , 4
所以這四個數字當中0最小,所以位置不動,還是第一個位置,8是最大的 所以位置就移動到之前的4的位置上,4移動到8的位置上,但是2和4比較 2小 於4的 所以2和4位置繼續調換。所以現在的順序為0 , 2 , 4 , 8,如上圖(間隔序列=3)
B. 現在第二次執行 "間隔序列=3" 的步驟,找到元素為 9 , 7 , 3 分析還是和上面的一樣 3是最小的,所以移動到原先9的位置上,9就移到到3的位置上, 由 於7小於9 所以不需要移動,所以現在的順序為 3 , 7 , 9 如上圖(間隔序列=3)
C. 現在第三次執行 "間隔序列=3"的步驟,找到元素 1 , 6 , 5 ,由於1是最小的 所以不需要移動,6大於5,所以2者要調換位置 所以順序為 1 , 5 , 6
執行完上面的步驟後,正確的順序為 [0,3,1,2,7,5,4,9,6,8]
2. 執行 "間隔序列=2"的步驟
A. 第一次查詢 找到元素 0,1,7,4,6,所以原理還是和上面一樣,0和1不需要移動 7和4及6調換位置,因此現在的順序變為 0,1,4,6,7
B. 第二次查詢 找到元素 3,2,5,9,8 ,所以順序變為 2,3,5,8,9
執行完上面的步驟後,正確的順序為 [0,2,1,3,4,5,6,8,7,9] 如上圖(間隔序列=2)
3. 執行 "間隔序列=1"的步驟;
陣列的順序就變為 [0,1,2,3,4,5,6,7,8,9].如上圖(間隔序列=1)
JS程式碼如下:
function CArray(numElements,gaps) { this.dataStore = []; this.pos = 0; this.numElements = numElements; this.gaps = gaps; this.insert = insert; this.toString = toString; this.clear = clear; this.shellSort = shellSort; for(var i = 0; i < numElements.length; i++) { this.dataStore[i] = numElements[i]; } } function clear() { for(var i = 0; i < this.dataStore.length; i++) { this.dataStore[i] = 0; } } function insert(element) { this.dataStore[this.pos++] = element; } function toString() { var restr = ""; for(var i = 0; i < this.dataStore.length; i++) { restr += this.dataStore[i] + " "; if(i > 0 && i % 10 == 0) { restr+= "\n"; } } return restr; } function shellSort() { for(var g = 0; g < this.gaps.length; ++g) { for(var i = this.gaps[g]; i < this.dataStore.length; ++i) { var temp = this.dataStore[i]; for(var j = i; j >= this.gaps[g] && this.dataStore[j - this.gaps[g]] > temp; j -= this.gaps[g]) { this.dataStore[j] = this.dataStore[j - this.gaps[g]]; } this.dataStore[j] = temp; } } } // 希爾排序測試程式碼 var numElements = [0,9,1,8,7,6,2,3,5,4]; var gaps = [3,2,1]; var myNums = new CArray(numElements,gaps); myNums.shellSort(); console.log(myNums.toString());
二:快速排序
快速排序是處理大資料集最快的排序演算法之一。它是一種分而治之的演算法,通過遞迴的方式將資料依次分解為包含較小元素和較大的元素的不同子序列。該演算法不斷重複這個步驟直到所有資料都是有序的。
這個演算法首先要在列表中選擇一個元素來作為基準值,資料排序圍繞基準值進行,將列表中小於基準值的元素移動到陣列的左邊,將大於基準值的元素移動到陣列的右邊,如下圖所示:
基本原理是:
- 選擇一個基準元素,將列表分割成2個子序列。基準元素的選擇可以有3種方式,可以選擇第一個元素作為基準元素,也可以把中間的值作為基準元素,還可以把最後一個元素作為基準的元素。
- 對列表重新排序,將所有小於基準值的元素放在基準值的前面,所有大於基準值的元素放在基準值的後面。
- 分別對較小元素的子序列和較大元素的子序列的重複步驟1和2.
下面是JS的程式碼如下:
// 快速排序 function qSort(list) { if(list.length == 0) { return []; } // 儲存小於基準值的值 var left = []; // 儲存大於基準值的值 var right = []; var pivot = list[0]; for(var i = 1; i < list.length; i++) { if(list[i] < pivot) { left.push(list[i]); }else { right.push(list[i]) } } return qSort(left).concat(pivot,qSort(right)); } // 快速排序測試程式碼 var numElements = [44,75,23,43,55,12,64,77,33]; var list = qSort(numElements); console.log(list); // [12, 23, 33, 43, 44, 55, 64, 75, 77]