动态规划求最优二叉树JAVA,动态规划之最优二叉树 - osc_taaj0nlw的个人空间 - OSCHINA - 中文开源技术交流社区...

原理来自于《算法导论》,其实和矩阵的动态规划基本一样,所以这里就不作阐述了。

直接上代码,通过构造了最优的root数组后,很容易再创建一个二叉树(这一小部分大家可以自己理解后试试)。

关于代码的说明,因为书上给出的是伪代码,数组并没有采用C语言格式,下标不是从0开始,所以算法和root数组我做了调整,让其尊重了C语言数组格式。最后解释最优二叉树时,需要把C语言形式的root数组转换为原来书上的数组格式,简单的做法是下标加1后显示就行了。

定多个预处理函数

#define LENGTHP (sizeof(p)/sizeof(p[0]))

#define LENGTHQ (sizeof(q)/sizeof(q[0]))

#define DYNAMICDEBUG(TY, NM, N) \printf("Showing type:" #TY ", variable name:" #NM "\n"); \

showbst((NM),(N))

optimalbst函数,生成二维数组root, p, q,并填充数据。注意:此时的root数组内容是下标从0开始的。

int **optimalbst(float *p, float *q, int lengthp, int lengthq, float ***e, float ***w) {//返回root,记录着对应的索引

if (lengthp <= 0 || lengthq <= 0) returnNULL;int **root = new int *[lengthp], i, j;floatt;*e = new float *[lengthq];*w = new float *[lengthq];for (i = 0; i < lengthp; i++)

root[i]= new int[lengthp];for (i = 0; i < lengthq; i++) {

(*e)[i] = new float[lengthq];

(*w)[i] = new float[lengthq];

}//初始化数据

for (i = 0; i < lengthp; i++)for (j = 0; j < lengthp; j++)

root[i][j]= -1;for (i = 0; i < lengthq; i++)for (j = 0; j < lengthq; j++)

(*e)[i][j] = (*w)[i][j] = -1;//动态规划算法

for (i = 0; i < lengthq; i++)

(*e)[i][i] = (*w)[i][i] =q[i];for (int l = 1; l <= lengthp; l++)for (i = 1; i <= lengthp - l + 1; i++) {

j= i + l - 1;

(*w)[i - 1][j] = (*w)[i - 1][j - 1] + p[j - 1] + q[j];//i下标全部调整,j下标保持

for (int r = i; r <= j; r++) {

t= (*e)[i - 1][r - 1] + (*e)[r][j] + (*w)[i - 1][j];if ((*e)[i - 1][j] == -1.0f || t < (*e)[i - 1][j]) {

(*e)[i - 1][j] =t;

root[i- 1][j - 1] = r - 1;

}

}

}returnroot;

}

printfbst函数,解释root数组。注意:此时要将下标转换为原始数据的标号!!!

void printfbst(int **root, int i, int j, intn) {if (i == 0 && j == n - 1)

printf("k%d是根\n", root[i][j]+1);if (i

{int index =root[i][j];if (index !=i)

printf("k%d是k%d的左节点\n", root[i][index - 1] + 1, index + 1);

printfbst(root, i, index- 1, n);if (index !=j)

printf("k%d是k%d的右节点\n", root[index + 1][j] + 1, index + 1);

printfbst(root, index+ 1, j, n);

}else if (i ==j)

{

printf("d%d是k%d的左节点\n", i, i + 1);

printf("d%d是k%d的右节点\n", i + 1, i + 1);

}elseprintf("d%d是k%d的右节点\n", j + 1, j + 1);

}

数据录入,从这里就看的出p数组的下标不满足C语言数组性质,所以我作了修改,让其满足,这样录入数据就非常方便了!!!

d9c3bf5c49fd8bf211e84387a68091e9.png

float p[] = { 0.15,0.1,0.05,0.1,0.2 }, q[] = { 0.05,0.1,0.05,0.05,0.05,0.1 }

完整的main函数,用于测试

intmain()

{float p[] = { 0.15,0.1,0.05,0.1,0.2 }, q[] = { 0.05,0.1,0.05,0.05,0.05,0.1 }, **e, **w;//k1 - k5, d0-d5

int **root;//root保存的是数组下标

root = optimalbst(p, q, LENGTHP, LENGTHQ, &e, &w);

DYNAMICDEBUG(float, e,LENGTHQ);

DYNAMICDEBUG(float, w, LENGTHQ);

DYNAMICDEBUG(int, root, LENGTHP);

printf("解释最优二叉树,数组下标转换为实际的k1-k5, d0-d5\n");

printfbst(root,0, LENGTHP-1, LENGTHP);

freebst(root, LENGTHP);

freebst(e, LENGTHQ);

freebst(w, LENGTHQ);return 0;

}

几个辅助函数,用于测试

template

void freebst(T **p, intn) {for (int i = 0; i < n; i++)

delete[] p[i];

delete[] p;

}

template

void showbst(T **p, intn) {for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++)if ((float)p[i][j] != -1.0f)

printf("%.2f", (float)p[i][j]);elseprintf("%-05s", " ");

printf("\n");

}

printf("\n");

}

测试结果:

9b0f449522e5e87da936523d60711791.png

上图分别对应书上的结果图

e数组, w数组,以及root数组。注意:再三强调,经过修改,root数组内容是指向数组下标的,而非实际的数据标号。

66749ecdbca7789af343a0e6141b38b8.png

再看对应的二叉树解释

14f809d26a84b75dfbda353a948868fd.png

所有代码经过测试,结果正确!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值