- 資料結構與演算法
- DSA - 首頁
- DSA - 概述
- DSA - 環境設定
- DSA - 演算法基礎
- DSA - 漸進分析
- 資料結構
- DSA - 資料結構基礎
- DSA - 資料結構和型別
- DSA - 陣列資料結構
- 連結串列
- DSA - 連結串列資料結構
- DSA - 雙向連結串列資料結構
- DSA - 迴圈連結串列資料結構
- 棧和佇列
- DSA - 棧資料結構
- DSA - 表示式解析
- DSA - 佇列資料結構
- 搜尋演算法
- DSA - 搜尋演算法
- DSA - 線性搜尋演算法
- DSA - 二分搜尋演算法
- DSA - 插值搜尋
- DSA - 跳躍搜尋演算法
- DSA - 指數搜尋
- DSA - 斐波那契搜尋
- DSA - 子列表搜尋
- DSA - 雜湊表
- 排序演算法
- DSA - 排序演算法
- DSA - 氣泡排序演算法
- DSA - 插入排序演算法
- DSA - 選擇排序演算法
- DSA - 歸併排序演算法
- DSA - 希爾排序演算法
- DSA - 堆排序
- DSA - 桶排序演算法
- DSA - 計數排序演算法
- DSA - 基數排序演算法
- DSA - 快速排序演算法
- 圖資料結構
- DSA - 圖資料結構
- DSA - 深度優先遍歷
- DSA - 廣度優先遍歷
- DSA - 生成樹
- 樹資料結構
- DSA - 樹資料結構
- DSA - 樹遍歷
- DSA - 二叉搜尋樹
- DSA - AVL樹
- DSA - 紅黑樹
- DSA - B樹
- DSA - B+樹
- DSA - 伸展樹
- DSA - 字典樹
- DSA - 堆資料結構
- 遞迴
- DSA - 遞迴演算法
- DSA - 使用遞迴實現漢諾塔
- DSA - 使用遞迴實現斐波那契數列
- 分治法
- DSA - 分治法
- DSA - 最大最小問題
- DSA - Strassen矩陣乘法
- DSA - Karatsuba演算法
- 貪心演算法
- DSA - 貪心演算法
- DSA - 旅行商問題(貪心法)
- DSA - Prim最小生成樹
- DSA - Kruskal最小生成樹
- DSA - Dijkstra最短路徑演算法
- DSA - 地圖著色演算法
- DSA - 分數揹包問題
- DSA - 帶截止日期的作業排序
- DSA - 最優合併模式演算法
- 動態規劃
- DSA - 動態規劃
- DSA - 矩陣鏈乘法
- DSA - Floyd-Warshall演算法
- DSA - 0-1揹包問題
- DSA - 最長公共子序列演算法
- DSA - 旅行商問題(動態規劃法)
- 近似演算法
- DSA - 近似演算法
- DSA - 頂點覆蓋演算法
- DSA - 集合覆蓋問題
- DSA - 旅行商問題(近似演算法)
- 隨機化演算法
- DSA - 隨機化演算法
- DSA - 隨機化快速排序演算法
- DSA - Karger最小割演算法
- DSA - Fisher-Yates洗牌演算法
- DSA有用資源
- DSA - 問答
- DSA - 快速指南
- DSA - 有用資源
- DSA - 討論
最優合併模式演算法
將一組不同長度的有序檔案合併成一個有序檔案。我們需要找到一個最優解,使得生成的結果檔案在最短時間內完成。
如果給定了有序檔案的數量,那麼將它們合併成一個有序檔案的方法有很多。這種合併可以成對進行。因此,這種型別的合併稱為**二路合併模式**。
由於不同的配對需要不同的時間,因此在這種策略中,我們希望確定一種將多個檔案合併在一起的最佳方法。在每一步中,合併兩個最短的序列。
合併一個**包含p個記錄的檔案**和一個**包含q個記錄的檔案**可能需要**p + q**次記錄移動,顯而易見的選擇是在每一步中合併兩個最小的檔案。
二路合併模式可以用二叉合併樹表示。讓我們考慮一組**n**個有序檔案**{f1, f2, f3, …, fn}**。最初,每個元素都被認為是一個單獨的節點二叉樹。為了找到這個最優解,使用以下演算法。
虛擬碼
以下是最優合併模式演算法的虛擬碼:
for i := 1 to n – 1 do declare new node node.leftchild := least (list) node.rightchild := least (list) node.weight) := ((node.leftchild).weight)+ ((node.rightchild).weight) insert (list, node); return least (list);
在這個演算法結束時,根節點的權重表示最優成本。
示例
讓我們考慮給定的檔案f1、f2、f3、f4和f5,它們分別包含20、30、10、5和30個元素。
如果根據提供的順序執行合併操作,則
M1 = 合併f1和f2 => 20 + 30 = 50
M2 = 合併M1和f3 => 50 + 10 = 60
M3 = 合併M2和f4 => 60 + 5 = 65
M4 = 合併M3和f5 => 65 + 30 = 95
因此,操作總數為
50 + 60 + 65 + 95 = 270
現在,問題出現了,是否有更好的解決方案?
根據大小按升序對數字進行排序,我們得到以下序列:
f4, f3, f1, f2, f5
因此,可以在此序列上執行合併操作
M1 = 合併f4和f3 => 5 + 10 = 15
M2 = 合併M1和f1 => 15 + 20 = 35
M3 = 合併M2和f2 => 35 + 30 = 65
M4 = 合併M3和f5 => 65 + 30 = 95
因此,操作總數為
15 + 35 + 65 + 95 = 210
顯然,這比前一個更好。
在這種情況下,我們現在將使用此演算法來解決問題。
初始集合
步驟1
步驟2
步驟3
步驟4
因此,該解決方案需要15 + 35 + 60 + 95 = 205次比較。
示例
以下是上述方法在各種程式語言中的實現:
#include <stdio.h>
#include <stdlib.h>
int optimalMerge(int files[], int n)
{
// Sort the files in ascending order
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
int temp = files[j];
files[j] = files[j + 1];
files[j + 1] = temp;
}
}
}
int cost = 0;
while (n > 1) {
// Merge the smallest two files
int mergedFileSize = files[0] + files[1];
cost += mergedFileSize;
// Replace the first file with the merged file size
files[0] = mergedFileSize;
// Shift the remaining files to the left
for (int i = 1; i < n - 1; i++) {
files[i] = files[i + 1];
}
n--; // Reduce the number of files
// Sort the files again
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
int temp = files[j];
files[j] = files[j + 1];
files[j + 1] = temp;
}
}
}
}
return cost;
}
int main()
{
int files[] = {5, 10, 20, 30, 30};
int n = sizeof(files) / sizeof(files[0]);
int minCost = optimalMerge(files, n);
printf("Minimum cost of merging is: %d Comparisons\n", minCost);
return 0;
}
輸出
Minimum cost of merging is: 205 Comparisons
#include <iostream>
#include <algorithm>
int optimalMerge(int files[], int n) {
// Sort the files in ascending order
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
std::swap(files[j], files[j + 1]);
}
}
}
int cost = 0;
while (n > 1) {
// Merge the smallest two files
int mergedFileSize = files[0] + files[1];
cost += mergedFileSize;
// Replace the first file with the merged file size
files[0] = mergedFileSize;
// Shift the remaining files to the left
for (int i = 1; i < n - 1; i++) {
files[i] = files[i + 1];
}
n--; // Reduce the number of files
// Sort the files again
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
std::swap(files[j], files[j + 1]);
}
}
}
}
return cost;
}
int main() {
int files[] = {5, 10, 20, 30, 30};
int n = sizeof(files) / sizeof(files[0]);
int minCost = optimalMerge(files, n);
std::cout << "Minimum cost of merging is: " << minCost << " Comparisons\n";
return 0;
}
輸出
Minimum cost of merging is: 205 Comparisons
import java.util.Arrays;
public class Main {
public static int optimalMerge(int[] files, int n) {
// Sort the files in ascending order
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
// Swap files[j] and files[j + 1]
int temp = files[j];
files[j] = files[j + 1];
files[j + 1] = temp;
}
}
}
int cost = 0;
while (n > 1) {
// Merge the smallest two files
int mergedFileSize = files[0] + files[1];
cost += mergedFileSize;
// Replace the first file with the merged file size
files[0] = mergedFileSize;
// Shift the remaining files to the left
for (int i = 1; i < n - 1; i++) {
files[i] = files[i + 1];
}
n--; // Reduce the number of files
// Sort the files again
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (files[j] > files[j + 1]) {
// Swap files[j] and files[j + 1]
int temp = files[j];
files[j] = files[j + 1];
files[j + 1] = temp;
}
}
}
}
return cost;
}
public static void main(String[] args) {
int[] files = {5, 10, 20, 30, 30};
int n = files.length;
int minCost = optimalMerge(files, n);
System.out.println("Minimum cost of merging is: " + minCost + " Comparisons");
}
}
輸出
Minimum cost of merging is: 205 Comparison
def optimal_merge(files):
# Sort the files in ascending order
files.sort()
cost = 0
while len(files) > 1:
# Merge the smallest two files
merged_file_size = files[0] + files[1]
cost += merged_file_size
# Replace the first file with the merged file size
files[0] = merged_file_size
# Remove the second file
files.pop(1)
# Sort the files again
files.sort()
return cost
files = [5, 10, 20, 30, 30]
min_cost = optimal_merge(files)
print("Minimum cost of merging is:", min_cost, "Comparisons")
輸出
Minimum cost of merging is: 205 Comparisons