排序算法-4(javascript) 归并排序的实现

归并排序实际是使用了分治再合并的思想:

  • 分治:
    它每轮会把数组分割成2分部分,如果分割的部分还很多数,可以按照这个方法继续分割,直到分割成简单序列(比如分割到剩最后一个数了,一个数的序列自然就是最简单的有序序列)。

  • 合并:
    这时候,对分割的最小部分开始,进行两两合并成有序序列,合并的实现方法是:

    1. 创建一个左指针,指向一个分割的有序序列(比如是数组arr1, 长度为n)的初始位置0;
    2. 创建一个右指针,指向另一个分割的有序序列(数组arr2,长度为m)的初始位置0;
    3. 再创建一个m+n的空数组(res),用来存储此轮的有序结果;
    4. 比较两个指针的数,哪个小就放到res中,然后该指针右移;
    5. 重复4步骤操作,直到有一个有序序列已经全被放到到res中,另一个有序序列剩下的所有值就可以直接拼接在res后面了,这样一轮操作就结束了
    6. 然后,再对再一对分割部分重复做1-5步骤,直至所有分割部分都合并完,结束

下面通过例子来说明它的思想:
初始的无序数组:[ 8, 5, 4, 9, 6, 2, 1 ]
分割:

  1. 第1步,对半分,分成两组 [8, 5, 4, 9],[6, 2, 1],此时这两还不是有序数组
  2. 第2步,各自继续对半分,[8, 5, 4, 9]分成[8, 5]和[4, 9]; [6, 2, 1]被分割成[6, 2]和[1],发现除了[1]其它都发现还不是有序数组
  3. 第3步,各自继续对半分,[8, 5]分成[8]和[5],[4, 9]分成[4]和[9], [6, 2]分成[6]和[2],这下好了,所有的都是有序序列了[8],[5],[4],[9],[6],[2],[1]
    合并:
  4. 对各层最小部分进行合并[8],[5]合并成了有序序列[5, 8];[4],[9]合并成了有序序列[4, 9],[6]和[2]合并成了[2, 6],[1]这一步没有对象合并闲置
  5. 再向上一层合并,[5, 8]和[4, 9]合并成了[4, 5, 8, 9];[2, 6]和[1]合并成了[1, 2, 6]
  6. 再向上一层合并[4, 5, 8, 9] 和 [1, 2, 6] 合并成了 [1, 2, 4, 5, 6, 8, 9],此时,已经是个完整的有序序列了,结束

复杂度分析

  • 时间复杂度:
    1. 分割过程每次步骤是n/2,所以时间复杂度为O(logn)
    2. 合并过程是遍历一个循环,O(n)
      所以总的是O(nlogn)
  • 空间复杂度:
    要重新定义一个数组存放有结果,所以是O(n)
  • 稳定性:归并排序并不会改变相同元素的相对位置,所以是一个稳定的算法

代码实现

/**
 * @description 递归实现归并排序
 * @param arr: 初始的无序队列
 * @return res: 被排好序的队列
 */
function mergeSort(arr) {
  // 如果分割得只每剩一个值,自然已经是一个有序区间,直接返回
  if(arr.length <= 1) return arr;
  // 否则分割
  let mid = 0;
  mid = Math.floor((arr.length)/2)
  console.log('mid:', mid);
  // 左子序列
  let left = arr.slice(0, mid)
  // 递归获取左子序列的分割合并,得到最后一层的有序左子序列
  left = mergeSort(left)
  // 右子序列
  let right = arr.slice(mid)
  // 递归获取右子序列的分割合并,得到最后一层的有序右子序列
  right = mergeSort(right)
  return merge(left, right)
}

/**
 * @description 合并算法
 * @param left: 要被合并的有序数组1
 * @param right: 要被合并的有序数组2
 * @return arr: 被排序好的数组
 */
function merge(left, right) {
  // 合并后存放的数组
  let res = []
  while(left.length && right.length) {
    // 如果左子序列第1个数数比较小,弹出此数放到结果队列中
    if(left[0] <= right[0]) {
      res.push(left.shift())
    // 否则,如果右子序列第1个数数比较小,弹出此数放到结果队列中
    } else {
      res.push(right.shift())
    }
  }
  // 当一个子序列排序结束时,另一个子序列就不需要再遍历比较了,直接拼接到结果后
  return res.concat(left, right)
}

// 查看所有结果
arr = [ 8, 5, 4, 9, 6, 2, 1 ]
let res = mergeSort(arr) // [1, 2, 4, 5, 6, 8, 9]
console.log("res:", res)

参考:
图灵社区:https://www.ituring.com.cn/book/miniarticle/62897
小象Web开发:https://baijiahao.baidu.com/s?id=1675262114341494342&wfr=spider&for=pc

排序算法系列文章传送门(未完,持续更新中):
排序算法-1(javascript) 冒泡、选择、插入、希尔排序的实现
排序算法-2(javascript) 快速排序的实现
排序算法-3(javascript) 堆排序的实现
排序算法-4(javascript) 归并排序的实现

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341