2.3-6 题目大意是结合二分查找来改进插入排序,能否使插入排序的最坏运行时间改善至O(nlgn)?
在插入排序中,将数据插入已排序的序列中使用的是反向遍历,最坏情况是完全遍历,使用二分查找可以减少搜索应该插入位置的时间。而二分查找的时间为O(lgn),放入外层for(1-n)的遍历中,那么看似时间变为了O(nlgn)。其实不然,这要理解插入排序的时间花费不仅仅是在搜索插入位置上,更多的是在插入后老数据的移动上,二分查找虽然减少了查找位置的比较次数,但是并没有减少数据的移动,所以移动数据的代价仍为O(n)。因此,结合二分查找不能达到题目要求的性能改善。
思考题2-1
尽管合并排序最坏运行情况为O(n),插入排序最坏运行情况为O(n^2),然而插入排序的常数因子使得在n较小时,运行得更快。考虑在合并排序中,当子问题足够小时,采用插入排序。使用插入排序策略,对n/k个长度为k的子序列进行排序,然后在用标准的合并机制将它们合并。
a)证明最坏情况n/k个子序列可以用插入排序在O(nk)的时间内完成。
b)证明子列表可以在O(nlg(n/k))时间内完成合并。
c)修改后运行时间为O(nk+nlg(n/k)),要与标准合并排序同样的渐进时间,则k的最大渐近值为多少?(以O形式表示)
d)实践中,k的值如何选取?
c) The modified algorithm has the same asymptotic running time as standard merge sort when (nk + n lg ( n / k )) = (n lg n ) . The largest asymptotic value of k as a function of n that satis fies this condition is k = (lg n ) .To see why, first observe that k cannot be more than (lg n ) (i.e., it canít have a higher-order term than lg n ), for otherwise the left-hand expression wouldn‘t be (n lg n ) (because it would have a higher-order term than n lg n ). So all we need to do is verify that k = (lg n ) works, which we can do by plugging k = lg n into (nk + n lg ( n / k )) = (nk + n lg n − n lg k ) to get (n lg n + n lg n − n lg lg n ) = (2n lg n − n lg lg n ), which, by taking just the high-order term and ignoring the constant coef ficient, equals (n lg n ) .
d) 实践中,k的值应该选为使得插入排序比合并排序快的最大的数组长度。很容易理解,假设k=1,那么退化为标准合并排序,那么要提高效率需放大k,k放大到使得array[k]使用插入排序比合并排序快,而array[k+1]的插入排序效率不如或等于合并排序。