C 最优二叉搜索树错误输出
我正在研究一个问题,通过尽可能最好地安排二叉搜索树,来计算二叉搜索树中所需的最小遍历次数。我确实在网上遇到了一个解决方案,我已经理解了,但我手工计算了一些样本输入,并没有得到正确的结果 下面是代码C 最优二叉搜索树错误输出,c,algorithm,dynamic-programming,C,Algorithm,Dynamic Programming,我正在研究一个问题,通过尽可能最好地安排二叉搜索树,来计算二叉搜索树中所需的最小遍历次数。我确实在网上遇到了一个解决方案,我已经理解了,但我手工计算了一些样本输入,并没有得到正确的结果 下面是代码 #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, in
#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;
}
#包括
#包括
//获取数组元素freq[i]到freq[j]之和的实用函数
整数和(整数频率[],整数i,整数j);
/*一种基于动态规划的函数,用于计算
二叉搜索树*/
整数优化搜索树(整数键[],整数频率[],整数n)
{
/*创建辅助二维矩阵以存储子问题的结果*/
国际成本[n][n];
/*cost[i][j]=二叉搜索树的最佳成本
由键[i]到键[j]构成。
成本[0][n-1]将存储结果成本*/
//对于单个密钥,成本等于密钥的频率
对于(int i=0;i 对于(int L=2;L您对预期结果的理解是错误的。以您的第一个示例为例,使用键{1,2,3}
和频率{10,3,1}
;最佳二进制搜索树是:
1 (10)
\
2 (3)
\
3 (1)
成本为(200*1)+(5*2)+(4*3)+(1*4)=226
使用键{1,2,3,4,5,6}
和频率{33,1409,2,1,34}
:
3 (409)
/ \
/ \
1 (33) 6 (34)
\ /
2 (1) 4 (2)
\
5(1)
3 (409)
/ \
/ \
1 (33) 6 (34)
\ /
2 (1) 4 (2)
\
5(1)
成本(409*1)+(33+34)*2)+(1+2)*3)+(1*4)=556
程序在每种情况下都返回正确的结果
我把20个关键点的例子留给你作为练习。这种情况下有多个最佳搜索树,但正如程序所给出的那样,所有的搜索树都花费了532英镑。你能解释一下这些值关键点和频率代表了什么,以及你试图应用的算法吗?@chmike这是你使用debu时的一个很好的来源gger和single逐步浏览代码,哪些行出现问题?对于这种情况:int-keys[]={1,2,3};int-freq[]={10,3,1};结果应该是19假设您有三个项,A、B和C。您搜索A 10次、B 3次和C 1次。您可以将它们排列为A在左分支上,B和C在右分支上成对排列。就处理所有搜索所需遍历的边的数量而言,单个边有10次遍历才能到达A、A然后对边进行4次遍历以到达B和C对,然后沿边向下3次遍历到B,沿边向下1次遍历到C。此树的边遍历总数为10+4+3+1,或18。假设您有三个术语,A、B和C。您搜索10次、B3次和C1次。您可以使用左分支上的A以及B和C来排列它们作为右分支上的一对。就处理所有搜索所需遍历的边数而言,有10次遍历一条边才能到达a,然后4次遍历边才能到达B和C对,然后3次遍历边才能到达B,1次遍历边才能到达C。此树的边遍历总数为10+4+3+1或18。@user2733436,该程序计算节点访问次数,这是一个有效的成本度量。当且仅当在计数中包含根节点的传入边时(这样做是有意义的,否则搜索存储在根节点中的密钥是免费的),这相当于计算边遍历次数。忽略树的根节点和右侧子节点中存储了哪些键的问题,搜索它所需的节点访问次数为(10*2)+((4+3)*3)=56,比我给出的树糟糕得多。@user2733436,即使您计算边遍历次数,即使您没有计算到达根的边遍历次数,您对树的计算也是错误的。您必须为每个键A的搜索计算1次边遍历,为每个键B或C的搜索计算2次边遍历——一次从根到其右侧子级,另一次从右到右om到目标节点。这使得10+(4+3)*2=24,仍然比我的树更糟糕(如果这样计算的话,值为18)@user2733436,无论如何,问题是为什么程序的输出不符合OP的期望,我已经用程序正在做的准确描述回答了这个问题。你可以随意不同意它使用的成本度量,但这与问题无关。@user2733436,我明确给出了数字搜索树涉及的节点访问次数,当然是19次,如我所说。答案中给出了计算。这也是搜索树所需的边遍历次数,假设您将传入边计算到根节点。如果不将传入边计算到根节点,则搜索成本为(10*0)+(3*1)+(1*2)=5
。
3 (409)
/ \
/ \
1 (33) 6 (34)
\ /
2 (1) 4 (2)
\
5(1)