Select(快速选择顺序统计量)原理及C++代码实现

SELECT算法利用快排中的partition思想来进行无序数组的快速选择。

寻找第i个顺序统计量可以简单理解为寻找第i小的元素。

该算法通过为partition选择一个好的主元,来保证Partition得到一个好的划分。

当然partition需要进行一些修改,把划分的主元也作为输入参数。

代码如下:(仅供参考)

 1 void InsertionSort(int * const begin, int * const end) {
 2     int i, j, key;
 3     for (i = 1; i < begin - end; ++i) {
 4         key = *(begin + i);
 5         for (j = i - 1; j >= 0 && (*(begin + j) > key); --j) {
 6             *(begin + j + 1) = *(begin + j);
 7         }
 8         *(begin + j + 1) = key;
 9     }
10 }
11 int Partition(int * const begin, int * const end, int x) {
12     int i = -1;
13     for (int j = 0; j < (end - begin); ++j) {
14         if (*(begin + j) < x) {
15             ++i;
16             swap(*(begin + i), *(begin + j));
17         }
18         else if (*(begin + j) == x && j != (end - begin - 1)) {
19             swap(*(begin + j), *(end - 1));
20             --j;
21         }
22     }
23     ++i;
24     swap(*(begin + i), *(end - 1));
25     return i;
26 }
27 
28 //返回第k小的元素,要求输入元素互异,最坏情况下时间复杂度为线性
29 int Select(int * const begin, int * const end, int k) {
30     if (end - begin == 1)
31         return *begin;
32     int n = end - begin;
33     int groupnum = n / 5; //groupnum个组,每组五个数
34     int medium[10000]; //因小于50000个数
35 
36     int i, j, t = groupnum;
37     for (i = 0, j = 0; t--; i += 5) {
38         InsertionSort(begin + i, begin + i + 5);
39         medium[j++] = *(begin + i + 2);
40     }
41     if (n > (groupnum * 5)) {
42         InsertionSort(begin + i, end);
43         medium[j++] = *(begin + i + (end - begin - i) / 2);
44     }
45 
46     int x = Select(medium, medium + j, (j + 1) / 2);
47     int m = Partition(begin, end, x) + 1;
48     if (m == k)
49         return x;
50     else if (m > k)
51         return Select(begin, begin + m - 1, k);
52     else
53         return Select(begin + m, end, k - m);
54 }
posted @ 2020-01-14 19:56  简讯  阅读(721)  评论(0编辑  收藏  举报