目錄**編寫
實驗資料
資料分析
總結參考資料
分治法的思想是將乙個難以直接解決的大問題劃分成一些規模較小的子問題,分別求解各個子問題,再合併子問題的解得到原問題的解。一般來說,分治法的求解過程由以下二個階段組成:
劃分:把規模為 n 的原問題劃分為 k 個規模較小的子問題。
求解子問題:各子問題的解法與原問題的解法通常是相同的,可以用遞迴的方法求解各個子問題,有時遞迴處理也可以用迴圈來實現。
把各個子問題的解合併起來,合併的代價因情況不同有很大差異.分治演算法的效率很大程度上依賴於合併的實現。
主元素問題是設 t[0:n-1] 是 n 個元素的陣列,如果其中某個元素 x 在整個陣列中的出現次數超過 n/2,則稱 x 為陣列 t 的主元素。
主元素和歸併排序、最大子段和等情景類似。對於乙個規模為 n 的資料集而言,若資料集中有乙個元素的出現次數大於 n/2,我們就認為它是主元素。注意到主元素不一定所有的資料集都存在,因此需要對找不到的情況做考慮。
如果對於乙個資料集存在主元素,可以將資料集任意分為 2 等分。分別求出這 2 部分的主元素,如果 2 部分的主元素相同,則資料集的主元素就一定等於 2 個子集的主元素。若 2 個子集的主元素不同,則再分別求出這 2 個主元素在整個資料集中的個數,選取其中總個數大於 n/2 的元素為主元素,反之則判定主元素不存在。
特殊情況分析
顯然,主元素的存在性是唯一的。考慮最極端的情況,乙個資料集中只有 2 個不同的元素,這 2 個不同的元素的個數以 1:1 的關係出現。此時由於主元素的判定條件是元素個數超過 n/2,因此這 2 個元素均不能是主元素。
考慮第二種極端情況,資料集如下所示:「1,2,1,2,1,3,2,3,2,3」。當把這個資料集對半分成2部分時,第一部分的主元素是 1,第二部分的主元素是 3,對於整個資料集而言它們都不是主元素。注意到元素 2 其實是資料集中個數最多的元素,但是它同樣也不能滿足主元素的定義。從中我們也可以得知,將資料集均等分為 2 部分時,原資料集的主元素一定是 2 個子集的主元素之一。其他元素均不需要考慮,即使其他元素中存在這個資料集的眾數,其個數也不可能符合主元素的定義。
int findmainelement(vectordataset, int front, int rear)
mainelement1 = findmainelement(dataset, front, mid); //對資料集左半邊找主元素
mainelement2 = findmainelement(dataset, mid + 1, rear); //對資料集右半邊找主元素
if(mainelement1 == mainelement2) //找到的主元素相同
else
else if(dataset[i] == mainelement2)
}if(count1 > (rear - mid)) //根據次數返回主元素
else if(count2 > (rear - mid))
else //無解,返回無窮大 }}
int main()
else
cout << num1 << " " << num2 << " " << num3 << endl;
return 0;
}
資料集序號
資料集資料量(個)
資料集特點
1100
存在主元素,一般情況
2100
存在主元素,一般情況
3100
不存在主元素,一般情況
4100
不存在主元素,一般情況
5100
存在主元素,元素抱團出現
6100
不存在主元素,元素抱團出現
7100
存在主元素,2個元素交替出現
8100
不存在主元素,2個元素交替出現
9100
不存在主元素,3個元素交替出現
10100
(-10000,10000)隨機數
11100
(-10000,10000)隨機數
實驗序號
分治次數
統計元素操作次數
統計元素操作規模
1201
15284
2201
66208
3201
74162
4201
6491
5201
16174
6201
46204
7201
91509
8201
92532
9201
79170
10201
6491
11201
6491
從實驗資料我們可以看到,當資料集規模相同時,使用分治法劃分的子問題的規模是一樣的。但是在合併分治的結果時,如果兩個子集返回的主元素不相等,就需要去統計 2 個主元素的出現次數,這時也會帶來較大的時間開銷。而且使用分治法進行直接分割,沒有考慮資料集原本的狀態,會使得原本抱團出現的元素被切割成毫無特徵的子集,從而使演算法的執行次數維持在一定的水平無法降低。同時也能明顯地看到,當資料集的分布過於分散時,演算法在統計主元素出現次數的操作會有很大的開銷。
演算法的時間複雜度遞推式如下,得出時間複雜度為 o(n) = n㏒n。由於演算法存在對元素個數的統計操作,因此演算法實際的時間開銷 (t(n)) 會比理論分析的複雜度更高。
可以明顯地看到分治演算法雖然能夠解決問題,但是它很可能並不是種聰明的做法。分治法會把資料集分割個多個資料子集進行求解,資料子集往往是相互獨立的小問題。可能拿到的資料集本身具有一定的特徵,但是分治演算法不能提取資料集的特性而是直接劃分,導致資料集的特徵被破壞,進而導致分治演算法的規模會保持在一定的水平難以降低。而且純分治演算法求解主元素問題時,涉及到對元素的個數統計,使得劃分的子問題也同樣存在很大的開銷。此時還不如直接使用快速排序對資料集預處理,然後使用蠻力法統計不同元素的出現次數,雖然時間複雜度沒有降低,但是t(n)可以得到優化。總而言之,分治演算法的確可以解決一些問題,但是它不一定是這個問題的最優解,還是要具體問題具體分析。
《資料結構(c語言版|第二版)》—— 嚴蔚敏 李冬梅 吳偉民 編著,人民郵電出版社
《演算法設計與分析(第二版)》——王紅梅,胡明 編著,清華大學出版社
c++檔案和流
partition演算法 主元素問題 分治
主元素是一組n個數 現次數大於n 2的數。求乙個陣列中的主元素。取陣列中的乙個數,將陣列分成兩部分 比它大和比它小 再接著在子問題中求解。這是乙個常用的演算法 以後還會補充 include include include using namespace std int n intmode int a...
主元素問題 減治法
乙個有n個元素的序列a中,出現次數大於n 2的元素稱為主元素。現給定乙個序列 保證存在主元素 求其主元素 以下假設a的主元素存在,且出現了k次,則其他元素出現的次數為n k,二者的差記為c 2k n。可知x為主元素當且僅當 c 0。1.若 x 確實為a的主元素,則a剪去字首p後得到的字尾s,x的個數...
主元素問題
主元素 majority number 定義為陣列中出現次數嚴格超過一半的數。找到這個數。要求使用o 1 的額外空間和o n 的時間。初階 有n個數,其中乙個數的出現次數嚴格超過了一半。求這個數。高階1 有n個數,其中兩個數的出現次數都超過了 求這兩個數。高階2 有n個數,其中乙個數的出現次數嚴格超...