快排與堆排的比較 std sort實現分析

2021-10-23 16:59:09 字數 1777 閱讀 7210

今天面試被問到了快排與堆排的應用場景,思考了一下只答上來了資料基本有序的情況下堆排優於快排以及topk問題選擇堆排,更進一步卻答不上來。

後來發現其實堆排序和快速排序平均複雜度雖然都是o(nlogn)但是在最差情況下堆排複雜度也是o(nlogn)這一點比快排要好。但是稍微實驗一下就能發現,堆排序雖然平均複雜度和快排是一樣的,但是它平均交換元素次數是要比快排高出很多的,所以雖然時間開銷都是nlogn但是堆排序的常數要大出不少,所以在元素基本無續的情況下快排速度還是會快一些。

還有就是在資料量逐漸增大的情況下,堆排序的交換元素次數隨著資料量的增大而增大,所以效能開銷也會越來越大,跟快速排序的差距就慢慢拉開了。所以在資料量較大的情況下選擇快速排序是乙個比較正確的選擇。

這裡不得不提一下stl演算法中的std::sort這個排序函式了。這個標準庫的排序演算法還是十分高效的,底層實現是插入排序 + 快排 + 堆排。

首先講一下為什麼插入排序平均時間複雜度為o(n^2)的排序演算法也能上榜吧。

插入排序:

插入排序雖然平均時間複雜度不是很樂觀,但是在元素基本有序的情況下它的時間複雜度是接近o(n)的

快速排序:

我們都知道快速排序是基於分治的思想,需要通過遞迴來實現。當分段很小的情況下,快速排序還需要進行遞迴來交換資料,而遞迴需要將函式壓棧,出棧,這一系列額外的負荷。所以在這種情況下快排的缺點就會被放大。

std::sort集合了三種演算法的優點:

所以std::sort就是採用這種思路來實現的。下面貼上**

template inline void sort(randomaccessiterator first, randomaccessiterator last) 

}template void __introsort_loop(randomaccessiterator first,

randomaccessiterator last, t*,

size depth_limit)

--depth_limit;

randomaccessiterator cut = __unguarded_partition

(first, last, t(__median(*first, *(first + (last - first)/2),

*(last - 1))));

__introsort_loop(cut, last, value_type(first), depth_limit);

last = cut;

}}// 分割 快排部分

template randomaccessiterator __unguarded_partition(randomaccessiterator first,

randomaccessiterator last,

t pivot)

} // 堆排部分

template void __partial_sort(randomaccessiterator first, randomaccessiterator middle,

randomaccessiterator last, t*, compare comp)

template inline void partial_sort(randomaccessiterator first,

randomaccessiterator middle,

randomaccessiterator last, compare comp)

快排與堆排

本文複習一下快速排序和堆排序 2 種排序演算法 為了多快好省地刷 leetcode 主要思想 通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。時間複...

快排和堆排

一 快速排序 最常用的排序演算法,速度通常也是最快的。時間複雜度 o nlogn 最壞 o n 2 空間複雜度 o nlgn 不穩定 比如 5 3 3 4 3 8 9 10 11 這個序列,在中樞元素5和3交換就會把元素3的穩定性打亂 實現原理 快排主要是通過選擇乙個關鍵值作為基準值。比基準值小的都...

快排 歸併 堆排

快排 include include include includeusing namespace std void quicksort vector a,int l,int r 終止遞迴的條件,子串行長度為1 int mid low high low 2 取得序列中間的元素 mergesort a...