問題描述
給出n
nn個元素的權值w[i
]w[i]
w[i]
,問如何構造查詢樹使得查詢效率最高?
靜態最優查詢樹
將n個元素的權值有序排列,設定opt
imal
(i,j
)optimal(i, j)
optima
l(i,
j)表示區間[i,
j]
[i, j]
[i,j
]之間的元素構造的最小ph值的子樹。
易知有關係:
o pt
imal
(i,j
)=∑k
=ijw
[i]+
minr
=ij[
opti
mal(
i,r−
1)+o
ptim
al(r
+1,j
)]
optimal(i, j) = \sum_^j w[i] + min_^[optimal(i,r -1) + optimal(r + 1, j)]
optima
l(i,
j)=∑
k=ij
w[i
]+mi
nr=i
j[o
ptim
al(i
,r−1
)+op
tima
l(r+
1,j)
] 這裡的∑k=
ijw[
i]
\sum_^j w[i]
∑k=ij
w[i]
將解題角度進行轉換,在搜尋區間[i,
j]
[i, j]
[i,j
]時必然其中每乙個元素的權值都被加上一次,而隨著往更小長度的搜尋被加上的元素也不斷的變少,以此從層次的角度而不是元素的深度來進行遍歷操作。
為了避免暴力搜尋的指數級的複雜度,可以設定二維dp陣列,預處理權值的字首和,根據區間[i,
j]
[i, j]
[i,j
]之間的距離從小到大進行遍歷更新,從而完成最後的更新。
時間複雜度為o(n
3)
o(n^3)
o(n3
),空間複雜度為o(n
2)
o(n^2)
o(n2)。
次優查詢樹
為了避免最優查詢樹令人不滿意的時間複雜度,我們近似地構造乙個最優的查詢樹。
我們在區間[l,
r]
[l,r]
[l,r
]通過如下方法找根節點:如果有δpi
=min
i=lr
∣∑j=
li−1
w[j]
−∑j=
i+1r
w[j]
∣\delta pi = min_^r\mid\sum_^w[j] -\sum_^rw[j]\mid
δpi=mi
ni=l
r∣∑
j=li
−1w
[j]−
∑j=i
+1r
w[j]
∣最小,那麼就取節點i為根節點。據此可不斷往後構造該次優查詢樹。
構造查詢樹的時間複雜度為o(n
2)
o(n^2)
o(n2)。
對於每乙個節點i
ii,最壞可能會被搜尋n−i
n - i
n−i次?
其查詢的複雜度最壞是o(n
logn
)o(nlogn)
o(nlog
n),此時元素等概率,查詢樹退化成二分查詢。
具體查詢效率對比未知,但是可以肯定的是,當n在1e3以上的數量級時,最優查詢樹的構造是需要花費大量時間的,同時輔助空間的需要也在不斷提公升。此時使用次優查詢樹可以在查詢效率不損失太多的前提下大幅縮短構造查詢樹的複雜度,因而實際使用中通常使用次優查詢樹。
在最優查詢樹中,dp狀態的設定與「層次遍歷」的手法是值得學習的。
靜態樹表查詢演算法 次優查詢樹
自 有關在靜態查詢表中對特定關鍵字進行順序查詢 折半查詢或者分塊查詢,都是在查詢表中各關鍵字被查詢概率相同的前提下進行的。例如查詢表中有 n 個關鍵字,表中每個關鍵字被查詢的概率都是 1 n。在等概率的情況,使用折半查詢演算法的效能最優。而在某些情況下,查詢表中各關鍵字被查詢的概率是不同的。例如水果...
構造次優查詢樹
似乎有些錯誤,但是錯在哪了呢?include include using namespace std const int num 9 int value num float weight num float sum weight num void init sum weight struct tre...
次優查詢樹的建立
查詢效率最高即平均查詢長度最小,根據前面所學知識,我們可以給出有序表在非等概率情況下應遵循的兩個原則 1 最先訪問的結點應是訪問概率最大的結點 2 每次訪問應使結點兩邊尚未訪問的結點的被訪概率之和盡可能相等。這兩個原則可用一句話來表示,即判定樹為帶權內路徑長度之和最小的二叉樹,亦即 ph wihi ...