Dynamic Programming - Optimal binary search trees

1) Problem Description

Using the optimal binary search tree to achieve the minimum cost of the search tree. Spend all nodes of the tree each node has a probability value to be searched pi, spend searching a node is pi * (depth (ki) +1), how to construct a binary search tree so that the tree search the minimum is the optimum binary search tree problem. The problem with the idea of ​​dynamic programming can be realized.

Formal definitions: Given n different keywords sorted sequence K = (k1, k2, ..., kn) and therefore (k1 <k2 <k3 <... <kn), we wish to construct a binary search with these keywords. tree. For each keyword ki, we have a probability of pi represents the probability of starting the search. Some of the value of K may no longer be searched, so we also need n + 1 pseudo keyword (d0, d1, d2, ... dn), for each pseudo-keyword search has a probability qi represents the corresponding probability.


example:

The binary search tree has five vertices (x1, x2, x3, x4 , x5).
[X1 <x2 <x3 <x4 < x5 ]
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description

2) The basic idea

Here Insert Picture Description

3) code implementation

public class example {

    public static void main(String[] args) {
        double[] p={0,0.15,0.1,0.05,0.1,0.2};  //n=5关键字有5个
        double[] q={0.05,0.1,0.05,0.05,0.05,0.1};  //叶子结点有n+1 = 6个
        ///这里的关键字长度为5
        int n = p.length;

        System.out.println("输出根节点辅助表");
        int[][] root = Optimal_BST(p,q,n-1);
        int temp = root.length-1;
        for(int i=1;i<temp;i++){
            for(int j=1;j<temp;j++){
                System.out.print(root[i][j]+"-");
            }
            System.out.println();
        }

        printOptimalBST(root,1,5,root[1][5]);
    }

    /**
     * DP在计算最优二叉树的辅助表的算法实现
     * @param p
     * @param q
     * @param n
     * @return
     */
    private static int[][] Optimal_BST(double[] p, double[] q, int n) {
        double[][] e = new double[n+2][n+2];//
        double[][] w = new double[n+2][n+2];
        int[][] root = new int[n+2][n+2];

        //初始化叶子结点的值
        for(int i=1;i<=n+1;i++){
            e[i][i-1]=q[i-1];
            w[i][i-1]=q[i-1];
        }
        for(int l=1 ; l<=n ; l++){///最外层循环是逐渐的将关键字个数从一个扩展到n个
            for(int i=1;i<=n-l+1;i++){
                int j=i+l-1;
                e[i][j]=Double.MAX_VALUE;
                w[i][j]=w[i][j-1]+p[j]+q[j];
                for(int r=i;r<=j;r++){
                    double t = e[i][r-1]+e[r+1][j]+w[i][j];
                    if(t<e[i][j]){
                        e[i][j]=t;
                        root[i][j]=r;///存储根节点的位置
                    }
                }
            }



        }

        System.out.println("输出当前的最小代价:"+e[1][n]);
        return root;

    }

    /**
     * 构建最优二叉搜索树
     * @param root
     * @param i
     * @param j
     * @param k
     */
    private static void printOptimalBST(int[][] root, int i, int j, int r) {
        int rootChild = root[i][j];
        if(rootChild==r){
            System.out.println("K"+rootChild+"是根");
            printOptimalBST(root,i,rootChild - 1,rootChild);
            printOptimalBST(root,rootChild + 1,j,rootChild);
            return;
        }
        if (j < i - 1)
        {
            return;
        }
        else if (j == i - 1)//遇到虚拟键
        {
            if (j < r)
            {
                System.out.println( "d" +  j + "是" + "k" + r + "的左孩子" );
            }
            else {//j>=r
                System.out.println( "d" +  j + "是" + "k" + r + "的右孩子" );
            }
            return;
        }
        else//遇到内部结点
        {
            if (rootChild < r)
            {
                System.out.println ("k" + rootChild + "是" + "k" + r + "的左孩子" );
            }
            else{
                System.out.println ("k" + rootChild + "是" + "k" + r + "的右孩子" );
            }

        }

        printOptimalBST(root,i,rootChild - 1,rootChild);
        printOptimalBST(root,rootChild + 1,j,rootChild);

    }


}
输出根节点辅助表
输出当前的最小代价:2.75
1-1-2-2-2-
0-2-2-2-4-
0-0-3-4-5-
0-0-0-4-5-
0-0-0-0-5-
K2是根
k1是k2的左孩子
d0是k1的左孩子
d1是k1的右孩子
k5是k2的右孩子
k4是k5的左孩子
k3是k4的左孩子
d2是k3的左孩子
d3是k3的右孩子
d4是k4的右孩子
d5是k5的右孩子

4) time complexity and space complexity

Time complexity of
O (n- . 3)
spatial complexity of
O (n-
2)

Released eight original articles · won praise 0 · Views 87

Guess you like

Origin blog.csdn.net/weixin_44721537/article/details/104087399