演算法導論-9-2-c-帶權中位元

來源:互聯網
上載者:User

演算法導論-9-2其它題目見第9章 排序和順序統計學

 

題目:

說明如何利用一個線性時間的中位元演算法(如9.3節中的SELECT),來在最壞情況下O(n)時間內求出n個數的帶權中位元

思考:

step1:利用SELECT中尋找中值的中值的演算法,找到主元

step2:用主元把數組分為三段,即A[1..q-1] < A[q] < A[q+1..r]

step3:計算A[1..q-1]<0.5和A[1..q]>=0.5的權值和,是否滿足題目中的公式

step4:若滿足,A[q]就是所求的數

step5:若不滿足,就繼續遞迴使用本演算法進行遞迴尋找。偏大就找前半段,偏小就找後半段

代碼:

#include <iostream>using namespace std;struct node{int value;double weight;};void Print(node *A, int len){int i;for(i = 1; i <= len; i++)cout<<A[i].value<<' ';cout<<endl;for(i = 1; i <= len; i++)cout<<A[i].weight<<' ';cout<<endl;}/*************最壞情況線性時間的選擇**************************************************///已經出現很多次了,不解釋int Partition(node *A, int p, int r){int i = p-1, j;for(j = p; j < r; j++){if(A[j].value <= A[r].value){i++;swap(A[i], A[j]);}}swap(A[i+1], A[r]);return i+1;}node Select(node *A, int p, int r, int i);//對每一組從start到end進行插入排序,並返回中值//插入排序很簡單,不解釋node Insert(node *A, int start, int end, int k){int i, j;for(i = 2; i <= end; i++){node t = A[i];for(j = i; j >= start; j--){if(j == start)A[j] = t;else if(A[j-1].value > t.value)A[j] = A[j-1];else{A[j] = t;break;}}}return A[start+k-1];}//根據文中的演算法,找到中值的中值node Find(node *A, int p, int r){int i, j = 0;int start, end, len = r - p + 1;node *B = new node[len/5+1];//每5個元素一組,長度為start到end,對每一組進行插入排序,並返回中值for(i = 1; i <= len; i++){if(i % 5 == 1)start = i+p-1;if(i % 5 == 0 || i == len){j++;end = i+p-1;//對每一組從start到end進行插入排序,並返回中值,如果是最後一組,組中元素個數可能少於5node ret = Insert(A, start, end, (end-start)/2+1);//把每一組的中值挑出來形成一個新的數組B[j] = ret;}}//對這個數組以遞迴調用Select()的方式尋找中值node ret = Select(B, 1, j, (j+1)/2);//delete []B;return ret;}//以f為主元的劃分int Partition2(node *A, int p, int r, node f){int i;//找到f的位置並讓它與A[r]交換for(i = p; i < r; i++){if(A[i].value == f.value){swap(A[i], A[r]);break;}}return Partition(A, p, r);}//尋找數組A[p..r]中的第i大的元素,i是從1開始計數,不是從p開始node Select(node *A, int p, int r, int i){//如果數組中只有一個元素,則直接返回if(p == r)return A[p];//根據文中的演算法,找到中值的中值node f = Find(A, p, r);//以這個中值為主元的劃分,返回中值在整個數組A[1..len]的位置//因為主元是數組中的某個元素,劃分好是這樣的,A[p..q-1] <= f < A[q+1..r]int q = Partition2(A, p, r, f);//轉換為中值在在數組A[p..r]中的位置int k = q - p + 1;//與所尋找的元素相比較if(i == k)return A[q];else if(i < k)return Select(A, p, q-1, i);else//如果主元是數組中的某個元素,後面一半要這樣寫return Select(A, q+1, r, i-k);//但是如果主元不是數組中的個某個元素,後面一半要改成Select(A, q, r, i-k+1)}//尋找數組A[p..r]中的第i大的元素,i是從1開始計數,不是從p開始node Select2(node *A, int p, int r, double i){//如果數組中只有一個元素,則直接返回if(p == r)return A[p];//根據文中的演算法,找到中值的中值node f = Find(A, p, r);//以這個中值為主元的劃分,返回中值在整個數組A[1..len]的位置//因為主元是數組中的某個元素,劃分好是這樣的,A[p..q-1] <= f < A[q+1..r]int q = Partition2(A, p, r, f);//轉換為中值在在數組A[p..r]中的位置int k = q - p + 1;//與所尋找的元素相比較double w = 0;for(int j = p; j <= k; j++)w += A[j].weight;if(w-A[k].weight < i && w >= i)return A[q];else if(w-A[k].weight >= i)return Select2(A, p, q-1, i);else//如果主元是數組中的某個元素,後面一半要這樣寫return Select2(A, q+1, r, i-w);//但是如果主元不是數組中的個某個元素,後面一半要改成Select(A, q, r, i-k+1)}int main(){int n, sum = 0, i;cin>>n;node *A = new node[n+1];int *B = new int[n+1];//產生隨機資料for(i = 1; i <= n; i++){A[i].value = rand() % 100;do{B[i] = rand() % 100;}while(B[i]==0);sum = sum + B[i];}//將權值規格化for(i = 1; i <= n; i++)A[i].weight = (double)B[i]/sum;//列印產生的資料Print(A, n);//求帶權中位元cout<<Select2(A, 1, n, 0.5).value<<endl;return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.