給定n個有序檔案,每個檔案的記錄數分別為w1~wn,請給出一種兩兩合併的方案,使得總合併次數最少。注意:1. 外排序演算法是將多個有序檔案合併成乙個有序檔案的過程。
2. 在一次合併的過程中,兩個檔案中的所有記錄都需要先從檔案中讀入記憶體,再在記憶體中排序,最後將排序的結果寫入檔案中。
3. 假設兩個待排序檔案記錄數分別為n、m,那麼將這兩個檔案合併成乙個有序的檔案需要進行n+m次讀寫。
n個檔案兩兩合併的過程可以用一棵擴充二叉樹來表示。因為擴充二叉樹只有度為2或0的節點,沒有度為1的節點,這符合兩兩合併的過程。
在這棵擴充二叉樹中:
1. 方形節點(外界點)表示原始的檔案,圓形節點(內節點)表示合併過程中的檔案;
2. 節點的權值表示檔案的記錄數
因此,n個檔案合併過程的總讀寫次數為帶權外路徑長度之和。
要求最小的合併次數即為求最小的帶權外路徑長度之和。
因此,問題就轉化為『如何求擴充二叉樹的最小加權路徑』。
這個問題可以用哈夫曼演算法解決。
若要使得帶權外路徑長度最小,可以將權值大的節點盡量靠近根節點,這樣路徑短一些;而權值小的節點可以適當遠離根節點,因為權值小,外路徑稍微長一點也沒事。
用乙個優先權佇列儲存所有的初始節點;
從佇列中選出兩個權值最小的節點,將它們的和作為它們的根節點,並放入佇列中;
迴圈這個過程,直到佇列中只有乙個節點為止,此時具有最小帶權路徑的擴充二叉樹構造完畢!此時帶權外路徑長度即為最小的讀寫次數。
/**
* 構造二叉樹的節點類
*/class
treenode
}
/**
* 構造哈夫曼樹
*@param w:所有節點的權值
*@return 哈夫曼樹的根節點
*/treenode hfmtree(int w)
});for(int i=0; inew treenode(w[i]));
}// 構造哈夫曼樹
最優合併問題 (貪心演算法)
最優合併問題 time limit 1000 ms memory limit 65536 kib problem description 給定k 個排好序的序列s1 s2,sk 用2 路合併演算法將這k 個序列合併成乙個序列。假設所採用的2 路合併演算法合併2 個長度分別為m和n的序列需要m n 1...
最優合併問題 貪心演算法
給定k個排好序的序列s 1s 1 s1 s 2s 2 s2 s ks k sk 用2 路合併演算法將這k 個序列合併成乙個序列。假設所採用的2 路合併演算法合併2 個長度分別為m和n的序列需要m n 1次比較。試設計乙個演算法確定合併這個序列的最優合併順序,使所需的總比較次數最少。為了進行比較,還需...
常用演算法三(貪心演算法)
一 基本概念 所謂貪心演算法是指,在對問題求解時,總是做出在 當前看來是最好的選擇 也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的 區域性最優解 貪心演算法沒有固定的演算法框架,演算法設計的關鍵是貪心策略的選擇。必須注意的是,貪心演算法不是對所有問題都能得到整體最優解,選擇的貪心策略...