接着昨天的寫,裏面的代碼包含昨天的ios
1 #include <iostream> 2 using namespace std; 3 #define N 50 4 5 //初始化數組 6 int a[] = {6, 2, 3, 4, 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 a[] = {6, 2, 3, 9, 4, 10, 1, 20, 40, 5}; 10 int n = 10; 11 int K = 4; 12 13 //快速排序,o(nlogn),最應該想到的思路,排好序要多大數就輸出多大數 14 /* 15 partition就是挖第一個洞,從後往前找,找到,挖起來,把前面的洞埋上,再從前日後找,找到,挖起來,把後面的洞埋上,直到最後,high=low了,把這個洞補上 16 */ 17 int partition(int* p, int low, int high) 18 { 19 int i; 20 int pivot; 21 //把第一個數拿出來,挖個洞 22 pivot = p[low]; 23 while (low < high) 24 { 25 //從後往前找,找到比pivot小的值 26 while (low < high && p[high] <= pivot) 27 high--; 28 //而後後面的數埋上前面的洞 29 //Note這裏無須再加個if,由於即便相同了,那我再作一步也無妨,並且也無須把low指針往上移,由於,到時候我能夠再判斷一次,仍是能夠移動的 30 p[low] = p[high]; 31 32 //從前日後找,找到比pivot大的值,而後把前面的數埋上 33 while (low < high && p[low] >= pivot) 34 low++; 35 p[high] = p[low]; 36 } 37 //這裏low和high已經相同了,因此也能夠寫成p[high]=pivot,這一步就是把洞埋上 38 p[low] = pivot; 39 return low; 40 } 41 /* 42 其實,兩個能夠寫一塊兒,可是,分開寫更清楚 43 quickSort函數就是當low<high時,進行一次partition,而後再對分開的兩塊進行quickSort 44 */ 45 void quickSort(int* p, int low, int high) 46 { 47 if(low < high) 48 { 49 int breakpoint = partition(p, low, high); 50 quickSort(p, low, breakpoint - 1); 51 quickSort(p, breakpoint + 1, high); 52 } 53 } 54 55 //堆排序, o(nlogk),考慮到只需取K大的數,那就無須對n個數都排序,只需記錄下k個便可 56 int heap[N]; 57 /* 58 //這裏有點疑問哦,考慮到heap數組可能比較大,因此想定義成全局變量,但是這樣就沒必要傳遞參數勒,定義成局部變量,參數又太多 59 目前定義成全局變量 60 input: lastIndex指heap數組要插入的value的位置(是要插入的位置哦); value指要插入的數字 61 function: heap數組是從index=0開始儲存的,就是把value儲存heap數組內,並進行相應的調整,符合最大堆的性質 62 */ 63 void MaxHeapPush(int lastIndex, int value) 64 { 65 //把value放在堆的末尾 66 heap[lastIndex] = value; 67 //記錄下末尾的index 68 int index = lastIndex; 69 // 不斷向上調整 70 while (index) 71 { 72 //若比上面的大,就交換 73 if (heap[index] > heap[(index - 1) / 2]) 74 { 75 int temp = heap[index]; 76 heap[index] = heap[(index - 1) / 2]; 77 heap[(index - 1) / 2] = temp; 78 } 79 //不然,說明已經調整好了,當即中止 80 else 81 break; 82 //若沒有break出來,就要一直調整了,因此index要變更 83 index = (index - 1) / 2; 84 } 85 } 86 /* 87 input: 88 p數組要初始化數組,提供數據的 89 n表示該數組的長度,c就是麻煩,連長度都要傳入 90 heapSize表示要維護的堆的大小,Note,必定要大於K哦 91 */ 92 void MaxHeapInit(int *p, int n, int heapSize) 93 { 94 int i, lastIndex; 95 lastIndex = 0; 96 for (i = 0; i < n; i++) 97 { 98 //依次插入 99 MaxHeapPush(lastIndex, p[i]); 100 // 若比預約好的堆的大小小的話,最後一個value的值就要增長了 101 if (lastIndex < heapSize) 102 lastIndex++; 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 //快排的優化,時間複雜度仍是o(nlogn),可是時間會大大減小 143 /* 144 因爲只須要知道前K大數,不必把全部的數都進行排序,而快排的思想就是找到一個值一分爲二,因此,咱們正好利用這一點 145 有了以前寫好的partition函數,實現起來就就是方便!! 146 */ 147 void optQuickSort(int* p, int low, int high, int k) 148 { 149 int cur = partition(p, low, high); 150 if (cur - low > k) 151 optQuickSort(p, low, cur - 1, k); 152 else if (cur - low < k - 1) 153 optQuickSort(p, cur + 1, high, k - (cur - low + 1)); 154 } 155 156 //部分排序,o(nK) 157 /* 158 這本應該最新想到的呀,若K=1,其實就只需找最大值就行了 159 當K<logn時,纔有用武之地呀 160 */ 161 void partSort(int* p, int n, int k) 162 { 163 int i, j, maxI, temp; 164 for (i = 0; i < k; i++) 165 { 166 maxI = i; 167 for (j = i; j < n; j++) 168 { 169 if (p[j] > p[maxI]) 170 maxI = j; 171 } 172 if (i != maxI) 173 { 174 temp = p[maxI]; 175 p[maxI] = p[i]; 176 p[i] = temp; 177 } 178 } 179 } 180 181 //時間換空間的辦法,o(n) 182 /* 183 適用於整數,且範圍不是很大的狀況 184 若是沒有重複的話,還能夠用bit數組 185 */ 186 void findCount(int*p, int n, int k) 187 { 188 int count[N] = {0}; 189 int i, j, sumCount; 190 //首先先對輸入的元素進行計數 191 for (i = 0; i < n; i++) 192 { 193 count[p[i]] += 1; 194 } 195 sumCount = 0; 196 for (i = N - 1; i > 0; i--) 197 { 198 sumCount += count[i]; 199 //若累計最大的數大於k了,就把多餘的部分去掉,把最大的k個數輸出 200 if (sumCount > k) 201 { 202 for (j = 0; j < count[i] - (sumCount - k); j++) 203 cout<<i<<" "; 204 break; 205 } 206 //若累計的沒有到達K,那就直接輸出啦 207 else 208 { 209 for (j = 0; j < count[i]; j++) 210 cout<<i<<" "; 211 } 212 } 213 } 214 215 int main() 216 { 217 int i, j; 218 for (i = 0; i < n; i++) 219 cout<<a[i]<<" "; 220 cout<<endl; 221 /* 222 //快排,若取前K大的數,只需從末尾到前輸出K個數便可 223 quickSort(a, 0, n - 1); 224 for (i = 0; i < n; i++) 225 cout<<a[i]<<" "; 226 cout<<endl; 227 228 //注意這裏之因此乘以2,是由於只維護K個數字的堆,不能獲得前K個大的數!! 229 MaxHeapInit(a, n, K * 2 - 1); 230 for (i = 0; i < n; i++) 231 cout<<heap[i]<<" "; 232 cout<<endl; 233 // 輸出,這裏的lastIndex是變化的哦,由於以前維護的2 * K - 1的堆,因此這裏也應該是2 * K - 1 234 for (i = 0; i < K; i++) 235 cout<<MaxHeapPop(2 * K - 1 - i)<<" "; 236 cout<<endl; 237 238 optQuickSort(a, 0, n - 1, K); 239 240 partSort(a, n, K); 241 for (i = 0; i < n; i++) 242 cout<<a[i]<<" "; 243 cout<<endl; 244 */ 245 findCount(a, n, K); 246 system("pause"); 247 return 0; 248 }