尋找最大的K個數(下)

接着昨天的寫,裏面的代碼包含昨天的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 }
相關文章
相關標籤/搜索