算法java實現--動態規劃--最優二叉樹搜索

最優二叉搜索樹算法的java實現(動態規劃法)

具體問題描述以及C/C++實現參見網址

http://blog.csdn.net/liufeng_king/article/details/8694652

未改進版的java代碼如下:

/**
 * 最優二叉搜索樹(動態規劃)---未改進版
 * @author Lican
 *
 */
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");
	}

}
算法實現結果如圖:

===================================================================================================================================

改進後的java代碼如下(具體改進的地方,參見引文中的介紹)

/**
 * 最優二叉搜索樹(動態規劃)---改進版
 * @author Lican
 *
 */
public class BinarySearchTree2 {
	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;
			s[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;
				/*以下爲 改進後的地方*/
				int i1=s[i][j-1]>i?s[i][j-1]:i;
				int j1=s[i+1][j]>i?s[i+1][j]:j;
				//i,j之間距離爲r時,首選i爲根,其左子樹爲空,右子樹爲節點
				w[i][j]=w[i][j-1]+a[j]+b[j];//計算w[i][j]
				m[i][j]=m[i][i1-1]+m[i1+1][j];//k=i1時的情況
				s[i][j]=i1;
				 //左子樹爲節點:i1,i1+1……k-1,右子樹爲節點:k+1,k+2,……j1
				for(int k=i1+1;k<=j1;k++){//i1<=k<=j1,通過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");
	}

}
運行結果與未改進版相同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章