標題:利用動態規劃求解最優二叉樹
阿新 • • 發佈:2019-02-14
摘要:二叉查詢書所要查詢的目標出現的頻率可能不一樣,因此它們在二叉查詢樹上的位置不同,查詢的代價也不同.
(1)基本思路:
[1]因為二叉查詢樹的左兒子一定要小於右兒子,這裡用單詞作為元素.首先按照首字母的順序排序,當首字母相同時,按照字串的長度排序。
[2]假設對於單詞wLeft……wRight進行構建二叉查詢樹,設F[Left][Right]以該單詞集合中某個單詞為根的最小查詢代價.則可以寫出遞迴關係
F[Left[Right]=minNi=1(wi+F[Left][i−1]+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);
}
}