最优二叉搜索树


首先了解什么是二叉查找树:
给定n个互异的关键字组成的序列s=<k1,k2,…,kn>,且关键字有序(k1<k2<…<kn),我们想从这些关键字中构造一棵二叉查找树。对每个关键字ki,一次搜索搜索到的概率为pi。可能有一些搜索的值不在K内,因此还有n+1个“虚拟键”d0,d1,…,dn,他们代表不在K内的值。具体:d0代表所有小于k1的值,dn代表所有大于kn的值。而对于i = 1,2,…,n-1,虚拟键di代表所有位于ki和ki+1之间的值。对于每个虚拟键,一次搜索对应于di的概率为qi。要使得查找一个节点的期望代价(代价可以定义为:比如从根节点到目标节点的路径上节点数目)最小,就需要建立一棵最优二叉查找树

package ch01;

public class BinarySearchTree {
    public void optimalBinarySearchTree(float[] a,float[] b,float[][] m,int[][] s,float[][] w){
        int n=a.length-1;        
        for(int i=0;i<=n;i++){//初始化构造无内部节点的情况
            w[i+1][i]=a[i];
            m[i+1][i]=0;
        }
        for(int r=0;r<n;r++){//r为i与j之间的差值
            for(int i=1;i<=n-r;i++){
                int j=i+r;
                //i,j之间距离为r时,首选i为根,其左子树为空,右子树为节点
                w[i][j]=w[i][j-1]+a[j]+b[j];//计算w[i][j]
                m[i][j]=m[i+1][j];
                s[i][j]=i;
                for(int k=i+1;k<=j;k++){//i<=k<=j,通过k循环,找到min{m(i,k-1)+m(k+1,j)}的值
                    float temp=m[i][k-1]+m[k+1][j];
                    if(temp<m[i][j]){
                        m[i][j]=temp;
                        s[i][j]=k;//k作为根节点
                    }
                }
                m[i][j]+=w[i][j];//m(i,j)=wi,j+min{m(i,k-1)+m(k+1,j)}
            }
        }
    }
    public void backtrace(int[][] s,int n,int i,int j,int p,String str){
        int k=s[i][j];
        if(k>0){
            if(p==0){
                System.out.println("root is:"+k);
            }else{
                System.out.println(str+" of "+p+" is "+k+"; and (i:j) is "+i+":"+j);
            }
            int t=k-1;
            if(t>=i&&t<=n)
                backtrace(s,n,i,t,k,"left");
            t=k+1;
            if(t<=j)
                backtrace(s,n,t,j,k,"right");
        }
    }
    public static void main(String[] args) {
        float a[] = {0.15f,0.1f,0.05f,0.05f};//a,b的下标都是从0开始
        float b[] = {0.00f,0.5f,0.1f,0.05f};
        int n=a.length-1;
        float[][] m=new float[n+2][n+2];
        int[][] s=new int[n+2][n+2];//因为w[i+1][i]存在,i最大为n,即可以从0.....n,n+1,共n+2个
        float[][] w=new float[n+2][n+2];
        BinarySearchTree bi = new BinarySearchTree();
        bi.optimalBinarySearchTree(a, b, m, s, w);
        System.out.println("二叉搜索树最小平均路长为:"+m[1][n]);
        bi.backtrace(s, n, 1, n, 0, "0");
    }
}

 

posted @ 2022-12-24 21:19  kuailest  阅读(55)  评论(0编辑  收藏  举报