摘要:一談,原始的歸并排序二談,優(yōu)化后的歸并排序優(yōu)化算法的指導(dǎo)思想之一,找到某些可以簡(jiǎn)化處理的特殊情況合并時(shí)的特殊情況當(dāng)?shù)淖詈笠粋€(gè)元素小于的第一個(gè)元素時(shí),那么順序就應(yīng)該是當(dāng)?shù)淖詈笠粋€(gè)元素小于的第一個(gè)元素時(shí),那么順序就應(yīng)該是所以修改函數(shù)如下適時(shí)
一談,原始的歸并排序
function mergeSort(arr) { let { length } = arr if (length < 2) { return arr } let midIndex = Math.floor(length / 2) let leftArr = mergeSort(arr.slice(0, midIndex)) let rightArr = mergeSort(arr.slice(midIndex)) return merge(leftArr, rightArr) } function merge(leftArr, rightArr) { let i = 0, j = 0, arr = [] while (true) { if (i === leftArr.length) { arr.push(...rightArr.slice(j)) break } if (j === rightArr.length) { arr.push(...leftArr.slice(i)) break } if (leftArr[i] < rightArr[j]) { arr.push(leftArr[i]) i++ } if (rightArr[j] <= leftArr[i]) { arr.push(rightArr[j]) j++ } } return arr } let arr = [1, 5, 2, 11, 7, 3, 1, 6, 17, 10] let arrInOrder = mergeSort(arr) console.log(arrInOrder) // [ 1, 1, 2, 3, 5, 6, 7, 10, 11, 17 ]二談,優(yōu)化后的歸并排序
優(yōu)化算法的指導(dǎo)思想之一,找到某些可以簡(jiǎn)化處理的特殊情況
合并時(shí)的特殊情況當(dāng) leftArr 的最后一個(gè)元素小于 rightArr 的第一個(gè)元素時(shí),那么順序就應(yīng)該是 [leftArr, rightArr]
當(dāng) rightArr 的最后一個(gè)元素小于 leftArr 的第一個(gè)元素時(shí),那么順序就應(yīng)該是 [rightArr, leftArr]
所以修改 mergeSort 函數(shù)如下
function mergeSort(arr) { let { length } = arr if (length < 2) { return arr } let midIndex = Math.floor(length / 2) let leftArr = mergeSort(arr.slice(0, midIndex)) let rightArr = mergeSort(arr.slice(midIndex)) if (leftArr[leftArr.length - 1] <= rightArr[0]) { return [...leftArr, ...rightArr] } if (rightArr[rightArr.length - 1] <= leftArr[0]) { return [...rightArr, ...leftArr] } return merge(leftArr, rightArr) } ...適時(shí)的利用插入排序
當(dāng)數(shù)組的長(zhǎng)度變小到一定程序時(shí),采用插入排序
遞歸優(yōu)化-尾遞歸先修改代碼如下
function mergeSort(arr, fromIndex, length) { if (length < 2) { return } mergeSort(arr, fromIndex, Math.floor(length / 2)) mergeSort(arr, fromIndex + Math.floor(length / 2), length - Math.floor(length / 2)) merge(arr, fromIndex, length) } function merge(arr, fromIndex, length) { let leftArr = arr.slice(fromIndex, fromIndex + Math.floor(length / 2)) let rightArr = arr.slice(fromIndex + Math.floor(length / 2), fromIndex + length) let i = 0, j = 0, orderedArr = [] while (true) { if (i === leftArr.length) { orderedArr.push(...rightArr.slice(j)) break } if (j === rightArr.length) { orderedArr.push(...leftArr.slice(i)) break } if (leftArr[i] < rightArr[j]) { orderedArr.push(leftArr[i]) i++ } if (rightArr[j] <= leftArr[i]) { orderedArr.push(rightArr[j]) j++ } } arr.splice(fromIndex, length, ...orderedArr) } let arr = [1, 5, 2, 11, 7, 3, 1, 6, 17, 10] mergeSort(arr, 0, arr.length) arr // [ 1, 1, 2, 3, 5, 6, 7, 10, 11, 17 ]
把傳過的參數(shù)都記錄下來,存在 argsArr 中
例如在計(jì)算 fromIndex 為 0, length 為 10 時(shí),分為三步
先要通過mergeSort計(jì)算 fromIndex 為 0, length 為 5
再通過mergeSort計(jì)算 fromIndex 為 5, length 為 5
最后merge (arr, 0, 10)
由于尾遞歸調(diào)用,只能先計(jì)算 mergeSort(arr, 0, 5, argsArr)
而把 [0, 10, 5, 5] 存起來,前兩個(gè)參數(shù)是merge的參數(shù),后兩個(gè)是mergeSort的參數(shù)
用過的參數(shù)就把它去掉,所以[0, 10, 5, 5] => [0, 10] =>
function mergeSort(arr, fromIndex, length, argsArr) { if (length < 2) { let args = argsArr.pop() while (args) { if (args.length === 4) { argsArr.push([args[0], args[1]]) break } if (args.length === 2) { merge(arr, args[0], args[1]) args = argsArr.pop() } } if (args) { return mergeSort(arr, args[2], args[3], argsArr) } else { return } } argsArr.push([fromIndex, length, fromIndex + Math.floor(length / 2), length - Math.floor(length / 2)]) return mergeSort(arr, fromIndex, Math.floor(length / 2), argsArr) } function merge(arr, fromIndex, length) { let leftArr = arr.slice(fromIndex, fromIndex + Math.floor(length / 2)) let rightArr = arr.slice(fromIndex + Math.floor(length / 2), fromIndex + length) let i = 0, j = 0, orderedArr = [] while (true) { if (i === leftArr.length) { orderedArr.push(...rightArr.slice(j)) break } if (j === rightArr.length) { orderedArr.push(...leftArr.slice(i)) break } if (leftArr[i] < rightArr[j]) { orderedArr.push(leftArr[i]) i++ } if (rightArr[j] <= leftArr[i]) { orderedArr.push(rightArr[j]) j++ } } arr.splice(fromIndex, length, ...orderedArr) } let arr = [1, 5, 2, 11, 7, 3, 1, 6, 17, 10, 312, 312, 1, 1, 2323, 4, 56, 3, 14, 5543] mergeSort(arr, 0, arr.length, []) console.log(arr)三談,迭代版歸并排序
其中 merge 函數(shù)不變,修改 mergeSort 函數(shù)
function mergeSort(arr) { for (let size = 1; size < arr.length; size = size * 2) { for (let i = 0; i + size < arr.length; i = i + size * 2) { merge(arr, i, size * 2) } } } function merge(arr, fromIndex, length) { ... }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/92722.html
摘要:一談,原始的快速排序的位置已經(jīng)固定,不用在排二談,優(yōu)化后的快速排序適時(shí)的采用插入排序代碼略隨機(jī)化快速排序改變選擇主元的方式,從選擇末尾的元素,改為隨機(jī)選擇修改函數(shù)隨機(jī)索引與最后一個(gè)元素交換,其余不變?nèi)房炫哦家呀?jīng)排好序末 一談,原始的快速排序 function swap(arr, i, j) { let temp = arr[i] arr[i] = arr[j] ...
摘要:兩個(gè)單元素?cái)?shù)組的合并實(shí)際就是對(duì)這兩個(gè)數(shù)進(jìn)行了排序,即變?yōu)椋瑯釉賹?duì)后一組的兩個(gè)數(shù)歸并排序,即變?yōu)椋賹蓡卧獢?shù)組歸并成四單元數(shù)組即和歸并為。 前言 本周講解兩個(gè)50多年前發(fā)明,但今天仍然很重要的經(jīng)典算法 (歸并排序和快速排序) 之一 -- 歸并排序,幾乎每個(gè)軟件系統(tǒng)中都可以找到其中一個(gè)或兩個(gè)的實(shí)現(xiàn),并研究這些經(jīng)典方法的新變革。我們的涉及范圍從數(shù)學(xué)模型中解釋為什么這些方法有效到使這些算法...
摘要:排序之歸并排序簡(jiǎn)介歸并排序的算法是將多個(gè)有序數(shù)據(jù)表合并成一個(gè)有序數(shù)據(jù)表。如果參與合并的只有兩個(gè)有序表,則成為二路合并。對(duì)于一個(gè)原始的待排序數(shù)列,往往可以通過分割的方法來歸結(jié)為多路合并排序。 Java排序之歸并排序 1. 簡(jiǎn)介 歸并排序的算法是將多個(gè)有序數(shù)據(jù)表合并成一個(gè)有序數(shù)據(jù)表。如果參與合并的只有兩個(gè)有序表,則成為二路合并。對(duì)于一個(gè)原始的待排序數(shù)列,往往可以通過分割的方法來歸結(jié)為多路合...
閱讀 3081·2021-11-24 10:47
閱讀 3831·2021-11-02 14:43
閱讀 2228·2021-09-26 10:15
閱讀 2254·2021-09-08 09:35
閱讀 560·2019-08-30 12:45
閱讀 2781·2019-08-29 17:04
閱讀 3214·2019-08-26 14:05
閱讀 1259·2019-08-26 12:10