這裏的一個兩行通用的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));
}
}
該算法需要一個範圍內的元素(由兩個迭代first
和last
給出)和比較功能(這是默認指向可能內置的operator<
)。
主循環(元素數量中的線性)保持子區間[first, it)
的排序,並重復搜索插入點放置下一個元素的位置。這相當於你的主循環。它是這樣做的,具有binary search(對數複雜度)。在你的代碼中,你使用反向線性搜索(有線性複雜性但可能更好的緩存行爲)。
找到插入點後,它簡單地rotates兩個範圍[insertion, it)
和[it, it+1)
,這意味着將當前元素交換到插入點。這種旋轉在迄今爲止已排序的元素的數量上是線性的。由於它嵌套在主循環中,插入排序的整體複雜度是二次的,即e。 O(N^2)
。您的代碼集成了交換和搜索插入點,但這並沒有改變複雜性。
請注意,當輸入範圍已經排序時,插入點將始終等於it
指向的元素,這意味着std::rotate
不必交換任何東西。一個足夠聰明和優化的編譯器應該能夠執行該優化。如果是這種情況,排序範圍上的插入排序具有線性複雜度。
給出了類似的選擇排序的兩行方法here。
最差情況下的運行時間爲O(n^2)。但我不知道如何得到它。 –