關於貪心演算法介紹:
乙個複雜的工程,經常可以分解成一組簡單一些的任務,這些任務完成了,整個工程就完成了。例如汽車組裝問題可以分解成:底盤安裝、車軸安裝、車輪安裝、座位安裝、噴漆、剎車安裝、車門安裝等。但是這些任務之間有個先後順序,例如車軸安裝之前先要進行底盤安裝。
類似的問題,可以將任務和人物的先後順序用有向圖表示——稱為頂點活動網路,頂點代表乙個任務,有向邊(i,j)代表任務i要在任務j之前完成。下圖就是乙個工程,它有6個任務,邊(1,3)表示任務1要在任務3開始前完成,邊(4,6)表示任務4要在任務6之前完成。
這樣就形成了乙個任務序列,對有向圖的任意一條邊(i,j),在這個序列中,任務i一定出現在任務j之前,具有這種性質的序列叫做拓撲序列(topological order),根據有向圖建立拓撲序列的過程稱為拓撲排序(topological sorting)。
對於這樣乙個有向圖有若干個拓撲序列,如1-2-3-4-5-6,1-3-2-4-5-6,2-1-3-4-5-6等。
我們可以通過從左到右分步構造拓撲序列,每一步選擇乙個新頂點加入到序列中。選擇新頂點的貪心準則:從剩餘的頂點中選擇乙個頂點w,所有鄰接於它的頂點都在序列中。
演算法步驟:
令n表示有向圖的頂點數
令theorder表示空虛列
while(true)
if(theorder的頂點數小於n)
演算法失敗
else
theorder是乙個拓撲序列
針對上圖,使用這樣乙個演算法:
從theorder是乙個空序列開始,第一步選擇插入theorder序列的第乙個頂點,頂點1和2都滿足貪心準則。若選擇1,則theorder;第二步插入第二個頂點,這時有兩個個候選頂點2,3。若選擇3,則theorder;第三步選擇第三個頂點,候選頂點只有2,則theorder;第四步候選頂點為4和5,如果選擇4,則theorder;第五步只有乙個候選頂點5,第六步最後乙個頂點6,則theorder。
資料結構選擇:
用乙個一維陣列表示theorder,儲存拓撲序列;用乙個棧儲存可以加入theorder的候選頂點; 用乙個一維陣列indegree儲存每個頂點的實時入度,indegree[j]表示不在theorder中但鄰接於頂點j的數目。每次向theorder中新增,乙個頂點時,所有鄰接於此頂點的頂點j,thedegree[j]減1,當indegree變成0時,表示頂點j成為候選頂點。
函式是圖的graph抽象類的成員函式,使用到的介面包括:
directed():確定圖是否是有向圖
numberofvertices():返回圖的頂點數
vertexiterator類:創造乙個頂點的迭代器,其next()成員返回鄰接於改頂點的下乙個頂點。
arraystack是用陣列描述的棧,介面:
push(i):將i壓入棧
pop(),刪除棧頂元素
bool topologicalorder(int *theorder)
//把入邊數加入到棧中
arraystack stack;
for (int i = 1; i <= n; ++i)
if (indegree[i] == 0)
stack.push(i);
//生成拓撲序列
int j = 0;
while (!stack.empty())
}return (j == n);
}
複雜度分析:
計算入度的for迴圈的時間複雜度為o(n2);生成拓撲序列的外部while迴圈的時間複雜度為o(n),內層巢狀的while迴圈的時間複雜度為o(n),所以總的時間複雜度為o(n2)。故此演算法的時間複雜度為o(n2)。
經典貪心演算法 貪心演算法概述
貪心演算法具有最優子問題結構,它的特點是 短視 每次選擇對當前局面最有利的決策,來一步步獲得最優解。我個人認為,貪心不是乙個具體的方法,而是一類方法,貪心演算法的關鍵不在於想到,而在於正確性的證明。要證明乙個貪心演算法是正確的,需要證明我們可以把乙個最優解逐步轉化為我們用貪心演算法所得到的解,而解不...
演算法 貪心演算法
把乙個複雜問題分解為一系列較為簡單的區域性最優選擇,每乙個選擇都是對當前解的乙個擴充套件,知道獲得問題的完整解。在解決問題的策略上目光短淺,只根據當前已有的資訊做出選擇,而且一旦做出了選擇,不管將來有什麼結果這個選擇都不會改變。換言之,貪心法並不是從整體最優考慮,它所做出的選擇只是在某種意義上的區域...
演算法 貪心演算法
集合覆蓋問題 旅行商問題等都屬於np完全問題,在數學領域上並沒有快速得到最優解的方案,非常適合用貪婪演算法。判斷方法 1.元素較少時,一般執行速度很快,但隨著元素數量增多,速度會變得非常慢 2.涉及到需要計算比較 所有的組合 情況的通常是np完全問題 3.無法分割成小問題,必須考慮各種可能的情況。這...