這是一道很經典的題目,有太多方法了,今天寫了兩種方法,分別是快排和堆排序ios
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 }