•已知数组中的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 */