算法参考《算法导论》第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; }