[英]Adding sum of frequencies whille solving Optimal Binary search tree
我指的是這個問題和解決方案。
首先,我不明白為什么將頻率之和加到遞歸方程中。 有人可以幫忙理解一個例子。
用作者的話來說。
我們將i到j的頻率總和相加(請參見上式中的第一項),這是因為每次搜索都將經過根,並且每次搜索都將進行一次比較。
在代碼中,頻率之和(我不了解其目的)...對應於fsum。
int optCost(int freq[], int i, int j)
{
// Base cases
if (j < i) // If there are no elements in this subarray
return 0;
if (j == i) // If there is one element in this subarray
return freq[i];
// Get sum of freq[i], freq[i+1], ... freq[j]
int fsum = sum(freq, i, j);
// Initialize minimum value
int min = INT_MAX;
// One by one consider all elements as root and recursively find cost
// of the BST, compare the cost with min and update min if needed
for (int r = i; r <= j; ++r)
{
int cost = optCost(freq, i, r-1) + optCost(freq, r+1, j);
if (cost < min)
min = cost;
}
// Return minimum value
return min + fsum;
}
其次,該解決方案將僅返回最佳成本。 關於如何獲得實際bst有什么建議嗎?
為什么我們需要頻率總和
頻率總和背后的想法是正確計算特定樹的成本。 它的行為就像存儲樹重量的累加器值。
想象一下,在第一級遞歸中,我們從樹的第一級上的所有鍵開始(我們尚未選擇任何根元素)。 記住權重函數-它求和所有節點權重乘以節點級別。 現在,我們樹的權重等於所有鍵的權重之和,因為我們的任何鍵都可以位於任何級別(從第一層開始),並且無論如何,我們在結果中每個鍵的權重至少為一個。
1)假設我們找到了最佳根密鑰,即密鑰r
。 接下來,我們將除r
以外的所有鍵向下移動一個級別,因為剩下的每個元素最多可以位於第二個級別上(第一級別已被占用)。 因此,我們將剩下的每個鍵的權重加到總和上,因為無論如何,對於所有這些鍵,我們將至少具有兩倍的權重。 左邊的鍵根據我們之前選擇的r
元素(從r
到右邊的左邊)分成兩個子數組。
2)下一步是選擇第二級的最佳鍵,從第一步剩下的兩個子陣列中的每個子陣列中選擇一個。 之后,我們再次將所有按鍵向左下移一層,並將其權重添加到總和中,因為它們將至少位於第三層,因此每個按鍵的權重至少為三倍。
3)依此類推。
我希望這種解釋能使您對為什么我們需要這種頻率總和有所了解。
尋找最佳的BST
正如作者在文章末尾提到的
2)在上述解決方案中,我們僅計算了最佳成本。 可以輕松修改解決方案以存儲BST的結構。 我們可以創建另一個大小為n的輔助數組來存儲樹的結構。 我們要做的就是將所選的“ r”存儲在最里面的循環中。
我們可以做到這一點。 在下面,您將找到我的實現。
一些注意事項:
1)我被迫用實用程序類Matrix
替換int[n][n]
,因為我使用了Visual C ++,並且它不支持非編譯時間常數表達式作為數組大小。
2)我使用了您提供的文章的第二種算法實現(帶有記憶),因為添加功能來存儲最佳bst要容易得多。
3)作者的代碼有誤: for (int i=0; i<=n-L+1; i++)
第二個循環的上限應為nL
而不是n-L+1
。
4)我們存儲最佳bst的方式如下:對於每對i, j
我們存儲最佳密鑰索引。 這與最佳成本相同,但是我們存儲最佳密鑰索引而不是存儲最佳成本。 例如,對於0, n-1
我們將得到結果樹的根鍵r
的索引。 接下來,我們根據根元素索引r
將數組分為兩部分,並獲得其最佳鍵索引。 我們可以通過訪問矩陣元素0, r-1
和r+1, n-1
。 依此類推。 實用程序功能“ PrintResultTree”使用此方法並按順序(左子樹,節點,右子樹)打印結果樹。 因此,您基本上會獲得有序列表,因為它是二進制搜索樹。
5)請不要為我的代碼而發火-我實際上不是C ++程序員。 :)
int optimalSearchTree(int keys[], int freq[], int n, Matrix& optimalKeyIndexes)
{
/* Create an auxiliary 2D matrix to store results of subproblems */
Matrix cost(n,n);
optimalKeyIndexes = Matrix(n, n);
/* cost[i][j] = Optimal cost of binary search tree that can be
formed from keys[i] to keys[j].
cost[0][n-1] will store the resultant cost */
// For a single key, cost is equal to frequency of the key
for (int i = 0; i < n; i++)
cost.SetCell(i, i, freq[i]);
// Now we need to consider chains of length 2, 3, ... .
// L is chain length.
for (int L = 2; L <= n; L++)
{
// i is row number in cost[][]
for (int i = 0; i <= n - L; i++)
{
// Get column number j from row number i and chain length L
int j = i + L - 1;
cost.SetCell(i, j, INT_MAX);
// Try making all keys in interval keys[i..j] as root
for (int r = i; r <= j; r++)
{
// c = cost when keys[r] becomes root of this subtree
int c = ((r > i) ? cost.GetCell(i, r - 1) : 0) +
((r < j) ? cost.GetCell(r + 1, j) : 0) +
sum(freq, i, j);
if (c < cost.GetCell(i, j))
{
cost.SetCell(i, j, c);
optimalKeyIndexes.SetCell(i, j, r);
}
}
}
}
return cost.GetCell(0, n - 1);
}
以下是實用程序類Matrix
:
class Matrix
{
private:
int rowCount;
int columnCount;
std::vector<int> cells;
public:
Matrix()
{
}
Matrix(int rows, int columns)
{
rowCount = rows;
columnCount = columns;
cells = std::vector<int>(rows * columns);
}
int GetCell(int rowNum, int columnNum)
{
return cells[columnNum + rowNum * columnCount];
}
void SetCell(int rowNum, int columnNum, int value)
{
cells[columnNum + rowNum * columnCount] = value;
}
};
和具有實用程序功能的主要方法按順序打印結果樹:
//Print result tree in in-order
void PrintResultTree(
Matrix& optimalKeyIndexes,
int startIndex,
int endIndex,
int* keys)
{
if (startIndex == endIndex)
{
printf("%d\n", keys[startIndex]);
return;
}
else if (startIndex > endIndex)
{
return;
}
int currentOptimalKeyIndex = optimalKeyIndexes.GetCell(startIndex, endIndex);
PrintResultTree(optimalKeyIndexes, startIndex, currentOptimalKeyIndex - 1, keys);
printf("%d\n", keys[currentOptimalKeyIndex]);
PrintResultTree(optimalKeyIndexes, currentOptimalKeyIndex + 1, endIndex, keys);
}
int main(int argc, char* argv[])
{
int keys[] = { 10, 12, 20 };
int freq[] = { 34, 8, 50 };
int n = sizeof(keys) / sizeof(keys[0]);
Matrix optimalKeyIndexes;
printf("Cost of Optimal BST is %d \n", optimalSearchTree(keys, freq, n, optimalKeyIndexes));
PrintResultTree(optimalKeyIndexes, 0, n - 1, keys);
return 0;
}
編輯:
在下面,您可以找到創建簡單樹狀結構的代碼。
這是實用程序TreeNode
類
struct TreeNode
{
public:
int Key;
TreeNode* Left;
TreeNode* Right;
};
使用BuildResultTree
函數更新了main
函數
void BuildResultTree(Matrix& optimalKeyIndexes,
int startIndex,
int endIndex,
int* keys,
TreeNode*& tree)
{
if (startIndex > endIndex)
{
return;
}
tree = new TreeNode();
tree->Left = NULL;
tree->Right = NULL;
if (startIndex == endIndex)
{
tree->Key = keys[startIndex];
return;
}
int currentOptimalKeyIndex = optimalKeyIndexes.GetCell(startIndex, endIndex);
tree->Key = keys[currentOptimalKeyIndex];
BuildResultTree(optimalKeyIndexes, startIndex, currentOptimalKeyIndex - 1, keys, tree->Left);
BuildResultTree(optimalKeyIndexes, currentOptimalKeyIndex + 1, endIndex, keys, tree->Right);
}
int main(int argc, char* argv[])
{
int keys[] = { 10, 12, 20 };
int freq[] = { 34, 8, 50 };
int n = sizeof(keys) / sizeof(keys[0]);
Matrix optimalKeyIndexes;
printf("Cost of Optimal BST is %d \n", optimalSearchTree(keys, freq, n, optimalKeyIndexes));
PrintResultTree(optimalKeyIndexes, 0, n - 1, keys);
TreeNode* tree = new TreeNode();
BuildResultTree(optimalKeyIndexes, 0, n - 1, keys, tree);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.