日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

分治法--线性时间选择

發布時間:2023/12/9 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分治法--线性时间选择 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【分治法】線性時間選擇

? ? ??? ??線性時間選擇問題:給定線性序集中n個元素和一個整數k,1≤k≤n,要求找出這n個元素中第k小的元素,(這里給定的線性集是無序的)。

? ? ? ?1、隨機劃分線性選擇

? ? ? ?線性時間選擇隨機劃分法可以模仿隨機化快速排序算法設計。基本思想是對輸入數組進行遞歸劃分,與快速排序不同的是,它只對劃分出的子數組之一進行遞歸處理

? ? ? ?程序清單如下:

[cpp]?view plaincopy
  • //2d9-1?隨機劃分線性時間選擇??
  • #include?"stdafx.h"??
  • #include?<iostream>???
  • #include?<ctime>??
  • using?namespace?std;???
  • ??
  • int?a[]?=?{5,7,3,4,8,6,9,1,2};??
  • ??
  • template?<class?Type>??
  • void?Swap(Type?&x,Type?&y);??
  • ??
  • inline?int?Random(int?x,?int?y);??
  • ??
  • template?<class?Type>??
  • int?Partition(Type?a[],int?p,int?r);??
  • ??
  • template<class?Type>??
  • int?RandomizedPartition(Type?a[],int?p,int?r);??
  • ??
  • template?<class?Type>??
  • Type?RandomizedSelect(Type?a[],int?p,int?r,int?k);??
  • ??
  • int?main()??
  • {??
  • ????for(int?i=0;?i<9;?i++)??
  • ????{??
  • ????????cout<<a[i]<<"?";??
  • ????}??
  • ????cout<<endl;??
  • ????cout<<RandomizedSelect(a,0,8,3)<<endl;??
  • }??
  • ??
  • template?<class?Type>??
  • void?Swap(Type?&x,Type?&y)??
  • {??
  • ????Type?temp?=?x;??
  • ????x?=?y;??
  • ????y?=?temp;??
  • }??
  • ??
  • inline?int?Random(int?x,?int?y)??
  • {??
  • ?????srand((unsigned)time(0));??
  • ?????int?ran_num?=?rand()?%?(y?-?x)?+?x;??
  • ?????return?ran_num;??
  • }??
  • ??
  • template?<class?Type>??
  • int?Partition(Type?a[],int?p,int?r)??
  • {??
  • ????int?i?=?p,j?=?r?+?1;??
  • ????Type?x?=?a[p];??
  • ??
  • ????while(true)??
  • ????{??
  • ????????while(a[++i]<x?&&?i<r);??
  • ????????while(a[--j]>x);??
  • ????????if(i>=j)??
  • ????????{??
  • ????????????break;??
  • ????????}??
  • ????????Swap(a[i],a[j]);??
  • ????}??
  • ????a[p]?=?a[j];??
  • ????a[j]?=?x;??
  • ????return?j;??
  • }??
  • ??
  • template<class?Type>??
  • int?RandomizedPartition(Type?a[],int?p,int?r)??
  • {??
  • ????int?i?=?Random(p,r);??
  • ????Swap(a[i],a[p]);??
  • ????return?Partition(a,p,r);??
  • }??
  • ??
  • template?<class?Type>??
  • Type?RandomizedSelect(Type?a[],int?p,int?r,int?k)??
  • {??
  • ????if(p?==?r)??
  • ????{??
  • ????????return?a[p];??
  • ????}??
  • ????int?i?=?RandomizedPartition(a,p,r);??
  • ????int?j?=?i?-?p?+?1;??
  • ????if(k?<=?j)??
  • ????{??
  • ????????return?RandomizedSelect(a,p,i,k);??
  • ????}??
  • ????else??
  • ????{??
  • ????????//由于已知道子數組a[p:i]中的元素均小于要找的第k小元素??
  • ????????//因此,要找的a[p:r]中第k小元素是a[i+1:r]中第k-j小元素。??
  • ????????return?RandomizedSelect(a,i+1,r,k-j);??
  • ????}??
  • }??
  • ? ? ? ?程序解釋:利用隨機函數產生劃分基準,將數組a[p:r]劃分成兩個子數組a[p:i]和a[i+1:r],使a[p:i]中的每個元素都不大于a[i+1:r]中的每個元素。接著"j=i-p+1"計算a[p:i]中元素個數j.如果k<=j,則a[p:r]中第k小元素在子數組a[p:i]中,如果k>j,則第k小元素在子數組a[i+1:r]中。注意:由于已知道子數組a[p:i]中的元素均小于要找的第k小元素,因此,要找的a[p:r]中第k小元素是a[i+1:r]中第k-j小元素。

    ? ? ? 在最壞的情況下,例如:總是找到最小元素時,總是在最大元素處劃分,這是時間復雜度為O(n^2)。但平均時間復雜度與n呈線性關系,為O(n)(數學證明過程略過,可參考王云鵬論文《線性時間選擇算法時間復雜度深入研究)。

    ? ? ? 2、利用中位數線性時間選擇

    ? ? ??中位數:是指將數據按大小順序排列起來,形成一個數列,居于數列中間位置的那個數據。

    ? ? ? 算法思路:如果能在線性時間內找到一個劃分基準使得按這個基準所劃分出的2個子數組的長度都至少為原數組長度的ε倍(0<ε<1),那么就可以在最壞情況下用O(n)時間完成選擇任務。例如,當ε=9/10,算法遞歸調用所產生的子數組的長度至少縮短1/10。所以,在最壞情況下,算法所需的計算時間T(n)滿足遞推式T(n)<=T(9n/10)+O(n)。由此可得T(n)=O(n)。

    ? ? ?實現步驟

    ? ? ? (1)將所有的數n個以每5個劃分為一組共組,將不足5個的那組忽略,然后用任意一種排序算法,因為只對5個數進行排序,所以任取一種排序法就可以了。將每組中的元素排好序再分別取每組的中位數,得到個中位數。

    ? ? ? (2)取這個中位數的中位數,如果是偶數,就找它的2個中位數中較大的一個作為劃分基準。

    ? ? ? (3)將全部的數劃分為兩個部分,小于基準的在左邊,大于等于基準的放右邊。在這種情況下找出的基準x至少比個元素大。因為在每一組中有2個元素小于本組的中位數,有個小于基準,中位數處于,即個中位數中又有個小于基準x。因此至少有個元素小于基準x。同理基準x也至少比個元素小。而當n≥75時≥n/4所以按此基準劃分所得的2個子數組的長度都至少縮短1/4。

    ? ? ??

    ? ? ? ?程序清單如下:

    [cpp]?view plaincopy
  • //2d9-2?中位數線性時間選擇??
  • #include?"stdafx.h"??
  • #include?<ctime>??
  • #include?<iostream>???
  • using?namespace?std;???
  • ??
  • template?<class?Type>??
  • void?Swap(Type?&x,Type?&y);??
  • ??
  • inline?int?Random(int?x,?int?y);??
  • ??
  • template?<class?Type>??
  • void?BubbleSort(Type?a[],int?p,int?r);??
  • ??
  • template?<class?Type>??
  • int?Partition(Type?a[],int?p,int?r,Type?x);??
  • ??
  • template?<class?Type>??
  • Type?Select(Type?a[],int?p,int?r,int?k);??
  • ??
  • int?main()??
  • {??
  • ????//初始化數組??
  • ????int?a[100];??
  • ??
  • ????//必須放在循環體外面??
  • ????srand((unsigned)time(0));??
  • ??
  • ????for(int?i=0;?i<100;?i++)??
  • ????{??
  • ????????a[i]?=?Random(0,500);??
  • ????????cout<<"a["<<i<<"]:"<<a[i]<<"?";??
  • ????}??
  • ????cout<<endl;??
  • ??
  • ????cout<<"第83小元素是"<<Select(a,0,99,83)<<endl;??
  • ??
  • ????//重新排序,對比結果??
  • ????BubbleSort(a,0,99);??
  • ??
  • ????for(int?i=0;?i<100;?i++)??
  • ????{??
  • ????????cout<<"a["<<i<<"]:"<<a[i]<<"?";??
  • ????}??
  • ????cout<<endl;??
  • }??
  • ??
  • template?<class?Type>??
  • void?Swap(Type?&x,Type?&y)??
  • {??
  • ????Type?temp?=?x;??
  • ????x?=?y;??
  • ????y?=?temp;??
  • }??
  • ??
  • inline?int?Random(int?x,?int?y)??
  • {??
  • ?????int?ran_num?=?rand()?%?(y?-?x)?+?x;??
  • ?????return?ran_num;??
  • }??
  • ??
  • //冒泡排序??
  • template?<class?Type>??
  • void?BubbleSort(Type?a[],int?p,int?r)??
  • {??
  • ?????//記錄一次遍歷中是否有元素的交換?????
  • ?????bool?exchange;????
  • ?????for(int?i=p;?i<=r-1;i++)????
  • ?????{????
  • ????????exchange?=?false?;????
  • ????????for(int?j=i+1;?j<=r;?j++)????
  • ????????{????
  • ????????????if(a[j]<a[j-1])????
  • ????????????{????
  • ????????????????Swap(a[j],a[j-1]);???
  • ????????????????exchange?=?true;????
  • ????????????}?????
  • ????????}?????
  • ????????//如果這次遍歷沒有元素的交換,那么排序結束?????
  • ????????if(false?==?exchange)????
  • ????????{??
  • ?????????????break?;????
  • ????????}??
  • ?????}??
  • }??
  • ??
  • template?<class?Type>??
  • int?Partition(Type?a[],int?p,int?r,Type?x)??
  • {??
  • ????int?i?=?p-1,j?=?r?+?1;??
  • ??
  • ????while(true)??
  • ????{??
  • ????????while(a[++i]<x?&&?i<r);??
  • ????????while(a[--j]>x);??
  • ????????if(i>=j)??
  • ????????{??
  • ????????????break;??
  • ????????}??
  • ????????Swap(a[i],a[j]);??
  • ????}?????
  • ????return?j;??
  • }??
  • ??
  • ??
  • template?<class?Type>??
  • Type?Select(Type?a[],int?p,int?r,int?k)??
  • {??
  • ????if(r-p<75)??
  • ????{??
  • ????????BubbleSort(a,p,r);??
  • ????????return?a[p+k-1];??
  • ????}??
  • ????//(r-p-4)/5相當于n-5??
  • ????for(int?i=0;?i<=(r-p-4)/5;?i++)??
  • ????{??
  • ????????//將元素每5個分成一組,分別排序,并將該組中位數與a[p+i]交換位置??
  • ????????//使所有中位數都排列在數組最左側,以便進一步查找中位數的中位數??
  • ????????BubbleSort(a,p+5*i,p+5*i+4);??
  • ????????Swap(a[p+5*i+2],a[p+i]);??
  • ????}??
  • ????//找中位數的中位數??
  • ????Type?x?=?Select(a,p,p+(r-p-4)/5,(r-p-4)/10);??
  • ????int?i?=?Partition(a,p,r,x);??
  • ????int?j?=?i-p+1;??
  • ????if(k<=j)??
  • ????{??
  • ????????return?Select(a,p,i,k);??
  • ????}??
  • ????else??
  • ????{??
  • ????????return?Select(a,i+1,r,k-j);??
  • ????}??
  • }??

  • ? ? ? ? ? ?運行結果如下:


    總結

    以上是生活随笔為你收集整理的分治法--线性时间选择的全部內容,希望文章能夠幫你解決所遇到的問題。

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