筆試面試常常涉及各類算法,本文簡要介紹經常使用的一些算法,並用JavaScript實現。面試
1)算法簡介算法
插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工做原理是經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,一般採用in-place排序(即只需用到O(1)的額外空間的排序),於是在從後向前掃描過程當中,須要反覆把已排序元素逐步向後挪位,爲最新元素提供插入空間。api
2)算法描述和實現 數組
通常來講,插入排序都採用in-place在數組上實現。具體算法描述以下:數據結構
JavaScript代碼實現:ide
1 function insertionSort(array) { 2 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') { 3 for (var i = 1; i < array.length; i++) { 4 var key = array[i]; 5 var j = i - 1; 6 while (j >= 0 && array[j] > key) { 7 array[j + 1] = array[j]; 8 j--; 9 } 10 array[j + 1] = key; 11 } 12 return array; 13 } else { 14 return 'array is not an Array!'; 15 } 16 }
3)算法分析ui
1)算法簡介spa
二分插入(Binary-insert-sort)排序是一種在直接插入排序算法上進行小改動的排序算法。其與直接插入排序算法最大的區別在於查找插入位置時使用的是二分查找的方式,在速度上有必定提高。prototype
2)算法描述和實現 設計
通常來講,插入排序都採用in-place在數組上實現。具體算法描述以下:
JavaScript代碼實現:
1 function binaryInsertionSort(array) { 2 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') { 3 for (var i = 1; i < array.length; i++) { 4 var key = array[i], left = 0, right = i - 1; 5 while (left <= right) { 6 var middle = parseInt((left + right) / 2); 7 if (key < array[middle]) { 8 right = middle - 1; 9 } else { 10 left = middle + 1; 11 } 12 } 13 for (var j = i - 1; j >= left; j--) { 14 array[j + 1] = array[j]; 15 } 16 array[left] = key; 17 } 18 return array; 19 } else { 20 return 'array is not an Array!'; 21 } 22 }
3)算法分析
1)算法簡介
選擇排序(Selection-sort)是一種簡單直觀的排序算法。它的工做原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢。
2)算法描述和實現
n個記錄的直接選擇排序可通過n-1趟直接選擇排序獲得有序結果。具體算法描述以下:
JavaScript代碼實現:
1 function selectionSort(array) { 2 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') { 3 var len = array.length, temp; 4 for (var i = 0; i < len - 1; i++) { 5 var min = array[i]; 6 for (var j = i + 1; j < len; j++) { 7 if (array[j] < min) { 8 temp = min; 9 min = array[j]; 10 array[j] = temp; 11 } 12 } 13 array[i] = min; 14 } 15 return array; 16 } else { 17 return 'array is not an Array!'; 18 } 19 }
3)算法分析
1)算法簡介
冒泡排序是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,若是它們的順序錯誤就把它們交換過來。走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成。這個算法的名字由來是由於越小的元素會經由交換慢慢「浮」到數列的頂端。
2)算法描述和實現
具體算法描述以下:
JavaScript代碼實現:
1 function bubbleSort(array) { 2 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') { 3 var len = array.length, temp; 4 for (var i = 0; i < len - 1; i++) { 5 for (var j = len - 1; j >= i; j--) { 6 if (array[j] < array[j - 1]) { 7 temp = array[j]; 8 array[j] = array[j - 1]; 9 array[j - 1] = temp; 10 } 11 } 12 } 13 return array; 14 } else { 15 return 'array is not an Array!'; 16 } 17 }
3)算法分析
1)算法簡介
快速排序的基本思想:經過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
2)算法描述和實現
快速排序使用分治法來把一個串(list)分爲兩個子串(sub-lists)。具體算法描述以下:
JavaScript代碼實現:
1 //方法一 2 function quickSort(array, left, right) { 3 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array' && typeof left === 'number' && typeof right === 'number') { 4 if (left < right) { 5 var x = array[right], i = left - 1, temp; 6 for (var j = left; j <= right; j++) { 7 if (array[j] <= x) { 8 i++; 9 temp = array[i]; 10 array[i] = array[j]; 11 array[j] = temp; 12 } 13 } 14 quickSort(array, left, i - 1); 15 quickSort(array, i + 1, right); 16 }; 17 } else { 18 return 'array is not an Array or left or right is not a number!'; 19 } 20 } 21 var aaa = [3, 5, 2, 9, 1]; 22 quickSort(aaa, 0, aaa.length - 1); 23 console.log(aaa); 24 25 26 //方法二 27 var quickSort = function(arr) { 28 if (arr.length <= 1) { return arr; } 29 var pivotIndex = Math.floor(arr.length / 2); 30 var pivot = arr.splice(pivotIndex, 1)[0]; 31 var left = []; 32 var right = []; 33 for (var i = 0; i < arr.length; i++){ 34 if (arr[i] < pivot) { 35 left.push(arr[i]); 36 } else { 37 right.push(arr[i]); 38 } 39 } 40 return quickSort(left).concat([pivot], quickSort(right)); 41 };
3)算法分析
1)算法簡介
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似徹底二叉樹的結構,並同時知足堆積的性質:即子結點的鍵值或索引老是小於(或者大於)它的父節點。
2)算法描述和實現
具體算法描述以下:
JavaScript代碼實現:
1 /*方法說明:堆排序 2 @param array 待排序數組*/ 3 function heapSort(array) { 4 if (Object.prototype.toString.call(array).slice(8, -1) === 'Array') { 5 //建堆 6 var heapSize = array.length, temp; 7 for (var i = Math.floor(heapSize / 2) - 1; i >= 0; i--) { 8 heapify(array, i, heapSize); 9 } 10 11 //堆排序 12 for (var j = heapSize - 1; j >= 1; j--) { 13 temp = array[0]; 14 array[0] = array[j]; 15 array[j] = temp; 16 heapify(array, 0, --heapSize); 17 } 18 } else { 19 return 'array is not an Array!'; 20 } 21 } 22 /*方法說明:維護堆的性質 23 @param arr 數組 24 @param x 數組下標 25 @param len 堆大小*/ 26 function heapify(arr, x, len) { 27 if (Object.prototype.toString.call(arr).slice(8, -1) === 'Array' && typeof x === 'number') { 28 var l = 2 * x + 1, r = 2 * x + 2, largest = x, temp; 29 if (l < len && arr[l] > arr[largest]) { 30 largest = l; 31 } 32 if (r < len && arr[r] > arr[largest]) { 33 largest = r; 34 } 35 if (largest != x) { 36 temp = arr[x]; 37 arr[x] = arr[largest]; 38 arr[largest] = temp; 39 heapify(arr, largest, len); 40 } 41 } else { 42 return 'arr is not an Array or x is not a number!'; 43 } 44 }
3)算法分析
1)算法簡介
歸併排序是創建在歸併操做上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個很是典型的應用。歸併排序是一種穩定的排序方法。將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲2-路歸併。
2)算法描述和實現
具體算法描述以下:
JavaScript代碼實現:
1 function mergeSort(array, p, r) { 2 if (p < r) { 3 var q = Math.floor((p + r) / 2); 4 mergeSort(array, p, q); 5 mergeSort(array, q + 1, r); 6 merge(array, p, q, r); 7 } 8 } 9 function merge(array, p, q, r) { 10 var n1 = q - p + 1, n2 = r - q, left = [], right = [], m = n = 0; 11 for (var i = 0; i < n1; i++) { 12 left[i] = array[p + i]; 13 } 14 for (var j = 0; j < n2; j++) { 15 right[j] = array[q + 1 + j]; 16 } 17 left[n1] = right[n2] = Number.MAX_VALUE; 18 for (var k = p; k <= r; k++) { 19 if (left[m] <= right[n]) { 20 array[k] = left[m]; 21 m++; 22 } else { 23 array[k] = right[n]; 24 n++; 25 } 26 } 27 }
3)算法分析
1)算法簡介
桶排序 (Bucket sort)的工做的原理:假設輸入數據服從均勻分佈,將數據分到有限數量的桶裏,每一個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排序)。
2)算法描述和實現
具體算法描述以下:
JavaScript代碼實現:
1 /*方法說明:桶排序 2 @param array 數組 3 @param num 桶的數量*/ 4 function bucketSort(array, num) { 5 if (array.length <= 1) { 6 return array; 7 } 8 var len = array.length, buckets = [], result = [], min = max = array[0], regex = '/^[1-9]+[0-9]*$/', space, n = 0; 9 num = num || ((num > 1 && regex.test(num)) ? num : 10); 10 for (var i = 1; i < len; i++) { 11 min = min <= array[i] ? min : array[i]; 12 max = max >= array[i] ? max : array[i]; 13 } 14 space = (max - min + 1) / num; 15 for (var j = 0; j < len; j++) { 16 var index = Math.floor((array[j] - min) / space); 17 if (buckets[index]) { // 非空桶,插入排序 18 var k = buckets[index].length - 1; 19 while (k >= 0 && buckets[index][k] > array[j]) { 20 buckets[index][k + 1] = buckets[index][k]; 21 k--; 22 } 23 buckets[index][k + 1] = array[j]; 24 } else { //空桶,初始化 25 buckets[index] = []; 26 buckets[index].push(array[j]); 27 } 28 } 29 while (n < num) { 30 result = result.concat(buckets[n]); 31 n++; 32 } 33 return result; 34 }
3)算法分析
桶排序最好狀況下使用線性時間O(n),桶排序的時間複雜度,取決與對各個桶之間數據進行排序的時間複雜度,由於其它部分的時間複雜度都爲O(n)。很顯然,桶劃分的越小,各個桶之間的數據越少,排序所用的時間也會越少。但相應的空間消耗就會增大。
1)算法簡介
計數排序(Counting sort)是一種穩定的排序算法。計數排序使用一個額外的數組C,其中第i個元素是待排序數組A中值等於i的元素的個數。而後根據數組C來將A中的元素排到正確的位置。它只能對整數進行排序。
2)算法描述和實現
具體算法描述以下:
JavaScript代碼實現:
1 function countingSort(array) { 2 var len = array.length, B = [], C = [], min = max = array[0]; 3 for (var i = 0; i < len; i++) { 4 min = min <= array[i] ? min : array[i]; 5 max = max >= array[i] ? max : array[i]; 6 C[array[i]] = C[array[i]] ? C[array[i]] + 1 : 1; 7 } 8 for (var j = min; j < max; j++) { 9 C[j + 1] = (C[j + 1] || 0) + (C[j] || 0); 10 } 11 for (var k = len - 1; k >=0; k--) { 12 B[C[array[k]] - 1] = array[k]; 13 C[array[k]]--; 14 } 15 return B; 16 }
3)算法分析
當輸入的元素是n 個0到k之間的整數時,它的運行時間是 O(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序算法。因爲用來計數的數組C的長度取決於待排序數組中數據的範圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據範圍很大的數組,須要大量時間和內存。