设 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');
}
}
}