最坏情况下保证时间复杂度为N*logN的快速排序

来源:互联网 发布:淘宝助理有什么功能 编辑:程序博客网 时间:2024/04/25 18:38
快速排序的平均时间复杂度是N*logN,同时其也是实践已知的最快的通用排序算法,但是其最坏情况的时间复杂度依然是N的平方,但是只要我们对快速排序算法稍作修改,就可以保证其最坏情况的时间复杂度也是N*logN。
思路就是在递归达到一定深度后,将快速排序的递归调用改为堆排序,下面是我实现的代码,我将递归深度设置为2*ln(N),这个值也是很多算法书籍推荐的值。

#include <iostream>#include <algorithm>#include <utility>#include <cstdlib>#include <ctime>#include <random>#include <limits>#include <cmath>#include <chrono>#include <cassert>inline int left_child(int rt) { return 2 * rt + 1; }void percolate_down(int *a,int rt,int sz){int tmp = a[rt];int child = left_child(rt);for(;child < sz;rt = child,child = left_child(rt)){if(child + 1 < sz && a[child] < a[child + 1])++child;if(tmp < a[child])a[rt] = a[child];elsebreak;}a[rt] = tmp;return;}void Hsort(int *a,int sz){for(int i = sz / 2 - 1; i >= 0; --i)percolate_down(a,i,sz);for(int j = sz - 1; j > 0; --j){std::swap(a[0],a[j]);percolate_down(a,0,j);}return;}void ssort3(int *a,int s, int e){int m = (s + e) / 2;if(a[e] < a[m]) std::swap(a[e],a[m]);if(a[e] < a[s]) std::swap(a[e],a[s]);if(a[m] < a[s]) std::swap(a[m],a[s]);return;}int elect_pivot(int *a,int s,int e){ssort3(a,s,e);std::swap(a[(s + e) /2],a[e]);return a[e];}void qsort(int *a,int s,int e,int depth){if(e - s < 3){ssort3(a,s,e);return;}int i = s;int j = e;int p = elect_pivot(a,s,e);while(true){while(a[++i] < p);while(a[--j] > p);if(i < j)std::swap(a[i],a[j]);elsebreak;}std::swap(a[i],a[e]);if(depth > 0){qsort(a,s,i - 1,depth - 1);qsort(a,i + 1,e,depth - 1);}else{Hsort(a + s,i - s + 1);Hsort(a + i + 1,e - i);}return;}void Qsort(int *a,int sz){int depth = 2 * log2(sz);qsort(a,0,sz - 1,depth);return;}int da(int *a,int n){for(int i = 0; i < n; ++i){std::cout << a[i] << " ";}std::cout << std::endl;return 0;}int gen(int *a,int n){std::default_random_engine dre(time(NULL));std::uniform_int_distribution<int> uid(std::numeric_limits<int>::min(),std::numeric_limits<int>::max());while(--n >= 0){a[n] = uid(dre);}return 0;}bool chk(int *a,int n){for(int i = 0;i < n - 1; ++i)if(a[i] > a[i + 1])return false;return true;}int main(int argc,char *argv[]){if(argc != 2 && argc != 3){return 0;}int loop = atoi(argv[1]);int n = 10;if(argc == 3)n = atoi(argv[2]);int *a = new int [n];while(--loop >= 0){gen(a,n);//da(a,n);auto start = std::chrono::steady_clock::now();Qsort(a,n);auto end = std::chrono::steady_clock::now();assert(true == chk(a,n));//da(a,n);std::cout << std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count()  << "s" << std::endl;}delete [] a;return 0;}


阅读全文
0 0
原创粉丝点击