TL;DR
对链表举行兼并排序,系列目次见 前言和目次 。
需求
完成函数 mergeSort()
举行兼并排序。注重这类排序法须要运用递归。在 frontBackSplit() 和 sortedMerge() 两个函数的协助下,你能够很轻松的写一个递归的排序。基础算法是,把一个链表切分红两个更小的链表,递归地对它们举行排序,终究把两个排好序的小链表合成完全的链表。
var list = 4 -> 2 -> 1 -> 3 -> 8 -> 9 -> null
mergeSort(list) === 1 -> 2 -> 3 -> 4 -> 8 -> 9 -> null
解法
兼并排序的运转体式格局是,递归的把一个大链表切分红两个小链表。切分到最后就满是单节点链表了,而单节点链表能够被认为是已排好序的。这时候再两两兼并,终究会获得一个完全的已排序链表。
由于切分和兼并两个最主要的功用都已完成,须要思索的就只是怎样递归全部历程了。我们剖析一下能够把全部历程分红:
用
frontBackSplit()
把链表切分红两个,分别叫first
和second
。对
first
和second
排序。用
sortedMerge()
把排好序的两个链表兼并起来。
个中第 2 步就是递归的点,由于排序这个事变恰好是 mergeSort
自身能够做的。
代码以下:
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))
}