/*
* 最優二叉搜索樹
*/
public class OptimalBST {
private final int MAX=10000;
private final int SCALE = 5; //樹的規模
private double[][] e= null; //e[i][j]表示樹ki..kj的期望代價
private double[][] w= null; //子樹期望代價增加值
private int[][] root=null; //記錄子樹的根
private double[] p = {0,0.15,0.10,0.05,0.10,0.20}; //k1..k5的概率
private double[] q = {0.05,0.10,0.05,0.05,0.05,0.10}; //d1..d5的概率
public static void main(String[] args) {
OptimalBST obst = new OptimalBST();
obst.compute(); //最優二叉搜索樹
obst.print(1, obst.SCALE, 0);
}
public OptimalBST() {
e = new double[SCALE+2][SCALE+1];
w = new double[SCALE+2][SCALE+1];
root = new int[SCALE+2][SCALE+1];
}
//計算得到最優二叉搜索樹期望代價
private void compute() {
for(int i=1;i<=SCALE+1;i++) {
e[i][i-1] = q[i-1];
w[i][i-1] = q[i-1];
}
for(int len=1;len<=SCALE;len++) {
for(int i=1;i<=SCALE-len+1;i++) {
int j=i+len-1;
e[i][j] = MAX;
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;
}
}
}
}
}
//打印最優二叉查找樹的結構
void print(int i,int j,int r)
{
int rootChild = root[i][j]; //子樹根節點
if (rootChild == root[1][SCALE]) {
//輸出整棵樹的根
System.out.println("k" + rootChild + "是根");
print(i,rootChild - 1,rootChild);
print(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
System.out.println("d" + j + "是k" + r + "的右孩子");
return;
}
else { //遇到內部結點
if (rootChild < r) {
System.out.println("k" + j + "是k" + r + "的左孩子");
}
else {
System.out.println("k" + j + "是k" + r + "的右孩子");
}
}
print(i,rootChild - 1,rootChild);
print(rootChild + 1,j,rootChild);
}
}
運行結果與算法導論上一致:
k2是根
k1是k2的左孩子
d0是k1的左孩子
d1是k1的右孩子
k5是k2的右孩子
k4是k5的左孩子
k3是k4的左孩子
d2是k3的左孩子
d3是k3的右孩子
d4是k4的右孩子
d5是k5的右孩子