目錄
1 問題描述
在了解最優二叉查找樹之前,我們必須先了解何為二叉查找樹?
引用自百度百科一段講解:
二叉排序樹(Binary Sort Tree)又稱二叉查找樹(Binary Search Tree),亦稱二叉搜索樹。
二叉排序樹或者是一棵空樹,或者是具有下列性質的二叉樹:
(1)若左子樹不空,則左子樹上所有結點的值均小於或等於它的根結點的值;
(2)若右子樹不空,則右子樹上所有結點的值均大於或等於它的根結點的值;
(3)左、右子樹也分別為二叉排序樹;
在二叉查找樹的基礎上,引出了一個最優二叉查找樹的問題:它在查找樹中所有節點的平均鍵值比較次數是最低的。(PS:如若對於最優二叉查找樹的定義理解還是有點模糊,可以參考本文最后給出的參考資料中的鏈接)
2 解決方案
本文具體編碼思想參考自《算法設計與分析基礎》第三版,具體如下(PS:對於文中的具體思想,樓主自己是前后看了三四遍才整明白其具體思想,竟無語吟噎......,如若對於下面貼出的書中介紹無法理解,可以參考文末給出的參考資料的鏈接中,一位網友的博客講解哦):
具體代碼如下:
package com.liuzhen.chapter8; public class OptimalBST { /* * 參數P:表示1~n個節點的查找概率。其中P[0] = 0,無意義 * 函數功能:返回在最優BST中查找的平均比較次數主表C[][],以及最優BST中子樹的根表R */ public void getBestTree(double[] P) { int lenP = P.length; double[][] C = new double[lenP+1][lenP]; //保存最有BST的成功查找的平均比較次數 int[][] R = new int[lenP+1][lenP]; //保存最優BST中子樹的根表R for(int i = 1;i < lenP;i++) { C[i][i] = P[i]; R[i][i] = i; } for(int d = 1;d < lenP-1;d++) { for(int i = 1;i < lenP-d;i++) { int j = i + d; double minval = Double.MAX_VALUE; //以double類型的最大值,表示minval趨向無窮大 int kmin = 0; for(int k = i;k <= j;k++) { if(C[i][k-1] + C[k+1][j] < minval) { minval = C[i][k-1] + C[k+1][j]; kmin = k; } } R[i][j] = kmin; double sum = P[i]; for(int s = i+1;s <= j;s++) sum += P[s]; C[i][j] = minval + sum; } } System.out.println("在最優BST中查找的平均比較次數依次為:"); for(int i = 1;i < C.length;i++) { for(int j = 0;j < C[0].length;j++) System.out.printf("%.1f\t",C[i][j]); System.out.println(); } System.out.println("在最優BST中子樹的根表R為:"); for(int i = 1;i < R.length;i++) { for(int j = 0;j < R[0].length;j++) System.out.print(R[i][j]+"\t"); System.out.println(); } } public static void main(String[] args) { OptimalBST test = new OptimalBST(); double[] P = {0,0.1,0.2,0.4,0.3}; test.getBestTree(P); } }
運行結果:
在最優BST中查找的平均比較次數依次為: 0.0 0.1 0.4 1.1 1.7 0.0 0.0 0.2 0.8 1.4 0.0 0.0 0.0 0.4 1.0 0.0 0.0 0.0 0.0 0.3 0.0 0.0 0.0 0.0 0.0 在最優BST中子樹的根表R為: 0 1 2 3 3 0 0 2 3 3 0 0 0 3 3 0 0 0 0 4 0 0 0 0 0
參考資料:
1.《算法設計與分析基礎》第3版 Anany Levitin 著 潘彥 譯