码迷,mamicode.com
首页 > 其他好文 > 详细

topK问题最小堆和快排哪个快

时间:2020-03-28 09:15:26      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:count   resize   次数   font   size   open   而且   gif   double   

最近一直纠结这个问题。看了很多帖子,决定自己写个例子,实测结果如下:

总数1万个取最大100,快排略快,最小堆偶尔快。

总数10万个取最大100,最小堆略快,快排偶尔快。

总数100万个取最大100,最小堆完胜,快排没戏,而且最小堆大概快了2倍。

总数1000万个取最大100,最小堆完虐,快排没戏,而且最小堆快了大概2倍。

结论:最小堆比快排优秀。

原因:

1.速度确实快。

2.最小堆不需要打乱原数据顺序,而快排会打乱。(并不是快的原因,而是最小堆的优点)

3.如果内存有限,无法加载所有数据,则最小堆快。

 

技术图片
  1 #include <vector>
  2 #include <iostream>
  3 #include <time.h>
  4 #include <random>
  5 using namespace std;
  6 
  7 //改良版部分区域快排
  8 int Partition(vector<int>& arr, int low, int high)
  9 {
 10     int pivokey = arr[low];//因为arr已经是随机数了,不需要再有分区算法,反而会慢
 11     while (low < high)
 12     {
 13         while (low < high && arr[high] <= pivokey) --high;
 14         arr[low] = arr[high];
 15         while (low < high && arr[low] >= pivokey) ++low;
 16         arr[high] = arr[low];
 17     }
 18     arr[low] = pivokey;
 19     return low;
 20 }
 21 int TopK_Qsort(vector<int>& arr, int start, int end, int k)
 22 {
 23     int index = 0;
 24     if (start < end)
 25     {
 26         index = Partition(arr, start, end);
 27         if (index < k)//还要从index的右边找k-index个数
 28         {
 29             index = TopK_Qsort(arr, index + 1, end, k);
 30         }
 31         else if (index > k)//k个数都在Index的左边
 32         {
 33             index = TopK_Qsort(arr, start, index - 1, k);
 34         }
 35     }
 36     return index;
 37 }
 38 
 39 //小顶堆化
 40 void HeapAdjust(vector<int>& nums, int pos)
 41 {
 42     for (int i = 2 * pos + 1; i < nums.size(); i = 2 * i + 1)
 43     {
 44         if (i<nums.size() - 1 && nums[i]>nums[i + 1])
 45             i++;
 46         if (nums[i] >= nums[pos])
 47             break;
 48         swap(nums[i], nums[pos]);
 49         pos = i;
 50     }
 51 }
 52 void TopK_Heap(vector<int>& arr, int k)
 53 {
 54     if (arr.size() <= k)
 55         return;
 56     vector<int> box;
 57     box.resize(k);
 58     for (int i = 0; i < k; i++)
 59         box[i] = arr[i];
 60     for (int i = box.size() / 2; i >= 0; i--)
 61         HeapAdjust(box, i);
 62     for (int i = k; i < arr.size(); i++)
 63     {
 64         if (arr[i] > box[0])
 65         {
 66             box[0] = arr[i];
 67             HeapAdjust(box, 0);
 68         }
 69     }
 70 }
 71 
 72 int main()
 73 {
 74     int nCounterA = 0;    //代表小顶堆胜出次数
 75     int nCounterB = 0;    //代表快排胜出次数
 76     int nCounterC = 0;    //平手
 77     for (int t = 750; t<= 770;++t)//t是随机种子,保证每次待排序列表里是新的随机数
 78     {
 79         default_random_engine e;
 80         e.seed(t);                
 81 
 82         int nTotal = 10000;            //总共有多少个数
 83         int nTopK = 100;                //前TOPK个数
 84         //-------------------填充随机数-----------------------
 85         vector<int> vecQsortResource;
 86         vecQsortResource.reserve(nTotal);
 87         vector<int> vecHeapResource;
 88         vecHeapResource.reserve(nTotal);
 89         for (int i = nTotal; i > 0; i--)
 90         {
 91             vecQsortResource.push_back(e() % nTotal);
 92         }
 93         vecHeapResource = vecQsortResource;
 94 
 95         //-------------------两种算法开始计算-----------------------
 96         clock_t start, finish;
 97         start = clock();
 98         TopK_Heap(vecHeapResource, nTopK);
 99         finish = clock();
100         double nRes1 = (double)(finish - start);
101         //cout << "\n小顶堆的运行时间为" << nRes1 / CLOCKS_PER_SEC << "秒!" << endl;
102 
103         start = clock();
104         TopK_Qsort(vecQsortResource, 0, nTotal - 1, nTopK - 1);
105         finish = clock();
106         double nRes2 = (double)(finish - start);
107         //cout << "\n快排的运行时间为" << nRes2 / CLOCKS_PER_SEC << "秒!" << endl;
108 
109         if (nRes1 < nRes2)
110         {
111             nCounterA++;
112         }
113         else if (nRes1 > nRes2)
114         {
115             nCounterB++;
116         }
117         else
118         {
119             nCounterC++;
120         }
121     }
122 
123     cout << nCounterA << endl;    //代表小顶堆胜出次数
124     cout << nCounterB << endl;    //代表快排胜出次数
125     cout << nCounterC << endl;    //平手
126     return 0;
127 }
测试代码

 

topK问题最小堆和快排哪个快

标签:count   resize   次数   font   size   open   而且   gif   double   

原文地址:https://www.cnblogs.com/workharder/p/12585363.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!