归并排序稍微复杂一丢丢,但是它的性能比前面的冒泡、选择和插入排序都好一点,是可以用在实战中的排序算法,听说以前火狐浏览器就是用它的
归并排序算法动图
一、归并排序的算法思路
底下的过程也不知道有没有说清楚,我总结一下就是,每每劈成两半,分成大组,大组里面分小组,一直二分,分到一个一组,不能分了,就是套娃
然后再从左边开始,从最小的组开始两两比较大小,左边两个比一下,右边两个比一下,再这四个比一下,再往外扩大范围用这个方式去比~
之前的过程说明
为了说清楚,假如有10个数
1、分组
先分组,大组分小组,再分小小组,直到分成一个数一组
左边是L,右边是R,每一个-表示后面的细分小组
(1)归并排序就是先对半劈,分成左边L1组5个和右边R2组5个两组
(2)左边5个分成左左边L1-L1组3个和右右边L1-R1组2个两组
(3)左左边的3个分成左左左边L1-L1-L1组的2个和右右右边L1-R1-L1组的1个
(4)左左左边的2个分成左左左左边L1-L1-L1-L1组的1个和右右右右边L1-L1-L1-R1组的1个
(5)前面的右边也要分直到分成1个和1个,省略不写了
这个要结合前面那个网址的动图来看~
2、排序
(1)左左左左边L1-L1-L1-L1组的1个数和右右右右边L1-L1-L1-R1组的1个数,来排序
小的一个就站出来,站到前面,另一个排到它后面,再回到队列里
(2)L1-L1-R1-L1组的1个数和右右右右边L1-L1-R1-R1的一个数比较
(3)这样的话,L1-L1的左边和L1-L1的右边就排好了是不是,再把
L1-L1-L1组的和L1-L1-R1的排列一下
啊啊啊~我好累。。。。。还是看图吧,不写了
二、编码实现
根据一的算法思路很明显的发现
第一需要递归不断的对半分
第二需要一个队列排序,每次小组排序时,把小的拿出来放在队列头
Array.prototype.mergeSort &#61; function() {const rec &#61; (arr) &#61;> {const len &#61; arr.length;if(len &#61;&#61;&#61; 1) return arr;const mid &#61; Math.floor(len/2);const leftArr &#61; arr.slice(0, mid);const rightArr &#61; arr.slice(mid, len);const leftOrder &#61; rec(leftArr);const rightOrder &#61; rec(rightArr);const res &#61; [];while(leftOrder.length || rightOrder.length) {if(leftOrder.length && rightOrder.length) {res.push(leftOrder[0] < rightOrder[0] ? leftOrder.shift(0) : rightOrder.shift(0));} else if(leftOrder.length) {res.push(leftOrder.shift(0));} else if(rightOrder.length) {res.push(rightOrder.shift(0));} else {break;}}return res;}const res &#61; rec(this);res.forEach((item, key) &#61;> {this[key] &#61; item;})
}const arr &#61; [1, 5, 9, 3, 18, 6, 2, 7, 0, 6]
arr.mergeSort()
console.log(arr);
三、算法时间复杂度
1、两两分组&#xff0c;用上递归&#xff0c;这种时间复杂度一般都是O(logn)
2、排序&#xff0c;也就是递归里面有个while循环&#xff0c;看到了吧&#xff0c;这种就是O(n)
所以这个排序算法的时间复杂度是O(nlogn)
终于写完了&#xff0c;写完发现也不是很难~算法还是以理解为主吧