[路飞]_你可能不知道的排序-归并排序(MergeSort)

838 阅读1分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

算法思想

归并排序是一种稳定的排序,是分治思想的的应用,是先把问题分成小的问题,是把分阶段的各个问题的答案合并

图片转自 www.cnblogs.com/chengxiao/p…

分治的过程

图片.png

处理左右两边的结果

图片.png

图片.png 总结思想

  • 左边处理一下,得到左边的信息
  • 右边处理一下,得到右边的信息
  • 最后在处理,横跨两边的信息

代码演示

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]

归并排序可以解决的问题

148. 排序链表

/**
 * 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
}

--未完待续--