c语言实现分治法求第K大元素(详细解释)
生活随笔
收集整理的這篇文章主要介紹了
c语言实现分治法求第K大元素(详细解释)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
注:本文不對快速排序作任何解釋,建議在對快速排序有一定了解后再閱覽
一、問題分析
? ? ? ?最簡單的做法應該是直接選擇先將集合排序(比如快速排序),然后直接以k為下標從有序集合中獲取。但是這樣做時間復雜度其實是比較大的。如果要想要提升一下效率,可以考慮在快速排序的原理下稍微做點修改。
二、修改快排
1、主元素的位置特殊性
? ? ? ?在快速排序中,第一步是選取主元素(這里記為x),然后將小于主元素x的數放在x左邊,剩下的所有大于x的數放在x右邊。記x的下標為x_index,這里不難發現,此時x正是集合中第x_index(如果下標從0開始算,則是x_index+1)大的元素。
2、題目情景特殊性----只求一個數
? ? ? ?按照快速排序的步驟,接下來是將左、右兩個子集合分別重復上述的“選取主元素,其余元素按照大小放主元素左右兩邊”的操作,但事實題目只是要求找到一個第k大的元素。那么,左右兩個子集是不是可以考慮舍去一個?(類似于二分法,只取一半)
顯然可以!我們可以將k與x_index進行比較,分三種情況,當
- k = x_index 時,說明已經找到了
- k < x_index 時,說明第k大元素在x左邊的子集里,可以舍去右邊部分
- k > x_index 時,說明第k大元素在x右邊的子集里,可以舍去左邊部分
3、C代碼實現:
#include <stdio.h> int exchange(int *a, int i, int j){int temp = a[i];a[i] = a[j];a[j] = temp; } int partition(int *a, int p, int r){int x = a[r];int i = p-1, j;for(j = p; j < r; j++){if(a[j] < x){i++;exchange(a, i, j); //交換下標為 i和 j 兩個數的位置 }}exchange(a, i+1, r); return i+1; } int quick_sort(int *a, int p, int r, int k, int *find) {if(p < r){int x_index = partition(a, p, r); //獲取主元素下標 printf("主元素下標x_index=%d\n", x_index);if(k == x_index){*find = 1;printf("find number k = %d\n", a[x_index]);return 0;}else if(k < x_index){quick_sort(a, p, x_index-1, k, find);}else if(k > x_index){quick_sort(a, x_index+1, r, k, find);}} }int main(){int find = -1, k;printf("請輸入k值"); scanf("%d", &k); k = k -1; //因為數組下標是從0開始算的,這里需要對應地做點調整int a[] = {0,9,7,5,3,6,1}; //試驗數組 quick_sort(a, 0, 6, k, &find); // 因為在整個遞歸過程中,存在x_index與k一直不相等的情況(實際上就是遞歸到底時,// x恰好就是是k的相鄰元素)。這里用find來標記是否相等。 不過無妨,到了最后,即// 便整個數組可能不是有序的,但是下標x_index和k所對應的數,已經恰好是第// x_index大和第k大的數了,目的已經達成 ,將對應下標k的元素輸出即可 if(find == -1){ //find為-1說明沒有在quick_sort沒有找到 k 元素 printf("find number k = %d\n", a[k]);}/*這里打印當前數組元素的順序,與題目無關,僅僅是想看看數組最后的順序 */ int i;for(i = 0; i <= 6; i++){printf("%d ", a[i]);}}運行結果:
三、復雜度分析
采用主定理分析
每次都考慮一個子問題,a=1,
- best-case(每次主元素都取到中間值) b=2
- worse-case(每次主元素都取到最大或者最小值)
事實上主元素采用random會使這個算法更加穩定。但是我看了下,它的時間復雜度好難算(我不會),所以不了不了,簡單點好0_0
總結
以上是生活随笔為你收集整理的c语言实现分治法求第K大元素(详细解释)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【论文阅读】Attention 机制在脱
- 下一篇: 最近邻插值法(nearest_neigh