最优二叉搜索树的重构动态方法

时间:2015-03-11 14:07:42

标签: c algorithm dynamic-programming

我对动态编程和CS的概念非常陌生。我通过阅读在线发布的讲座,观看视频和解决GeeksforGeeks和Hacker Rank等网站上发布的问题来自学。

问题

给定输入

3 25 30 5

where 3 =  #of keys

25 = frequency of key 1

30 = frequency of key 2

5  = frequency of key 3

如果每个键都以优化的方式排列,我将打印最低成本。这是一个最优的二叉搜索树问题,我找到了一个极客的极客解决方案,可以做类似的事情。

#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[] = {0,1,2};
    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;
}

然而,在这个解决方案中,他们也在输入“键”,但似乎它们对最终答案没有影响,因为它们不应该。只搜索每个键搜索多少时间的频率。

为了简单起见并理解这种动态方法,我想知道如何修改这个解决方案,以便它以上面显示的格式输入并输出结果。

1 个答案:

答案 0 :(得分:1)

您提供的功能确实有keys参数,但它不使用它。你可以完全删除它。


修改:特别是,由于函数optimalSearchTree()未在所有中使用其keys参数,因此删除该参数只需更改该函数签名(...

int optimalSearchTree(int freq[], int n)

...)和该函数的一次调用。既然你不需要这个特定练习的按键,你也可以将它们从主程序中删除,以便给你:

int main()
{
    int freq[] = {25, 30, 5};
    int n = sizeof(freq)/sizeof(freq[0]);
    printf("Cost of Optimal BST is %d ", optimalSearchTree(freq, n));
    return 0;
}

(替换为原始代码中指定的频率值替换)


然而,该函数假设频率是按键增加的顺序给出的。它至少需要相对键顺序来完成其工作,否则您无法构造搜索树。如果您对密钥值未知的想法感到不安,您可以将代码解释为使用freq[]数组中的索引作为键值的别名。这是有效的,因为上述假设的结果是x - &gt; keys[x]是从整数0 ... n - 1到任何实际密钥的1:1,保留订单映射。

如果函数无法假设频率最初按键递增的顺序给出,那么它可以先使用键将频率按顺序排序,然后按现在的步骤进行。