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

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

(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-11] = 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);
    }
}

你可能感兴趣的:(数据结构)