为合并排序选择数组的最小长度k,其中使用插入排序对子数组进行排序比标准合并排序更优化

时间:2013-08-07 13:14:09

标签: algorithm sorting mergesort insertion-sort

这是Cormen的算法导论中的一个问题。但这不是一个家庭作业问题而是自学。

有一个长度为n的数组。考虑对合并排序的修改,其中使用插入排序对每个长度为n/k的{​​{1}}子列表进行排序,然后使用合并机制进行合并,其中k是要确定的值。

kn之间的关系未知。数组的长度为kn的{​​{1}}个子列表表示k等于数组的n/k个元素。因此,n * (n/k)只是一个限制,在该限制下,停止使用与merge-sort一起使用的数组拆分,而是使用insert-sort,因为它的常数因子较小。

我能够做出数学证明,即修改后的算法在n最坏情况下工作。现在这本书继续对

  

根据Θ表示法找到k的最大值作为Θ(n*k + n*lg(n/k))的函数,对于该函数,此修改算法与标准合并排序具有相同的运行时间。我们应该如何在实践中选择k?

现在这让我想了很多时间,但我无法想出任何东西。我试着解决

k关系。我认为找到2个运行时间的相等会给我带来限制,可以使用简单的命中试验来检查更大。

我解决了这个问题

n

但它给了我n*k + n*lg(n/k) = n*lg(n)没有显示任何关系。有什么关系?我想我可能采取了错误的等式来寻找这种关系。

我可以实现算法,我想在n k + n lg(n/k) = n lg(n) k + lg(n/k) = lg(n) lg(2^k) + lg(n/k) = lg(n) (2^k * n)/k = n 2^k = k 函数here(Github link of merge sort implementation)中添加2 ^ k = k语句来调用插入排序就足够了。但是如何在现实生活中选择if (length_Array < k)

2 个答案:

答案 0 :(得分:2)

嗯,这是一个数学最小化问题,要解决它,我们需要一些基本的微积分。

我们需要找到k的{​​{1}}的值。

我们还应该检查边缘情况,d[n*k + n*lg(n/k)] / dk == 0k == n

k == 1提供最小结果的k值的候选者是所需范围内的最小值,因此是n*k + n*lg(n/k)的最佳值。


附件,求解导数方程式:

k

现在,我们有候选人:k = n,k = 1。对于k = n,我们得到d[n*k + n*lg(n/k)] / dk = d[n*k + nlg(n) - nlg(k)] / dk = n + 0 - n*1/k = n - n/k => n - n/k = 0 => n = n/k => 1/k = 1 => k = 1 ,因此我们得出最优O(n^2)k


请注意,我们在大Theta上找到了函数的派生词,而不是使用所需常量的精确复杂度函数。
在精确复杂度函数上执行此操作,所有常量可能会产生一些不同的最终结果 - 但解决它的方法几乎相同,只从不同的函数中获取派生词。

答案 1 :(得分:0)

也许k应该是lg(n)

theta(nk + nlog(n/k))有两个词,我们假设k>=1,所以第二个词小于nlog(n)

仅当k=lg(n)时,整个结果为theta(nlog(n))