找出最小的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 */

 

posted @ 2015-05-28 22:54  心若已冷  阅读(375)  评论(0编辑  收藏  举报