排序算法维度对比
稳定。 如果a原本在b前面,而a=b,排序之后a仍然在b的前面;反之则不稳定
时间复杂度。 运行完一个程序所需时间的长久
空间复杂度。 运行完一个程序所需内存的大小
排序对比:
排序分类:
冒泡排序 介绍 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
算法描述 <1>.比较相邻的元素。如果第一个比第二个大,就交换它们两个;1>
<2>.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;2>
<3>.针对所有的元素重复以上的步骤,除了最后一个;3>
<4>.重复步骤1~3,直到排序完成。4>
动态展示
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function bubbleSort (arr ) { var len = arr.length; for (var i = 0 ; i < len; i++) { for (var j = 0 ; j < len - 1 - i; j++) { if (arr[j] > arr[j+1 ]) { var temp = arr[j+1 ]; arr[j+1 ] = arr[j]; arr[j] = temp; } } } return arr; } var arr=[3 ,44 ,38 ,5 ,47 ,15 ,36 ,26 ,27 ,2 ,46 ,4 ,19 ,50 ,48 ];console .log(bubbleSort(arr));
改进后方案 改进冒泡排序原理: 设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function bubbleSort2 (arr ) { console .time('改进后冒泡排序耗时' ); var i = arr.length-1 ; while ( i> 0 ) { var pos= 0 ; for (var j= 0 ; j< i; j++) if (arr[j]> arr[j+1 ]) { pos= j; var tmp = arr[j]; arr[j]=arr[j+1 ];arr[j+1 ]=tmp; } i= pos; } console .timeEnd('改进后冒泡排序耗时' ); return arr; } var arr=[3 ,44 ,38 ,5 ,47 ,15 ,36 ,26 ,27 ,2 ,46 ,4 ,19 ,50 ,48 ];console .log(bubbleSort2(arr));
选择排序 介绍 选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
算法描述 <1>. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。1>
<2>. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。2>
<3>. 重复第二步,直到所有元素均排序完毕。3>
动态展示
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function selectionSort (arr ) { var len = arr.length; var minIndex, temp; console .time('选择排序耗时' ); for (var i = 0 ; i < len - 1 ; i++) { minIndex = i; for (var j = i + 1 ; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } console .timeEnd('选择排序耗时' ); return arr; } var arr=[3 ,44 ,38 ,5 ,47 ,15 ,36 ,26 ,27 ,2 ,46 ,4 ,19 ,50 ,48 ];console .log(selectionSort(arr));
插入排序 介绍 插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
算法实现 <1>.从第一个元素开始,该元素可以认为已经被排序;1>
<2>.取出下一个元素,在已经排序的元素序列中从后向前扫描;2>
<3>.如果该元素(已排序)大于新元素,将该元素移到下一位置;3>
<4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;4>
<5>.将新元素插入到该位置后;5>
<6>.重复步骤2~5。6>
动态展示
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function insertionSort (array ) { if (Object .prototype.toString.call(array).slice(8 , -1 ) === 'Array' ) { console .time('插入排序耗时:' ); for (var i = 1 ; i < array.length; i++) { var key = array[i]; var j = i - 1 ; while (j >= 0 && array[j] > key) { array[j + 1 ] = array[j]; j--; } array[j + 1 ] = key; } console .timeEnd('插入排序耗时:' ); return array; } else { return 'array is not an Array!' ; } }
改进二分查找方案 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function binaryInsertionSort (array ) { if (Object .prototype.toString.call(array).slice(8 , -1 ) === 'Array' ) { console .time('二分插入排序耗时:' ); for (var i = 1 ; i < array.length; i++) { var key = array[i], left = 0 , right = i - 1 ; while (left <= right) { var middle = parseInt ((left + right) / 2 ); if (key < array[middle]) { right = middle - 1 ; } else { left = middle + 1 ; } } for (var j = i - 1 ; j >= left; j--) { array[j + 1 ] = array[j]; } array[left] = key; } console .timeEnd('二分插入排序耗时:' ); return array; } else { return 'array is not an Array!' ; } } var arr=[3 ,44 ,38 ,5 ,47 ,15 ,36 ,26 ,27 ,2 ,46 ,4 ,19 ,50 ,48 ];console .log(binaryInsertionSort(arr));
快速排序 介绍 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法实现 快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
<1>.从数列中挑出一个元素,称为 “基准”(pivot);1>
<2>.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;2>
<3>.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。3>
动态展示
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 function quickSort (array, left, right ) { console .time('1.快速排序耗时' ); if (Object .prototype.toString.call(array).slice(8 , -1 ) === 'Array' && typeof left === 'number' && typeof right === 'number' ) { if (left < right) { var x = array[right], i = left - 1 , temp; for (var j = left; j <= right; j++) { if (array[j] <= x) { i++; temp = array[i]; array[i] = array[j]; array[j] = temp; } } quickSort(array, left, i - 1 ); quickSort(array, i + 1 , right); } console .timeEnd('1.快速排序耗时' ); return array; } else { return 'array is not an Array or left or right is not a number!' ; } } var quickSort2 = function (arr ) { console .time('2.快速排序耗时' ); if (arr.length <= 1 ) { return arr; } var pivotIndex = Math .floor(arr.length / 2 ); var pivot = arr.splice(pivotIndex, 1 )[0 ]; var left = []; var right = []; for (var i = 0 ; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } console .timeEnd('2.快速排序耗时' ); return quickSort2(left).concat([pivot], quickSort2(right)); }; var arr=[3 ,44 ,38 ,5 ,47 ,15 ,36 ,26 ,27 ,2 ,46 ,4 ,19 ,50 ,48 ];console .log(quickSort(arr,0 ,arr.length-1 ));console .log(quickSort2(arr));
算法实例 查找两个字符串的最长公共子串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 function findSubStr (arr1, arr2 ) { var sstr = '' ; var L1 = arr1.length; var L2 = arr2.length; if (L1 > L2) { var temp = arr1; arr1 = arr2; arr2 = temp; L1 = arr2.length; } for (var j = L1; j > 0 ; j--) for (var i = 0 ; i <= L1 - j; i++) { sstr = arr1.substr(i, j); if (arr2.indexOf(sstr) >= 0 ){ return sstr; } } return '' ; } function findMaxSubstr (str1, str2 ) { var shorter = str1; var longer = str2; if (str1.length > str2.length){ shorter = str2; longer = str1; }else { shorter = str1; longer = str2; } for (var subLength=shorter.length; subLength>0 ; subLength--){ for (var i=0 ; i<=shorter.length-subLength; i++){ var subString = shorter.substring(i,i+subLength); if (longer.indexOf(subString) >= 0 ){ var targetString = subString; return targetString; } } } }
统计一个字符串出现频率最高的字母/数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const getMaxChar = str => { let string = [...str]; let maxValue = '' ; let obj = {}; let max = 0 ; string.forEach(value => { obj[value] = obj[value] == undefined ? 1 : obj[value] + 1 if (obj[value] > max) { max = obj[value] maxValue = value } }) return maxValue; }
颠倒字符串 1 2 3 function reverseBySeparator (str ) { return str.split('' ).reverse().join('' ); }
判断大括号是否闭合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function isBalanced (expression ) { var checkString = expression; var stack = []; if (checkString.length <= 0 ) return true ; for (var i = 0 ; i < checkString.length; i++) { if (checkString[i] === '{' ) { stack.push(checkString[i]); } else if (checkString[i] === '}' ) { if (stack.length > 0 ) { stack.pop(); } else { return false ; } } } if (stack.pop()) return false ; return true ; } isBalanced('{}{' )
来源于1:https://juejin.im/post/57dcd394a22b9d00610c5ec8 来源于2:https://www.runoob.com/w3cnote/ten-sorting-algorithm.html