前端需要知道的排序算法
今天好好的学习了下关于排序的算法,以下是一些总结,也算是一种巩固。
首先排序算法没有什么优劣之分,在不同的场景中,不同的排序算法执行效率不同。
1.选择排序(selection sort):
一次排序,可以将某个区间的最小值排列到该区域的第一位
例如:数组[5, 1, 3, 2, 4, 6]
步骤一:选择该数组的最小值,一般设置为第一个值5,
步骤二:将该值与下面的值比较,如果下面的值小,就互换值,否则不变,
步骤三:循环下一个区域。
例如:[5, 1, 3, 2, 4, 6] 中默认最小值为5,然后跟后续区域最小值互换即1。[1, 5, 3, 2, 4, 6]
[1, 5, 3, 2, 4, 6]找出下一个区间[5, 3, 2, 4, 6]中默认最小值5,然后跟后续区域最小值互换即2,[2, 3, 5, 4, 6]
[2, 3, 5, 4, 6]找出下一个区间[3, 5, 4, 6]中默认最小值3,然后跟后续区域最小值互换即4,没他小,不换 [3, 5, 4, 6]后续以此类推
//颠倒数组值 function swap(arr, i1, i2) { var temp = arr[i1]; arr[i1] = arr[i2]; arr[i2] = temp; } /** * 选择排序 * @param {*} arr */ function selectionSort(arr) { for (var i = 0; i < arr.length - 1; i++) { //先记录其最小值,如果后面有比他还小的就换位置 var min = arr[i]; var index = i; for (var j = i + 1; j < arr.length - 1; j++) { if (arr[j] < min) { min = arr[j]; index = j; } } swap(arr, i, index); } }
2.冒泡排序(bubble sort):
一次冒泡排序,可以将某个区域序列的最大值排序到该区域的最后一位,具体的方式是:
- 将第1位和第2位比较,如果前者比后者大则交换
- 将第2位和第3位比较,如果前者比后者大则交换
- 依次类推,直到比较到该区域的最后两位
- 重复上述过程,直到序列排序完成
例如:[5, 1, 3, 2, 4, 6]
第一次:[1, 5, 3, 2, 4, 6]
第二次:[1, 3, 5, 2, 4, 6]
第三次:[1, 3, 2, 5, 4, 6]
第四次:[1, 3, 2, 4, 5, 6] 以此类推
/** * 冒泡排序 * @param {*} arr */ function bubbleSort(arr) { for (var i = 0; i < arr.length - 1; i++) { //循环了几次 for (var j = 0; j < arr.length - 1 - i; j++) { //需要经过arr.length-1次的冒泡 //i:0 循环:0~arr.length-1-i //i:1 循环:0~arr.length-1-i //i:2 循环: 0~arr.length-1-i if (arr[j] > arr[j + 1]) { swap(arr, j, j + 1); } } } } var arr = [5, 1, 3, 2, 4, 6]; bubbleSort(arr); console.log(arr)
3.插入排序(insertion sort):
将序列分为两个部分,一部分是有序的,一部分是无序的,现在要做的是,就是不断的从无序的部分取出数据,加入到有序的部分,直到整个排序完成
原理:序列[5, 7, 2, 3, 6]
- 分为有序的序列和无序的序列 (5) (7 2 3 6)
- 不断的扩充有序序列 (5 7) (2 3 6)
- 不断的扩充有序序列 (2 5 7) (3 6)
- 不断的扩充有序序列 (2 3 5 7) (6)
- 不断的扩充有序序列 (2 3 5 6 7)
- 排序完成
程序写法:
[5, 1, 3, 2, 4, 6],假设有序序列为(5,1,3),先保存其以后的第一个值arr[i]为temp=2,然后将temp和有序列表最后一位的前一个的值比较,
此时其最后一位的前一个为1,比temp小,所以temp就放置在最后一位上,其原来的值放在有序列表最后,就会变成(5,1,2,3),循环后即可
/** * 插入排序 * @param {*} arr */ function insertionSort(arr) { for (var i = 1; i < arr.length; i++) { if (arr[i] < arr[i - 1]) { //如果前一位大于该位, //将第i位的值加入到前面有序队列的正确位置 var temp = arr[i]; for (var j = i; j >= 0; j--) { if (j > 0 && arr[j - 1] > temp) { arr[j] = arr[j - 1];//如果有序列表的最后一位的前一位大于temp,就将有序列表的最后一位设为其前一位。 } else { //如果有序列表的最后一位的前一位小于temp,那就将最后一位设为temp。 arr[j] = temp; break; } } } } } var arr = [5, 3, 1, 6, 7, 4]; insertionSort(arr) console.log(arr);
4.快速排序(quick sort):
选择一个数(比如序列的最后一位)作为基准数,将整个序列排序成两部分,一部分比该数小,另一部分比该数大,基准数在中间,然后对剩余的序列做同样的事情,直到排序完成
例如:序列[5, 7, 2, 3, 6, 4]
- 选择4作为基准数,排序成为:(3, 2) 4 (7, 6, 5)
- 对于3,2, 继续使用该方式排序,得到: (2, 3) 4 (7,6,5)
- 对于7,6,5,继续使用该方式排序,得到: (2, 3) 4 (5,6,7)
- 排序完成
function quickSort(arr){ /** * * @param {*} arr * @param {*} start 开始下标 * @param {*} end 结束下标 */ function _quickSort(arr,start,end) { if (start >= end || start > arr.length - 1) return; var high = end,low = start;//设置高位和地位 var key = arr[high]; //设置基准值是最后一位 while (low < high) { while (low < high && arr[low] <= key) low ++ ; //如果低位的值小于基准值,低位向高位靠拢 arr[high] = arr[low]; //如果发现低位值大于基准值,将该位的值放在高位,且低位不再向高位靠拢 while (low < high && arr[high] >= key) high--; //低位不动,如果高位大于基准值,高位向低位靠拢 , arr[low] = arr[high];//靠拢过程中,如果高位小于基准值,将值放到靠拢的低位。 } arr[low] = key;//高位等于低位时,将基准值放入。 _quickSort(arr,start,low - 1);//循环快速排序基准值左边的数组 _quickSort(arr,high+1,end);//快速排序基准值右边的数组 } _quickSort(arr,0,arr.length-1); } var arr = [5, 1, 3, 2, 4, 6]; quickSort(arr); console.log(arr)