1. 程式人生 > >標題:利用動態規劃求解最優二叉樹

標題:利用動態規劃求解最優二叉樹

摘要:二叉查詢書所要查詢的目標出現的頻率可能不一樣,因此它們在二叉查詢樹上的位置不同,查詢的代價也不同.

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