wizen-coder
10/4/2018 - 12:30 PM

设 S={x1, x2, ···, xn}是一个有序集合,且x1, x2, ···, xn表示有序集合的二叉搜索树利用二叉树的顶点存储有序集中的元素,而且具有性质:存储于每个顶点中的元素x 大于其左子树中任一个顶点中存储的元素,小于其右子树中任意顶点中存储的元素。二叉树中的叶顶点

设 S={x1, x2, ···, xn}是一个有序集合,且x1, x2, ···, xn表示有序集合的二叉搜索树利用二叉树的顶点存储有序集中的元素,而且具有性质:存储于每个顶点中的元素x 大于其左子树中任一个顶点中存储的元素,小于其右子树中任意顶点中存储的元素。二叉树中的叶顶点是形如(xi,xi+1) 的开区间。在表示S的二叉搜索树中搜索一个元素x,返回的结果有两种情形: (1) 在二叉树的内部顶点处找到: x = xi (2) 在二叉树的叶顶点中确定: x∈ (xi , xi

//3d11-1 最优二叉搜索树 动态规划
#include "stdafx.h"
#include <iostream> 
using namespace std;
 
const int N = 3;
 
void OptimalBinarySearchTree(double a[],double b[],int n,double **m,int **s,double **w);
void Traceback(int n,int i,int j,int **s,int f,char ch);
 
int main()
{
	double a[] = {0.15,0.1,0.05,0.05};
	double b[] = {0.00,0.5,0.1,0.05};
 
	cout<<"有序集的概率分布为:"<<endl;
	for(int i=0; i<N+1; i++)
	{
		cout<<"a"<<i<<"="<<a[i]<<",b"<<i<<"="<<b[i]<<endl;
	}
 
	double **m = new double *[N+2];
	int **s = new int *[N+2];
	double **w =new double *[N+2];
 
	for(int i=0;i<N+2;i++)  
    {  
		m[i] = new double[N+2];  
		s[i] = new int[N+2];  
		w[i] = new double[N+2];  
    } 
 
	OptimalBinarySearchTree(a,b,N,m,s,w);
	cout<<"二叉搜索树最小平均路长为:"<<m[1][N]<<endl;
	cout<<"构造的最优二叉树为:"<<endl;
	Traceback(N,1,N,s,0,'0');
 
	for(int i=0;i<N+2;i++)  
    {  
		delete m[i];
		delete s[i];
		delete w[i];
    } 
	delete[] m;
	delete[] s;
	delete[] w;
	return 0;
}
 
void OptimalBinarySearchTree(double a[],double b[],int n,double **m,int **s,double **w)
{
	//初始化构造无内部节点的情况
	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代表起止下标的差
	{
		for(int i=1; i<=n-r; i++)//i为起始元素下标
		{
			int j = i+r;//j为终止元素下标
 
			//构造T[i][j] 填写w[i][j],m[i][j],s[i][j]
			//首选i作为根,其左子树为空,右子树为节点
			w[i][j]=w[i][j-1]+a[j]+b[j];
			m[i][j]=m[i+1][j];
			s[i][j]=i;
 
			//不选i作为根,设k为其根,则k=i+1,……j
			//左子树为节点:i,i+1……k-1,右子树为节点:k+1,k+2,……j
			for(int k=i+1; k<=j; k++)
			{
				double t = m[i][k-1]+m[k+1][j];
 
				if(t<m[i][j])
				{
					m[i][j]=t;
					s[i][j]=k;//根节点元素
				}
			}
			m[i][j]+=w[i][j];
		}
	}
}
 
void Traceback(int n,int i,int j,int **s,int f,char ch)
{
	int k=s[i][j];
	if(k>0)
	{
		if(f==0)
		{
			//根
			cout<<"Root:"<<k<<" (i:j):("<<i<<","<<j<<")"<<endl;
		}
		else
		{
			//子树
			cout<<ch<<" of "<<f<<":"<<k<<" (i:j):("<<i<<","<<j<<")"<<endl;
		}
 
		int t = k-1;
		if(t>=i && t<=n)
		{
			//回溯左子树
			Traceback(n,i,t,s,k,'L');
		}
		t=k+1;
		if(t<=j)
		{
			//回溯右子树
			Traceback(n,t,j,s,k,'R');
		}
	}
}