转自:http://www.cnblogs.com/ywang1724/p/3946339.html
笔试面试经常涉及各种算法,本文简要介绍常用的一些算法,并用JavaScript实现。
1)算法简介
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
2)算法描述和实现
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
JavaScript代码实现:
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)算法分析
1)算法简介
二分插入(Binary-insert-sort)排序是一种在直接插入排序算法上进行小改动的排序算法。其与直接插入排序算法最大的区别在于查找插入位置时使用的是二分查找的方式,在速度上有一定提升。
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),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。