一、冒泡排序 bubble sort
思想:
让数组中的当前项和后一项进行比较,如果当前项比后一项大,则两项交换位置(让大的靠后)即可。
var arr=[12,8,24,16,1];
12>8 位置交换 [8,12,24,16,1] 第二轮: 8<12 不交换 [8,12,16,1,24] ......
12<24 不交换位置 [8,12,24,16,1] 12<16 不交换 [8,12,16,1,24]
24<16 位置交换 [8,12,16,24,1] 16>1 交换 [8,12,1,16,24]
24<1 位置交换 [8,12,16,1,24]
最多比较length-1次(不用和自己比) 每一轮比较都把当前最大的放到了末尾,所以当前轮比较多少次,需要把之前放到末尾的值也得去掉
第一轮完成后,虽然没有实现最后的结果,但是当前数组中最大的这个值24放到了末尾,
第二轮比较:不用再和24比较了,而且本轮结束剩余值中最大的16也放到末尾。
/* 冒泡排序 */
/*
*bubble:实现冒泡排序
* @params arr [ARRAY] 需要排序的数组
* @return [ARRAY] 排序后的新数组
*/
function bubble(arr) {
let temp = null;
//外层循环I控制比较的轮数
for (let i = 0; i < arr.length - 1; i++) {
//里层循环控制每一轮比较的次数
for (let j = 0; j < arr.length - 1 - i; j++) {
//如果当前项大于后一项
if (arr[j] > arr[j + 1]) {
//1、交换值
// temp =arr[j+1]
// arr[j+1] = arr[j]
// arr[j]=temp;
//2、使用解构赋值
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
return arr;
}
bubble([5, 7, 2, 4]) // [2, 4, 5, 7]
二、插入排序 Insert sort
思想:
就好比玩牌,在抓牌的时候一边抓牌一边排序,让新抓的牌和手里的牌比较
var arr=[12,8,24,16,1];
只要会打牌,就会插入排序:(抓牌并整理牌的过程)
左手 开始先抓一张牌过来
12 继续抓牌,抓到这样的牌和手里的牌依次比较(个人习惯从后向前比)
如果当前新牌A比手里的某张牌B大,则把A放到B的后面,如果小则继续向前面的牌比较
前提: 如果已经比较到第一张牌,则把当前牌A插入到最前面即可
8 12
8 12 24
8 12 16 24
稳定性 和 范围:
比较稳定的一种算法;
不适合数量特别大的排序,量级小千
/* 插入排序 */
/*
*insert:实现插入排序
* @params arr [ARRAY] 需要排序的数组
* * @return [ARRAY] 排序后的新数组
* */
function insert(arr) {
//准备一个新数组,用来存储抓到手里的牌,开始先抓一张进来
let handle = [];
handle.push(arr[0]);
// 从第二项开始依次抓牌,一直到把台面上的牌抓光
for (let i = 1; i < arr.length; i++) {
//A是新抓牌
let A = arr[i];
//和handle手中里的牌进行比较(从后向前比)
for (let j = handle.length - 1; j >= 0; j--) {
//每一次要比较的手里的牌
let B = handle[j];
//如果当前新牌A比要比较的牌B大,把A放到B的后面
if (A > B) {
//想要把A放到B的后面,j必须加1,否则是放到了B的前面,这是splice的特性;
handle.splice(j + 1, 0, A);
break;
}
//如果已经比较到第一项,就直接把新牌A放到最前即可
if (j === 0) {
handle.unshift(A);
}
}
}
return handle;
}
insert([12, 8, 24, 16, 1])
三、快速排序 quick sort
思想:
找到中间项,让拿出来的每一项和中间项继续比较,比中间项小的放到左边,比他大的放到右边,用递归的方式将左右数组排好,最后将左边+中间+右边。
稳定性 和 范围:
不是很稳定。
擅长处理大数据。
快速排序又称为划分交换排序,以分治法为策略实现的快速排序算法。
var arr=[12,8,15,24,16,1];
左边数组 中间项 右边数组
12 8 1 15 16 24
每一次继续不断的重复操作(递归)
1 8 12 16 24
递归:函数执行的时候自己调用自己
/* 快速排序 */
/*
*quick:实现快速排序
* @params arr [ARRAY] 需要排序的数组
* @return [ARRAY] 排序后的新数组
*
* */
function quick(arr) {
//结束递归
if (arr.length <= 1) {
return arr; }
//找到数组的中间项,在原数组的数组红把它移除
let middleIndex = Math.floor(arr.length / 2);
let middleValue = arr.splice(middleIndex, 1)[0];
// arr.splice(middleIndex,1)取出后是数组,所以得取第一个[0]
//准备左右两个数组,循环剩下的数组中的每一项,比较当前项下的放到左边数组中,反之放到右边数组中
let leftArr = [],
rightArr = [];
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
item < middleValue ? leftArr.push(item) : rightArr.push(item);
}
//递归方式让左右两边的数组持续这样处理,一直到左右两边都排好序位置
//(最后左边+中间+右边排好的数组)
return quick(leftArr).concat(middleValue, quick(rightArr));
}
let arr = [12, 8, 15, 24, 16, 1];
quick(arr); //[1, 8, 12, 15, 16, 24]
四、sort 排序
思路:
使用sort() 函数进行排序。
let arr=[12, 8, 15, 24, 16, 1];
let arr=[12, 8, 15, 24, 16, 1];
arr.sort((a,b)=>a-b); //[1, 8, 12, 15, 16, 24]
// 倒序
arr.sort((a,b)=> b-a);
// [24, 16, 15, 12, 8, 1]
五、归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
思路:
- 归并排序的过程是首先用递归的方法把大数组分割成只包含1个元素的小数组。
- 再用递归的方法,将每个小数组合并并排序。
- 归并排序使用的是分治法。
- FireFox使用归并排序作为sort方法的实现。
思路理解:
归并排序其实可以类比二分法,二分法其实就是二等分的意思,简而言之就是不断和新序列的中间值进行比较。归并排序似乎有异曲同工之妙,什么意思呢,就是将一个原始序对等分为两部分,然后不断地对等分新的序列,直至序列的长度为1或者2,那么想,如果一个序列为1,那就没有比较的意义了,它本身就是之最,如果是两个呢,那直接比较不就完了,把比较之后的值推送到一个新的数组。就这样不断地细分,不断的产生子序列,然后把穿产生的新序列作为新的父序列,然后同等级的父序列再比较产生新的祖序列,依次类推。
稳定性和适用范围:
归并排序是稳定的排序算法。
归并排序适合数据量较大的情况,如几百万个数据。
归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(nlogn)的时间复杂度。代价是需要额外的内存空间
实现:
function mergeSort(arr){
if (arr.length > 1) {
let mid = Math.floor(arr.length / 2)
let left = mergeSort(arr.slice(0, mid))
let right = mergeSort(arr.slice(mid))
arr = merge(left, right)
}
return arr
}
function merge(left, right) {
let res = []
let index1 = 0
let index2 = 0
while (index1 < left.length && index2 < right.length) {
if (left[index1] < right[index2]) {
res.push(left[index1++])
} else {
res.push(right[index2++])
}
}
return res.concat(index1 < left.length ? left.slice(index1) : right.slice(index2))
}
var arry = [12, 8, 24, 16, 1]
mergeSort(arry) // [1, 8, 12, 16, 24]
** 学习总结;
排序方法有多重选择合适的即可
用于学习记录,如有问题,欢迎指出