前面的optimal-bst還能寫出來,要去construct就不會了,也是理解不夠深刻的原因吧。以下**的construct用了兩種方法,參照了兩位博主,前乙個**風格非常暴力,能看懂以後寫不出來系列。第二種的d的輸出那我沒有看出邏輯,好像是用的輸出的相鄰兩個下標是在同乙個節點上連著?這個的理由我沒想出來(我也不確定該博主**是否正確,但輸出是對的)。
參照 我在看最優二叉搜尋樹的時候遇到一點問題(現在也覺得沒有很透徹理解這個)
e[i][j]的遞迴式我就看了好一會…..首先聯絡最開始提出的英語翻譯成法語,如果搜尋的內容沒有,也就是書上的d0,d1,d2……,做的處理就是在二維陣列e[i][j]中j=i-1,為什麼搜尋的期望是q[i-1]呢,當j=i-1的時候表示的是沒有真實關鍵字,只有虛擬鍵,那深度就是0,再加一,乘以概率最後就是概率了。當i<=j的時候,我開始就沒想通為什麼後面加個w(i,j),w(i,j)是表示的某子樹的概率和,e[i][j]表示的是期望。在演算法裡面,我們是在找root也就是kr,找到root之後,為這棵樹構造乙個最優的左子樹和最優的右子樹,也就是在左邊和右邊都還要再找乙個root,構造成左子樹和右子樹,這個時候子樹的搜尋代價就變了,子樹中的每個節點深度都增加了1(一棵樹變成乙個結點的子樹時深度+1)。結合搜尋的期望的公式,(深度+1)*p+(深度+1)*q那個公式,可以看出最後就是多了乙個概率和。左子樹的e加上右子樹的e加上乙個w就行了。
還有就是寫construct的時候,不知道怎麼從乙個root得到他的左子樹和右子樹是什麼。
printf(「k%d是k%d的左孩子\n」,root[i][root[i][j]-1],root[i][j]);
printf(「k%d是k%d的右孩子\n」, root[root[i][j] + 1][j], root[i][j]);
其實這一點,看遞推公式那裡就能看出來。
#include "stdafx.h"
#include
#define n 5
int root[n+1][n+1]; //樹根
double e[n + 2][n + 2]; //e是當前的搜尋期望
double w[n + 2][n + 2]; //w是每個子樹上的概率和
double p[n+1] = ; //關鍵字的概率
double q[n+1] = ; //虛擬鍵的概率
void optimal_bst(double *p, double *q)
for (l = 1; l <= n; l++) }}
}}/*
void construct_optimal_bst(int r, int i, int j)
if (j < i - 1)
return ;
else
if (j == i - 1) //虛擬鍵
else //關鍵字
construct_optimal_bst(child,i,child - 1);
construct_optimal_bst(child,child+1,j);}*/
void construct_optiaml_bst(int root[n+1], int i, int j)
if (i == j)
if (i > j)
printf("d%d是k%d的右孩子\n", j, j);
}int main()
動態規劃 最優二叉搜尋樹
動態規劃與分治方法類似,都是通過組合子問題來求解原問題。通常用來求解最優化問題,通常按如下4個步驟設計乙個動態規劃演算法 1.刻畫乙個最優解的結構特徵 2.遞迴的定義最優解的值 3.採用自底向上的方法計算最優解的值 4.利用計算出的資訊構造乙個最優解。二叉搜尋樹 optimal binary sea...
最優二叉搜尋樹動態規劃
最優二叉搜尋樹問題是對於有序集s及其訪問概率或權值 q0,p1,q1,p2,q2,p3,q3 在所有表示有序集s的二叉搜尋樹中找出一顆具有最小平均路長的二叉搜尋樹。解決方法 使用動態規劃方法自底向上逐步構造最優二叉搜尋樹。動態規劃的兩個重要要素是 1 最優子結構。2 重疊子問題。1 所謂最優化子結構...
動態規劃之最優二叉搜尋樹
在看這張之前,最好看看我寫的 動態規劃詳解 裡面都是講理論基礎,我下面的分析都是在此基礎上進展的。給定乙個由n個互異的關鍵字組成的序列k k1,k2,kn 且關鍵字有序 因此有k1 k2 kn 從這些關鍵字中構造一棵二叉查詢樹。對每個關鍵字ki,一次搜尋為ki的概率是pi。某些搜尋的值可能不在k內,...