算法参考《算法导论》第15章--动态规划
//最优二叉查找树
#include <cstdio>
#include <cstring>
#include <limits>
class optimalBST{
private:
float *p, *q;
int n;
float **e;//(n+2)*(n+1)//e[1..n+1, 0..n]
float **w;//(n+2)*(n+1)//w[1..n+1, 0..n]
int **root;//(n+1)*(n+1),0 row and 0 col are not used
public:
optimalBST(float pp[], float qq[], int nn){
n = nn;
p = new float[n + 1];
q = new float[n + 1];
memcpy(p, pp, (n + 1) * sizeof(pp));//sizeof(pp)==sizeof(float)
memcpy(q, qq, (n + 1) * sizeof(qq));
e = new float*[n + 2];
w = new float*[n + 2];
root = new int*[n + 1];
for(int i = 0; i <= n + 1; i++){//此处是n+1--之前写成n,导致段错误
e[i] = new float[n + 1];
w[i] = new float[n + 1];
}
for(int i = 0; i <= n; i++){
root[i] = new int[n + 1];
}
}
~optimalBST(){//不知道这么写析构函数对不对,不会有内存泄漏或者重复释放的问题吧?
delete []p;
delete []q;
for(int i = 0; i <= n + 1; i++){//此处是n+1--之前写成n,导致段错误
delete []e[i];
delete []w[i];
}
for(int i = 0; i <= n; i++){
delete []root[i];
}
delete []e;
delete []w;
delete []root;
}
void calBST(){//核心部分,算法见算法导论第15章
for(int i = 1; i <= n + 1; i++){
e[i][i - 1] = w[i][i - 1] = q[i - 1];
}
for(int l = 1; l <= n; l++){
for(int i = 1; i <= n - l + 1; i++){
int j = i + l - 1;
e[i][j] = std::numeric_limits<float>::max();
w[i][j] = w[i][j - 1] + p[j] + q[j];
for(int r = i; r <= j; r++){
float 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 constructOptimalBST(){//练习15.5-1的算法
int r = root[1][n];
printf("k(%d) is root\n", r);
printBST(1, r - 1, 0);//0代表左子树
printBST(r + 1, n, 1);//1代表又子树
}
void printBST(int i, int j, int flag)//练习15.5-1的算法
{
if(j == i - 1){
if(flag == 0){
printf("d(%d)is k(%d)'s left child\n", i - 1, j + 1);
}else{
printf("d(%d)is k(%d)'s right child\n", i - 1, i - 1);
}
}else if(j >= i){
int r = root[i][j];
if(flag == 0){
printf("k(%d)is k(%d)'s left child\n", r, j + 1);
}else{
printf("k(%d)is k(%d)'s right child\n", r, i - 1);
}
printBST(i, r - 1, 0);
printBST(r + 1, j, 1);
}
}
void printBST2(int i, int j)//括号表示法:parent(left_subtree, right_subtree)
{
if(j == i - 1){
printf("d_%d", i - 1);
}else if(j >= i){
int r = root[i][j];
printf("k_%d(", r);
printBST2(i, r - 1);
printf(",");
printBST2(r + 1, j);
printf(")");
}
}
void printE()//e[1..n+1][0..n],打印e矩阵,格式同算法导论
{
for(int l = n; l >= 0; l--){
for(int i = 1; i <= n - l + 1; i++){
int j = i + l - 1;//[i..j] has l elements
printf("%f,", e[i][j]);
}
printf("\n");
}
}
void printRoot()//打印root矩阵,格式同算法导论
{
for(int l = n; l >= 1; l--){
for(int i = 1; i <= n - l + 1; i++){
int j = i + l - 1;//[i..j] has l elements
printf("%d,", root[i][j]);
}
printf("\n");
}
}
};
int main()
{
int n = 7;
float p[7 + 1] = {0, 0.04, .06, .08, .02, .10, .12, .14};//练习15.5-2的数据
float q[7 + 1] = {.06, .06, .06, .06, .05, .05, .05, .05};
optimalBST bst(p, q, n);
bst.calBST();
bst.constructOptimalBST();
bst.printE();
bst.printRoot();
bst.printBST2(1, n);
printf("\n");
return 0;
}