「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
算法思想
归并排序是一种稳定的排序,是分治思想的的应用,分是先把问题分成小的问题,治是把分阶段的各个问题的答案合并
图片转自 www.cnblogs.com/chengxiao/p…
分治的过程
处理左右两边的结果
总结思想
- 左边处理一下,得到左边的信息
- 右边处理一下,得到右边的信息
- 最后在处理,横跨两边的信息
代码演示
var mergeSort = function (sum, l, r) {
if (l >= r) return
var mid = Math.floor((l + r) / 2) //中点
mergeSort(sum, l, mid) //递归左边
mergeSort(sum, mid + 1, r) //递归右边
// 成为有序数组
var temp = new Array(r - l + 1) //借助储存空间
var k = l,
p1 = l,
p2 = mid + 1
// 比较左右区间将较小的放入temp
while (p1 <= mid || p2 <= r) {
if (p2 > r || (p1 <= mid && sum[p1] <= sum[p2])) {
temp[k++] = sum[p1++]
} else {
temp[k++] = sum[p2++]
}
}
for (var i = l; i <= r; i++) sum[i] = temp[i] //储存空间拷贝回原数组
return
}
var arr = [8, 1, 5, 6, 3, 2, 7, 4, 9]
mergeSort(arr, 0, arr.length - 1)
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
归并排序可以解决的问题
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function (head) {
var count = 0 //链表长度
var p = head
while (p) {
p = p.next
count++
}
return mergeSort(head, count)
};
// 归并排序
var mergeSort = function (head, n) {
if (n <= 1) return head
var left_cnt = n >> 1, //左右链表长度
right_cnt = n - left_cnt
var l = head,//左链表
r = l,//右链表
p = l,
ret = new ListNode()//虚拟头,指向待返回链表
for (var i = 1; i < left_cnt; i++) {
p = p.next
}
r = p.next
p.next = null//断开链表
// 递归左右链表排序
l = mergeSort(l, left_cnt)
r = mergeSort(r, right_cnt)
p = ret
while(l || r) {
if(r == null || (l && l.val <= r.val)){
// 将虚拟头指向较小的链表
p.next = l;
p = l;
l = l.next;
}else{
p.next = r;
p = r;
r = r.next
}
}
return ret.next
}
--未完待续--