日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言实现分治法求第K大元素(详细解释)

發布時間:2023/12/29 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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
T(n) = T(n/2)+Θ(n)=>Θ(lgn)
  • worse-case(每次主元素都取到最大或者最小值)
T(n) = T(0) + T(n-1) + Θ(n)= T(n-1) + Θ(n)=>Θ(n^2)

事實上主元素采用random會使這個算法更加穩定。但是我看了下,它的時間復雜度好難算(我不會),所以不了不了,簡單點好0_0

總結

以上是生活随笔為你收集整理的c语言实现分治法求第K大元素(详细解释)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。