JavaScript實現八大內部排序算法
阿新 • • 發佈:2017-12-24
clas 建立 所有 rec 等於 function log 使用 並排
1.1插入排序的優化:二分排序
與插入排序思想差不多,但是二分排序是在插入第i個元素時,對前面的0~i-1元素進行折半,先跟它們中間的元素進行比較。如果小,那麽對前半進行折半;如果打,那麽對後半進行折半。依次進行,直到left>right。然後再把第i個元素前一位與目標位置之間的所有元素向後移動一位,再將目標元素放入正確位置上。
註:基數排序中:r是關鍵字的基數,d是長度,n是關鍵字的個數
1.插入排序 基本思想:在序號i之前的元素(0到i-1)已經排好序,本趟需要找到i對應的元素x (此時即arr[i]) 的正確位置k,在尋找位置k的過程中與序號i-1到0的元素依次進行比較。如果x小於比較元素,則比較元素向後移動一位;否則,結束移位,將x插入當前位置k
1 function insertSort(arr) { 2 for (let i = 1; i < arr.length; i++) { 3 // 將待插入元素提取出來 4 let temp = arr[i] 5 let j6 for (j = i - 1; j >= 0; j--) { 7 if (arr[j] > temp) { 8 // 插入元素小於比較元素,比較元素則向後移動一位 9 arr[j + 1] = arr[j] 10 } else { 11 // 否則,結束移位 12 break 13 } 14 } 15 //將插入元素插入正確位置 16 arr[j + 1] = temp 17 } 18 return arr 19 } 20 console.log(insertSort([7, 3, 4, 5, 10, 7, 8, 2]))
1 function binarySort(arr) { 2 for (let i = 0; i < arr.length; i++) { 3 let temp = arr[i] 4 let left = 0 5 let right = i - 1 6let mid 7 while (left <= right) { 8 mid = Math.floor((left + right) / 2) 9 if (arr[mid] > temp) { 10 right = mid - 1 11 } else { 12 left = mid + 1 13 } 14 } 15 for (let j = i - 1; j >= left; j--) { 16 arr[j + 1] = arr[j] 17 } 18 if (left !== i) { 19 arr[left] = temp 20 } 21 } 22 return arr 23 } 24 console.log(binarySort([7, 3, 4, 5, 10, 7, 8, 2]))
2.希爾排序 基本思想:先取一個小於n的整數d1作為第一個增量,把文件的全部記錄分成d1個組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d2<d1重復上述的分組和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。
1 function shellSort(arr) { 2 let d = arr.length 3 while (true) { 4 d = Math.floor(d / 2) 5 for (let x = 0; x < d; x++) { 6 for (let i = x + d; i < arr.length; i = i + d) { 7 let temp = arr[i] 8 let j 9 for (j = i - d; j >= 0 && arr[j] > temp; j = j - d) { 10 arr[j + d] = arr[j] 11 } 12 arr[j + d] = temp 13 } 14 } 15 if (d == 1) { 16 break 17 } 18 } 19 return arr 20 } 21 console.log(shellSort([7, 3, 4, 5, 10, 7, 8, 2]))
3.直接選擇排序 基本思想:每次選擇待排序的元素中最小的值,放置在序列的首位
1 function directSelectSort(arr) { 2 for (let i = 0; i < arr.length; i++) { 3 let min = arr[i] 4 let index = i 5 for (let j = i + 1; j < arr.length; j++) { 6 if (arr[j] < min) { 7 // 找到最小值,並標註最小值索引,方便後續與元素arr[i]交換位置 8 min = arr[j] 9 index = j 10 } 11 } 12 arr[index] = arr[i] 13 arr[i] = min 14 } 15 return arr 16 } 17 console.log(directSelectSort([7, 3, 4, 5, 10, 7, 8, 2]))
4.堆排序 堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特征,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單 用大根堆排序的基本思想 ① 先將初始文件R[1..n]建成一個大根堆,此堆為初始的無序區 ② 再將關鍵字最大的記錄R[1](即堆頂)和無序區的最後一個記錄R[n]交換,由此得到新的無序區R[1..n-1]和有序區R[n],且滿足R[1..n-1].keys≤R[n].key ③由於交換後新的根R[1]可能違反堆性質,故應將當前無序區R[1..n-1]調整為堆。然後再次將R[1..n-1]中關鍵字最大的記錄R[1]和該區間的最後一個記錄R[n-1]交換,由此得到新的無序區R[1..n-2]和有序區R[n-1..n],且仍滿足關系R[1..n-2].keys≤R[n-1..n].keys,同樣要將R[1..n-2]調整為堆。…… 直到無序區只有一個元素為止。
1 let len 2 3 function buildMaxHeap(arr) { 4 //建立大根堆 5 len = arr.length 6 for (let i = Math.floor(len / 2); i >= 0; i--) { 7 heapify(arr, i) 8 } 9 } 10 11 function heapify(arr, i) { 12 //堆調整 13 let left = 2 * i + 1, 14 right = 2 * i + 2, 15 largest = i 16 17 if (left < len && arr[left] > arr[largest]) { 18 largest = left 19 } 20 21 if (right < len && arr[right] > arr[largest]) { 22 largest = right 23 } 24 25 if (largest !== i) { 26 // 解構賦值,交換變量 27 ;[arr[i], arr[largest]] = [arr[largest], arr[i]] 28 heapify(arr, largest) 29 } 30 } 31 32 function heapSort(arr) { 33 buildMaxHeap(arr) 34 35 for (let i = arr.length - 1; i > 0; i--) { 36 ;[arr[0], arr[i]] = [arr[i], arr[0]] 37 len-- 38 heapify(arr, 0) 39 } 40 return arr 41 } 42 43 console.log(heapSort([7, 3, 4, 5, 10, 7, 8, 2]))
5.冒泡排序 基本思想:每次比較兩相鄰的數,當發現它們的排序與排序要求相反時,就將它們互換。這樣小的數往下沈,大的數往上冒
1 function bubbleSort(arr) { 2 for (let i = 0; i < arr.length; i++) { 3 // 因為每次比較時都已經有i個元素沈下去了,所以j<arr.length-1-i 4 for (let j = 0; j < arr.length - 1 - i; j++) { 5 if (arr[j] > arr[j + 1]) { 6 // 這裏采用了解構賦值。如果一般做法,借助臨時變量,則輔助空間是O(1) 7 ;[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]] 8 } 9 } 10 } 11 return arr 12 } 13 console.log(bubbleSort([7, 3, 4, 5, 10, 7, 8, 2]))
6.快速排序 基本思想:選擇一個基準元素(通常選擇第一個元素),通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有元素都比基準元素小,另外一部分的所有元素大於或等於基準元素大。同樣方法依次分割;整個排序過程可以遞歸進行。
1 let quicksort = function(arr) { 2 if(arr.length <= 1) return arr; 3 4 let pivot = Math.floor((arr.length -1)/2); 5 let val = arr[pivot], less = [], more = []; 6 7 arr.splice(pivot, 1); 8 arr.forEach(function(e,i,a){ 9 e < val ? less.push(e) : more.push(e); 10 }); 11 12 return (quicksort(less)).concat([val],quicksort(more)) 13 } 14 console.log(quicksort([7, 3, 4, 5, 10, 7, 8, 2]))
7.歸並排序 基本思想:將待排序序列分為若幹個子序列,每個子序列是有序的,然後將有序子序列合並為整體有序序列。
1 function merge(left, right) { 2 let result = [] 3 while (left.length > 0 && right.length > 0) { 4 if (left[0] < right[0]) { 5 /*shift()方法用於把數組的第一個元素從其中刪除,並返回第一個元素的值。*/ 6 result.push(left.shift()) 7 } else { 8 result.push(right.shift()) 9 } 10 } 11 return result.concat(left).concat(right) 12 } 13 function mergeSort(arr) { 14 if (arr.length == 1) { 15 return arr 16 } 17 let middle = Math.floor(arr.length / 2), 18 left = arr.slice(0, middle), 19 right = arr.slice(middle) 20 return merge(mergeSort(left), mergeSort(right)) 21 } 22 console.log(mergeSort([7, 3, 4, 5, 10, 7, 8, 2]))
8.基數排序 基本思想:將所有待比較元素(正整數)統一為同樣的數位長度,數位較短的數前面補零。然後,從個位開始,進行排序;然後十位,進行排序;以此進行!這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。 基數排序兩種方法: MSD 從高位開始進行排序 LSD 從低位開始進行排序
1 // LSD Radix Sort 2 // helper function to get the last nth digit of a number 3 var getDigit = function(num,nth){ 4 // get last nth digit of a number 5 var ret = 0; 6 while(nth--){ 7 ret = num % 10 8 num = Math.floor((num - ret) / 10) 9 } 10 return ret 11 } 12 13 // radixSort 14 function radixSort(arr){ 15 var max = Math.floor(Math.log10(Math.max.apply(Math,arr))), 16 // get the length of digits of the max value in this array 17 digitBuckets = [], 18 idx = 0; 19 20 for(var i = 0;i<max+1;i++){ 21 22 // rebuild the digit buckets according to this digit 23 digitBuckets = [] 24 for(var j = 0;j<arr.length;j++){ 25 var digit = getDigit(arr[j],i+1); 26 27 digitBuckets[digit] = digitBuckets[digit] || []; 28 digitBuckets[digit].push(arr[j]); 29 } 30 31 // rebuild the arr according to this digit 32 idx = 0 33 for(var t = 0; t< digitBuckets.length;t++){ 34 if(digitBuckets[t] && digitBuckets[t].length > 0){ 35 for(j = 0;j<digitBuckets[t].length;j++){ 36 arr[idx++] = digitBuckets[t][j]; 37 } 38 } 39 } 40 } 41 return arr 42 } 43 console.log(radixSort([7, 3, 4, 5, 10, 7, 8, 2]))
註:網上有很多javascript實現的基數排序代碼時錯誤的
當搜索一些問題時,盡量使用英文進行搜索!
JavaScript實現八大內部排序算法