找出最小的k个数

•已知数组中的n个正数,找出其中最小的k个数。
•例如(4、5、1、6、2、7、3、8),k=4,则最小的4个数是1,2,3,4
•要求:
–高效;
–分析时空效率
•扩展:能否设计出适合在海量数据中实现上述运算?
 
 
 
方法一:
  1 //利用最大根堆实现最小k个节点

  2 //最大根堆特点:每个节点都比他左右孩子要大

  3 //调整最大堆的时间复杂度为O(lnK),因此该算法(问题)时间复杂度为O(nlnK).

  4 //思路:通过数组建堆

  5 //规律:第i个节点的左孩子为2i+1,右孩子为2i+2

  6 

  7 #include <iostream>

  8 

  9 using namespace std;

 10 int n;

 11 int K;

 12 int* stack;

 13 void InitStack();

 14 void ReStack(int parent);

 15 int baseJudge(int parent);

 16 int maxnode(int parent, int lc);

 17 int maxnode(int parent, int lc, int rc);

 18 

 19 //将最大数换给父节点(右子不存在) 返回替换前的最大值位置 未替换返回0

 20 int maxnode(int parent, int lc) {

 21     if (stack[parent] < stack[lc]) {

 22         int tmp = stack[parent];

 23         stack[parent] = stack[lc];

 24         stack[lc] = tmp;

 25         return lc;

 26     }

 27     return 0;

 28 }

 29 

 30 //将最大数换给父节点(左右子都存在) 返回替换前的最大值位置 未替换返回0

 31 int maxnode(int parent, int lc, int rc) {

 32     if (stack[parent] < stack[lc]) {

 33         int tmp = stack[parent];

 34         if (stack[lc] < stack[rc]) {

 35             stack[parent] = stack[rc];

 36             stack[rc] = tmp;

 37             return rc;

 38         }

 39         else {

 40             stack[parent] = stack[lc];

 41             stack[lc] = tmp;

 42             return lc;

 43         }

 44     }

 45     return 0;

 46 }

 47 

 48 //初始化堆

 49 void InitStack() {

 50     int lastpn = (K / 2 == 0) ? (K - 2) / 2 : (K - 1) / 2; //确定最后一个非叶子节点

 51     for (int parent = lastpn; parent > 0; parent--) {

 52         baseJudge(parent);

 53     }

 54 }

 55 

 56 //判断函数

 57 int baseJudge(int parent) {

 58     int lc = 2 * parent + 1;

 59     int rc = 2 * parent + 2;

 60     if (lc > K) return 0;

 61     int tmp;

 62     if (rc <= K) { //说明右子存在

 63         return maxnode(parent, lc, rc);

 64     }

 65     else {

 66         return maxnode(parent, lc);

 67     }

 68 }

 69 

 70 

 71 //递归判断

 72 void ReStack(int parent) {

 73     int p = baseJudge(parent);

 74     if (p) ReStack(p); //如果产生了交换,则从被交换的节点开始继续重建堆

 75 }

 76 

 77 

 78 int main(void) {

 79     cout << "输入K值:";

 80     cin >> K;

 81     stack = new int[K];

 82     cout << "数据个数:";

 83     cin >> n;

 84     cout << "依次输入:";

 85     for (int i = 0; i < K; i++)

 86         cin >> stack[i];

 87     InitStack();

 88     int tmp;

 89     for (int i = K; i < n; i++) {

 90         cin >> tmp;

 91         if (tmp < stack[0]) {

 92             stack[0] = tmp;

 93             ReStack(0);

 94         }

 95     }

 96     cout << "最小k个数:";

 97     for (int i = 0; i < K; i++) cout << stack[i] << " ";

 98     cout << endl;

 99     return 0;

100 }

101 

102 /*

103 样例输入:

104 4

105 20

106 7 5 1 10 3

107 6 11 4 7 9

108 25 13 47 6 20

109 13 47 68 32 1

110 

111 样例输出:

112 4 3 1 1

113 */

 

你可能感兴趣的:(找出最小的k个数)