插入排序是一种很基本的排序,其复杂度为 O(n2) ,在大一学编程时没有多想,为什么不能利用二分查找改进为 O(nlogn)呢 ?
问题描述:
我们都知道插入排序就是在已有的序列上不断地插入新的元素,我们都知道二分查找的时间复杂度是
O(logn)
,二分查找的条件就是序列必须是有序的。而刚好可以用在插入排序的过程中使用,这样
n
个元素的排序复杂度就是
如上图,a为原始序列,b为已排序,假设我们进行到c出,通过二分查找找到下一个要插入的元素位置,确实可以在 O(logn) 的时间内完成。但是有个前提,如果我们要在对数时间内完成查找,那么前面已排序的序列需要满足call-by-rank,也就是说能够从下标读取,我们常用的存储方式如数组,就可以。但是问题来了,如果我们将数插入有序序列,那么该元素后面的数均需要往后移动一个单位,如果运气不好,这是最小的一个数,那么子序列所有元素都要往后移动,这个操作复杂度为 O(logn) .所以其实并不能减少复杂度。
你可能会问:如果用链表保存已排序的序列,在插入时不就是常数复杂度吗?但是此时就不能用二分查找了,而在链表中找到有插入位置,仍然需要 O(n) 复杂度。所以依然不能降低插入排序复杂度。