最优二叉搜索树错误输出
Optimal Binary Search Tree Wrong Output
我正在研究一个问题,通过尽可能最好的方式来计算二叉搜索树中所需的最少遍历次数。确实在网上看到了一个解决方案,我明白了,但是我手工对样本输入进行了一些计算,结果没有得到正确的结果。
代码如下
#include <stdio.h>
#include <limits.h>
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j);
/* A Dynamic Programming based function that calculates minimum cost of
a Binary Search Tree. */
int optimalSearchTree(int keys[], int freq[], int n)
{
/* Create an auxiliary 2D matrix to store results of subproblems */
int cost[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[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+1; i++)
{
// Get column number j from row number i and chain length L
int j = i+L-1;
cost[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[i][r-1]:0) +
((r < j)? cost[r+1][j]:0) +
sum(freq, i, j);
if (c < cost[i][j])
cost[i][j] = c;
}
}
}
return cost[0][n-1];
}
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j)
{
int s = 0;
for (int k = i; k <=j; k++)
s += freq[k];
return s;
}
// Driver program to test above functions
int main()
{
int keys[] = {10, 12, 20};
int freq[] = {34, 8, 50};
int n = sizeof(keys)/sizeof(keys[0]);
printf("Cost of Optimal BST is %d ", optimalSearchTree(keys, freq, n));
return 0;
}
例如对于输入
int 键[] = {1,2,3};
int freq[] = {10,3,1};
I SHOULD GET 18 but i GET 19
对于这个输入
int 键[] = {1,2,3,4};
int freq[] = {5,4,1,200};
I SHOULD GET 225 I GET 226
对于这个输入
int 键[] = {1,2,3,4,5,6};
int freq[] = {33,1,409,2,1,34};
I SHOULD GET 997 but I GET 556
为此输入
int keys[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int freq[] = {5,5,5,5,5,5,5,5,5,5,167,5,5,5,5,5,5,5,5,5};
I Should Get 789 but i GET 532
怎么了?
您对预期的结果有误。以您的第一个示例为例,键 {1, 2, 3}
和频率 {10, 3, 1}
;最佳二叉搜索树是:
1 (10)
\
2 (3)
\
3 (1)
(括号中给出的频率)。函数 returns 搜索树 sum(frequencies) 次的预期成本,以访问的节点数衡量,它是 (10 * 1) + (3 * 2) + (1 * 3) = 19
。每次搜索 key 1
只遍历根节点。每次查找key2
都会遍历根节点,在其子节点中找到目标key,一共遍历两个节点。同理,每次搜索key3
都会遍历三个节点
根据访问的节点来衡量成本是有意义的,因为必须针对每个访问的节点的键进行比较,但您也可以根据遍历的边来衡量成本。但是,如果您计算进入根的边,则结果是相同的,表示宿主程序指向树的指针。在那种情况下,每个节点访问都涉及遍历该节点的传入边,消除了节点访问或边遍历计算成本之间的任何区别。
使用键 {1,2,3,4}
和频率 {5,4,1,200}
,最佳二叉搜索树是
4 (200)
/
1 (5)
\
2 (4)
\
3 (1)
费用为 (200 * 1) + (5 * 2) + (4 * 3) + (1 * 4) = 226
。
使用键 {1,2,3,4,5,6}
和频率 {33,1,409,2,1,34}
:
3 (409)
/ \
/ \
1 (33) 6 (34)
\ /
2 (1) 4 (2)
\
5(1)
费用为 (409 * 1) + ((33 + 34) * 2) + ((1 + 2) * 3) + (1 * 4) = 556
。
程序 returns 每种情况下的正确结果。
我将 20 键示例作为练习留给您。对于这种情况,有多个最优搜索树,但所有的成本都是 532,正如程序给出的那样。
我正在研究一个问题,通过尽可能最好的方式来计算二叉搜索树中所需的最少遍历次数。确实在网上看到了一个解决方案,我明白了,但是我手工对样本输入进行了一些计算,结果没有得到正确的结果。
代码如下
#include <stdio.h>
#include <limits.h>
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j);
/* A Dynamic Programming based function that calculates minimum cost of
a Binary Search Tree. */
int optimalSearchTree(int keys[], int freq[], int n)
{
/* Create an auxiliary 2D matrix to store results of subproblems */
int cost[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[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+1; i++)
{
// Get column number j from row number i and chain length L
int j = i+L-1;
cost[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[i][r-1]:0) +
((r < j)? cost[r+1][j]:0) +
sum(freq, i, j);
if (c < cost[i][j])
cost[i][j] = c;
}
}
}
return cost[0][n-1];
}
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j)
{
int s = 0;
for (int k = i; k <=j; k++)
s += freq[k];
return s;
}
// Driver program to test above functions
int main()
{
int keys[] = {10, 12, 20};
int freq[] = {34, 8, 50};
int n = sizeof(keys)/sizeof(keys[0]);
printf("Cost of Optimal BST is %d ", optimalSearchTree(keys, freq, n));
return 0;
}
例如对于输入 int 键[] = {1,2,3}; int freq[] = {10,3,1};
I SHOULD GET 18 but i GET 19
对于这个输入 int 键[] = {1,2,3,4}; int freq[] = {5,4,1,200};
I SHOULD GET 225 I GET 226
对于这个输入 int 键[] = {1,2,3,4,5,6}; int freq[] = {33,1,409,2,1,34};
I SHOULD GET 997 but I GET 556
为此输入 int keys[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; int freq[] = {5,5,5,5,5,5,5,5,5,5,167,5,5,5,5,5,5,5,5,5};
I Should Get 789 but i GET 532
怎么了?
您对预期的结果有误。以您的第一个示例为例,键 {1, 2, 3}
和频率 {10, 3, 1}
;最佳二叉搜索树是:
1 (10) \ 2 (3) \ 3 (1)
(括号中给出的频率)。函数 returns 搜索树 sum(frequencies) 次的预期成本,以访问的节点数衡量,它是 (10 * 1) + (3 * 2) + (1 * 3) = 19
。每次搜索 key 1
只遍历根节点。每次查找key2
都会遍历根节点,在其子节点中找到目标key,一共遍历两个节点。同理,每次搜索key3
都会遍历三个节点
根据访问的节点来衡量成本是有意义的,因为必须针对每个访问的节点的键进行比较,但您也可以根据遍历的边来衡量成本。但是,如果您计算进入根的边,则结果是相同的,表示宿主程序指向树的指针。在那种情况下,每个节点访问都涉及遍历该节点的传入边,消除了节点访问或边遍历计算成本之间的任何区别。
使用键 {1,2,3,4}
和频率 {5,4,1,200}
,最佳二叉搜索树是
4 (200) / 1 (5) \ 2 (4) \ 3 (1)
费用为 (200 * 1) + (5 * 2) + (4 * 3) + (1 * 4) = 226
。
使用键 {1,2,3,4,5,6}
和频率 {33,1,409,2,1,34}
:
3 (409) / \ / \ 1 (33) 6 (34) \ / 2 (1) 4 (2) \ 5(1)
费用为 (409 * 1) + ((33 + 34) * 2) + ((1 + 2) * 3) + (1 * 4) = 556
。
程序 returns 每种情况下的正确结果。
我将 20 键示例作为练习留给您。对于这种情况,有多个最优搜索树,但所有的成本都是 532,正如程序给出的那样。