这是一道很经典的题目,有太多方法了,今天写了两种方法,分别是快排和堆排序
1 #include <iostream> 2 using namespace std; 3 #define N 25 4 5 //初始化数组 6 //int a[] = {6, 2, 3, 9, 4, 3, 1, 2, 4, 4}; 7 //int a[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 8 int a[] = {1, 2, 3, 4, 5, 6}; 9 int n = 6; 10 int K = 3; 11 12 //快速排序,o(nlogn),最应该想到的思路,排好序要多大数就输出多大数 13 /* 14 partition就是挖第一个洞,从后往前找,找到,挖起来,把前面的洞埋上,再从前往后找,找到,挖起来,把后面的洞埋上,直到最后,high=low了,把这个洞补上 15 */ 16 int partition(int* p, int low, int high) 17 { 18 int i; 19 int pivot; 20 //把第一个数拿出来,挖个洞 21 pivot = p[low]; 22 while (low < high) 23 { 24 //从后往前找,找到比pivot小的值 25 while (low < high && p[high] >= pivot) 26 high--; 27 //然后后面的数埋上前面的洞 28 //Note这里无须再加个if,因为即使相同了,那我再做一步也无妨,而且也无须把low指针往上移,因为,到时候我可以再判断一次,还是可以移动的 29 p[low] = p[high]; 30 31 //从前往后找,找到比pivot大的值,然后把前面的数埋上 32 while (low < high && p[low] <= pivot) 33 low++; 34 p[high] = p[low]; 35 } 36 //这里low和high已经相同了,所以也可以写成p[high]=pivot,这一步就是把洞埋上 37 p[low] = pivot; 38 return low; 39 } 40 /* 41 其实,两个可以写一起,但是,分开写更清楚 42 quickSort函数就是当low<high时,进行一次partition,然后再对分开的两块进行quickSort 43 */ 44 void quickSort(int* p, int low, int high) 45 { 46 if(low < high) 47 { 48 int breakpoint = partition(p, low, high); 49 quickSort(p, low, breakpoint - 1); 50 quickSort(p, breakpoint + 1, high); 51 } 52 } 53 54 //堆排序, o(nlogk),考虑到只需取K大的数,那就无须对n个数都排序,只需记录下k个即可 55 int heap[N]; 56 /* 57 //这里有点疑问哦,考虑到heap数组可能比较大,所以想定义成全局变量,可是这样就不必传递参数勒,定义成局部变量,参数又太多 58 目前定义成全局变量 59 input: lastIndex指heap数组要插入的value的位置(是要插入的位置哦); value指要插入的数字 60 function: heap数组是从index=0开始储存的,就是把value储存heap数组内,并进行相应的调整,符合最大堆的性质 61 */ 62 void MaxHeapPush(int lastIndex, int value) 63 { 64 //把value放在堆的末尾 65 heap[lastIndex] = value; 66 //记录下末尾的index 67 int index = lastIndex; 68 // 不断向上调整 69 while (index) 70 { 71 //若比上面的大,就交换 72 if (heap[index] > heap[(index - 1) / 2]) 73 { 74 int temp = heap[index]; 75 heap[index] = heap[(index - 1) / 2]; 76 heap[(index - 1) / 2] = temp; 77 } 78 //否则,说明已经调整好了,立即停止 79 else 80 break; 81 //若没有break出来,就要一直调整了,所以index要变动 82 index = (index - 1) / 2; 83 } 84 } 85 /* 86 input: 87 p数组要初始化数组,提供数据的 88 n表示该数组的长度,c就是麻烦,连长度都要传入 89 heapSize表示要维护的堆的大小,Note,一定要大于K哦 90 */ 91 void MaxHeapInit(int *p, int n, int heapSize) 92 { 93 int i, lastIndex; 94 lastIndex = 0; 95 for (i = 0; i < n; i++) 96 { 97 //依次插入 98 MaxHeapPush(lastIndex, p[i]); 99 // 若比预定好的堆的大小小的话,最后一个value的值就要增加了 100 if (lastIndex < heapSize) 101 lastIndex++; 102 } 103 } 104 105 /* 106 input: lastIndex是要删除的value的位置(这里千万要注意,其实,跟前面的lastIndex有点不一样) 107 */ 108 int MaxHeapPop(int lastIndex) 109 { 110 // 交换头尾value 111 int temp, i; 112 temp = heap[0]; 113 heap[0] = heap[lastIndex]; 114 heap[lastIndex] = temp; 115 // 向下调整 116 i = 0; 117 int child = 2 * i + 1; 118 while (child < lastIndex) 119 { 120 //若有右孩子节点,且右节点比左节点大,那要只需要比较右节点即可 121 if (child + 1 < lastIndex && heap[2 * i + 2] > heap[2 * i + 1]) 122 { 123 child = child + 1; 124 } 125 //若孩子节点比父节点大,两个节点交换 126 if (heap[child] > heap[i]) 127 { 128 temp = heap[child]; 129 heap[child] = heap[i]; 130 heap[i] = temp; 131 } 132 //否则说明已经有序,停止 133 else 134 break; 135 // 变化孩子节点的index 136 child = 2 * i + 1; 137 } 138 // 返回末尾value 139 return heap[lastIndex]; 140 } 141 142 int main() 143 { 144 int i, j; 145 for (i = 0; i < n; i++) 146 cout<<a[i]<<" "; 147 cout<<endl; 148 /* 149 //快排,若取前K大的数,只需从末尾到前输出K个数即可 150 quickSort(a, 0, n - 1); 151 for (i = 0; i < n; i++) 152 cout<<a[i]<<" "; 153 cout<<endl; 154 */ 155 156 //注意这里之所以乘以2,是因为只维护K个数字的堆,不能得到前K个大的数!! 157 MaxHeapInit(a, n, K * 2 - 1); 158 for (i = 0; i < n; i++) 159 cout<<heap[i]<<" "; 160 cout<<endl; 161 162 // 输出,这里的lastIndex是变化的哦,因为之前维护的2 * K - 1的堆,所以这里也应该是2 * K - 1 163 for (i = 0; i < K; i++) 164 cout<<MaxHeapPop(2 * K - 1 - i)<<" "; 165 cout<<endl; 166 167 system("pause"); 168 return 0; 169 }