最优二叉查找树

最优二叉搜索树

首先了解什么是二叉查找树:
给定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");
	}
 
}

运行结果

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值