用 JavaScript 實現鏈表操做 - 15 Merge Sort

TL;DR

對鏈表進行歸併排序,系列目錄見 前言和目錄git

需求

實現函數 mergeSort() 進行歸併排序。注意這種排序法須要使用遞歸。在 frontBackSplit()sortedMerge() 兩個函數的幫助下,你能夠很輕鬆的寫一個遞歸的排序。基本算法是,把一個鏈表切分紅兩個更小的鏈表,遞歸地對它們進行排序,最終把兩個排好序的小鏈表合成完整的鏈表。github

var list = 4 -> 2 -> 1 -> 3 -> 8 -> 9 -> null
mergeSort(list) === 1 -> 2 -> 3 -> 4 -> 8 -> 9 -> null

解法

歸併排序的運行方式是,遞歸的把一個大鏈表切分紅兩個小鏈表。切分到最後就全是單節點鏈表了,而單節點鏈表能夠被認爲是已經排好序的。這時候再兩兩合併,最終會獲得一個完整的已排序鏈表。算法

由於切分和合並兩個最重要的功能都已經實現,須要思考的就只是如何遞歸整個過程了。咱們分析一下能夠把整個過程分紅:segmentfault

  1. frontBackSplit() 把鏈表切分紅兩個,分別叫 firstsecond函數

  2. firstsecond 排序。測試

  3. sortedMerge() 把排好序的兩個鏈表合併起來。ui

其中第 2 步就是遞歸的點,由於排序這個事情剛好是 mergeSort 自己能夠作的。code

代碼以下:排序

const { Node } = require('./00-utils')
const { frontBackSplit } = require('./12-front-back-split')
const { sortedMerge } = require('./14-sorted-merge')

function mergeSort(list) {
  if (!list || !list.next) return list

  const first = new Node()
  const second = new Node()
  frontBackSplit(list, first, second)

  return sortedMerge(mergeSort(first), mergeSort(second))
}

參考資料

Codewars Kata
GitHub 的代碼實現
GitHub 的測試遞歸

相關文章
相關標籤/搜索