标题:利用动态规划求解最优二叉树

摘要:二叉查找书所要查找的目标出现的频率可能不一样,因此它们在二叉查找树上的位置不同,查找的代价也不同.

(1)基本思路:

[1]因为二叉查找树的左儿子一定要小于右儿子,这里用单词作为元素.首先按照首字母的顺序排序,当首字母相同时,按照字符串的长度排序。
[2]假设对于单词wLeft……wRight进行构建二叉查找树,设F[Left][Right]以该单词集合中某个单词为根的最小查找代价.则可以写出递归关系
F[Left[Right]=minNi=1(wi+F[Left][i1]+F[i+1][Right]+i=LeftRightPi)
注意:其中pi是某个单词出现的概率.因为原问题的子集相对原来的根要深了一层.所以必须将所有查找概率加上一遍。
[3]按照常规方法以空间换时间,注意构建循环的顺序和求解矩阵时基本一致.

.

#include "stdafx.h"
#include "malloc.h"
#define N 7
#define Infinity 100
typedef struct wordstr* word;
typedef word Array[N];
struct wordstr
{
    char *name;
    int size;
    double P;
};

double sum(Array words,int Left,int Right)
{
    double sum = 0;
    for (int i  = Left;i<=Right;i++)
        sum += words[i]->P;

    return sum;

}
void BestTree(Array words,double cost[][N],int Lastchange[][N])
{

    int Left,Right,cutoff,i;
    double Thiscost;
    for (Left = 0;Left<=N-1;Left++)
    {
        cost[Left][Left] = words[Left]->P;
        Lastchange[Left][Left] = Left;
    }
    for(cutoff = 1;cutoff<=N-1;cutoff++)
    {
        for(Left = 0;Left<=N-1-cutoff;Left++)
        {
            Right = Left + cutoff;
            cost[Left][Right] = Infinity;
            for(i = Left;i<=Right;i++)
            {
                if(i-1<Left)
                    cost[Left][i-1] = 0;//注意特殊情况,没有左子树
                if(i+1>Right)
                    cost[i+1][Right] = 0;
                Thiscost = (cost[Left][i-1]+cost[i+1][Right]+ sum(words,Left,Right));
                if (Thiscost < cost[Left][Right])
                {
                    cost[Left][Right] = Thiscost;
                    Lastchange[Left][Right] = i;//记录相应的根
                }
            }
        }
    }
}
void PrintTree(int Lastchange[][N],int Left,int Right)
{
//将树打印一遍
    if(Left == Right)
    {
        printf("%d ",Left);
    } 
    else if (Left < Right)
    {

     int k =Lastchange[Left][Right];
     printf("%d ",k);
     PrintTree(Lastchange,Left,k-1);
     PrintTree(Lastchange,k+1,Right);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值