We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
归并排序(Merge Sort)是建立归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用
将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序
例如对于含有 n 个记录的无序表,首先默认表中每个记录各为一个有序表(只不过表的长度都为 1)
n
然后进行两两合并,使 n 个有序表变为n/2 个长度为 2 或者 1 的有序表(例如 4 个小有序表合并为 2 个大的有序表)
n/2
通过不断地进行两两合并,直到得到一个长度为 n 的有序表为止
例如对无序表{49,38,65,97,76,13,27}进行归并排序分成了分、合两部分:
如下图所示:
归并合过程中,每次得到的新的子表本身有序,所以最终得到有序表
上述分成两部分,则称为二路归并,如果分成三个部分则称为三路归并,以此类推
关于归并排序的算法思路如下:
分:把数组分成两半,再递归对子数组进行分操作,直至到一个个单独数字
合:把两个数合成有序数组,再对有序数组进行合并操作,直到全部子数组合成一个完整的数组
用代码表示则如下图所示:
function mergeSort(arr) { // 采用自上而下的递归方法 const len = arr.length; if(len < 2) { return arr; } let middle = Math.floor(len / 2), left = arr.slice(0, middle), right = arr.slice(middle); return merge(mergeSort(left), mergeSort(right)); } function merge(left, right) { const result = []; while (left.length && right.length) { if (left[0] <= right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } while (left.length) result.push(left.shift()); while (right.length) result.push(right.shift()); return result; }
上述归并分成了分、合两部分,在处理分过程中递归调用两个分的操作,所花费的时间为2乘T(n/2),合的操作时间复杂度则为O(n),因此可以得到以下公式:
T(n/2)
O(n)
总的执行时间 = 2 × 输入长度为n/2的sort函数的执行时间 + merge函数的执行时间O(n)
sort
merge
当只有一个元素时,T(1) = O(1)
T(1) = O(1)
如果对T(n) = 2 * T(n/2) + O(n) 进行左右 / n的操作,得到 T(n) / n = (n / 2) * T(n/2) + O(1)
T(n) = 2 * T(n/2) + O(n)
T(n) / n = (n / 2) * T(n/2) + O(1)
现在令 S(n) = T(n)/n,则S(1) = O(1),然后利用表达式带入得到S(n) = S(n/2) + O(1)
S(n) = T(n)/n
S(1) = O(1)
S(n) = S(n/2) + O(1)
所以可以得到:S(n) = S(n/2) + O(1) = S(n/4) + O(2) = S(n/8) + O(3) = S(n/2^k) + O(k) = S(1) + O(logn) = O(logn)
S(n) = S(n/2) + O(1) = S(n/4) + O(2) = S(n/8) + O(3) = S(n/2^k) + O(k) = S(1) + O(logn) = O(logn)
综上可得,T(n) = n * log(n) = nlogn
T(n) = n * log(n) = nlogn
关于归并排序的稳定性,在进行合并过程,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也不会交换,由此可见归并排序是稳定的排序算法
在外排序中通常使用排序-归并的策略,外排序是指处理超过内存限度的数据的排序算法,通常将中间结果放在读写较慢的外存储器,如下分成两个阶段:
例如,使用100m内存对900m的数据进行排序,过程如下:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
一、是什么
归并排序(Merge Sort)是建立归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用
将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序
例如对于含有
n
个记录的无序表,首先默认表中每个记录各为一个有序表(只不过表的长度都为 1)然后进行两两合并,使
n
个有序表变为n/2
个长度为 2 或者 1 的有序表(例如 4 个小有序表合并为 2 个大的有序表)通过不断地进行两两合并,直到得到一个长度为
n
的有序表为止例如对无序表{49,38,65,97,76,13,27}进行归并排序分成了分、合两部分:
如下图所示:
归并合过程中,每次得到的新的子表本身有序,所以最终得到有序表
上述分成两部分,则称为二路归并,如果分成三个部分则称为三路归并,以此类推
二、如何实现
关于归并排序的算法思路如下:
分:把数组分成两半,再递归对子数组进行分操作,直至到一个个单独数字
合:把两个数合成有序数组,再对有序数组进行合并操作,直到全部子数组合成一个完整的数组
用代码表示则如下图所示:
上述归并分成了分、合两部分,在处理分过程中递归调用两个分的操作,所花费的时间为2乘
T(n/2)
,合的操作时间复杂度则为O(n)
,因此可以得到以下公式:总的执行时间 = 2 × 输入长度为
n/2
的sort
函数的执行时间 +merge
函数的执行时间O(n)
当只有一个元素时,
T(1) = O(1)
如果对
T(n) = 2 * T(n/2) + O(n)
进行左右 / n的操作,得到T(n) / n = (n / 2) * T(n/2) + O(1)
现在令
S(n) = T(n)/n
,则S(1) = O(1)
,然后利用表达式带入得到S(n) = S(n/2) + O(1)
所以可以得到:
S(n) = S(n/2) + O(1) = S(n/4) + O(2) = S(n/8) + O(3) = S(n/2^k) + O(k) = S(1) + O(logn) = O(logn)
综上可得,
T(n) = n * log(n) = nlogn
关于归并排序的稳定性,在进行合并过程,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也不会交换,由此可见归并排序是稳定的排序算法
三、应用场景
在外排序中通常使用排序-归并的策略,外排序是指处理超过内存限度的数据的排序算法,通常将中间结果放在读写较慢的外存储器,如下分成两个阶段:
例如,使用100m内存对900m的数据进行排序,过程如下:
参考文献
The text was updated successfully, but these errors were encountered: