插入排序的运行时间

时间:2013-01-24 04:29:17

标签: c++ sorting c++11 time-complexity insertion-sort

for (int p=1; p < a.size(); p++) {
    int tmp = a[p];
    for(j=p; j>0 && tmp < a[j-1]; j--) {
        a[j] = a[j-1];
    }
    a[j] = tmp;
}

我无法找出插入排序的最坏情况。 因此,给定的数组按降序排列,我们希望按升序对其进行排序。

外部循环遍历数组。所以,它运行(n次)。上) int tmp=a[p] ----此语句执行n次。上) 内循环执行(1 + 2 + 3 + 4 + 5 + 6 + .... + n-1)次。为O(n ^ 2) a[j]= tmp --------此语句执行n次。为O(n)

我不确定在找到插入排序的运行时间之后该怎么办? 如果可以的话,纠正我的工作。 谢谢。

2 个答案:

答案 0 :(得分:2)

这是插入排序

的两行通用C ++ 11实现
template< typename ForwardIterator, typename Compare = std::less<typename std::iterator_traits<ForwardIterator>::value_type> >
void insertion_sort(ForwardIterator first, ForwardIterator last, Compare cmp = Compare())
{
        for (auto it = first; it != last; ++it) {
                auto const insertion = std::upper_bound(first, it, *it, cmp);
                std::rotate(insertion, it, std::next(it));
        }
}

该算法采用一系列元素(由两个迭代器firstlast给出)和一个比较函数(默认为可能内置operator<的元素指向的元素)。

主循环(元素数量的线性)保持子区间[first, it)排序,并重复搜索放置下一个元素的位置的插入点。它等同于你的主循环。它使用binary search(对数复杂度)来实现。在您的代码中,您使用反向线性搜索(具有线性复杂性但可能更好的缓存行为)。

找到插入点后,它只是rotates两个范围[insertion, it)[it, it+1),这意味着将当前元素交换到插入点。此旋转在到目前为止已排序的元素数量中是线性的。由于它嵌套在主循环中,因此插入排序的整体复杂性是二次的,即e。 O(N^2)。您的代码集成了交换和搜索插入点,但这并没有改变复杂性。

请注意,当输入范围已经排序时,插入点将始终等于it指向的元素,这意味着std::rotate根本不需要交换任何内容。一个足够智能和优化的编译器应该能够执行该优化。如果是这种情况,则对排序范围的插入排序具有线性复杂性。

选择排序的类似2行方法here

答案 1 :(得分:1)

外循环执行n次。

内循环的每次运行在0到p-1次之间执行,其中p从0变化到n。在更糟糕的情况下,它将执行p-1次。如果p在0到n之间变化,则平均而言p是n / 2。因此,内环的最坏情况复杂度为O(p-1)= O(n / 2-1)= O(n)。

除了循环之外,代码都是O(1)(最重要的是,内部循环中的代码是),所以它只是重要的循环。

O(n)* O(n)= O(n ^ 2)。

QED。

这大致是你自己给出的分析。