- 背景:語言翻譯,從英語到法語,對於給定的單詞在單詞表里找到該詞
- 方法:創建一棵二叉搜索樹,以英語單詞作為關鍵字構建樹
- 目標:盡快地找到英語單詞,使總的搜索時間盡量少
- 思路:頻繁使用的單詞,如the應盡可能的靠近根;而不經常出現的單詞可以離根遠一點
前提假設:所有元素互異
一些定義:
-
二叉搜索樹
二叉搜索樹\(T\)是一棵二元樹,它或者為空,或者其每個結點含有一個可以比較大小的數據元素,且有:
- \(T\)的左子樹的所有元素比根結點中的元素小;
- \(T\)的右子樹的所有元素比根結點中的元素大;
- \(T\)的左子樹和右子樹也是二叉搜索樹。
-
最優二叉搜索樹
給定含有\(n\)個關鍵字的已排序的序列\(K=<k_1,k_2,…,k_n>\)(不失一般性,設 \(k_1<k_2<…<k_n\)),對每個關鍵字\(k_i\),都有一個概率\(p_i\)表示其被搜索的頻率。根據\(k_i\)和\(p_i\)構建一個二叉搜索樹\(T\),每個\(k_i\)對應樹中的一個結點。
搜索對象\(x\),在\(T\)中可能找到、也可能找不到:
- 若\(x\)等於某個\(k_i\),則一定可以在\(T\)中找到結點\(k_i\),稱為成功搜索。成功搜索的情況一共有\(n\)種,分別是\(x\)恰好等於某個\(k_i\)。
- 若\(x<k_1\) 或$ x>k_n$ 或\(k_i<x<k_{i+1} (1\leq i<n)\), 則在\(T\)中搜索\(x\)將失敗,稱為失敗搜索。
- 為此引入外部結點\(d_0,d_1,...,d_n\),用來表示不在\(K\)中的值,稱為偽關鍵字。
- 偽關鍵字在\(T\)中對應外部結點,共有\(n+1\)個。—擴展二叉樹:內結點表示關鍵字\(k_i\),外結點(葉子結點)表示\(d_i\)
- 這里每個\(d_i\)代表一個區間。\(d_0\)表示所有小於\(k_1\)的值, \(d_n\)表示所有大於\(k_n\)的值,對於\(i=1,…,n-1\),\(d_i\)表示所有在\(k_i\)和\(k_{i+1}\)之間的值。每個\(d_i\)也有一個概率表示搜索對象x恰好落\(q_i\)入區間\(d_i\)的頻率。
-
二叉搜索樹的期望搜索代價
-
一次搜索的代價等於從根結點開始訪問結點的數量(包括外部結點)。從根結點開始訪問結點的數量等於結點在\(T\)中的深度\(+ 1\)。記\(depth_T(i)\)為結點\(i\)在\(T\)中的深度。
-
二叉搜索樹\(T\)的期望代價為:
\[E[search\;cost\;in\;T] = \sum_{i = 1}^{n} (depth_T(k_i) + 1) * p_i + \sum_{i = 0}^{n}(depth_T(d_i) + 1) * q_i\\ = 1 + \sum_{i = 1}^ndepth_T(k_i)*p_i + \sum_{i = 0}^n depth_T(d_i) * q_i \]
-
-
最優二叉搜索樹
對於給定的關鍵字及其概率集合,期望搜索代價最小的二叉搜索樹稱為其最優二叉搜索樹。
關鍵問題在於確定誰是根:1.樹根不一定是概率最高的關鍵字;2.樹也不一定是最矮的樹;3.該樹的期望搜索代價必須是最小的。
證明最優二叉搜索樹的最優子結構:
如果\(T\)是一棵相對於關鍵字\(k_1,…,k_n\)和偽關鍵字\(d_0, …,d_n\)的最優二叉搜索樹,則\(T\)中一棵包含關鍵字\(k_i,…,k_j\)的子樹\(T'\)必然是相對於關鍵字\(k_i,…,k_j\)(和偽關鍵字\(d_{i-1}, …,d_j\))的最優二叉搜索子樹。
證明:用剪切-粘貼法證明
對關鍵字\(k_i,…,k_j\)和偽關鍵字\(d_{i-1},…,d_j\),如果存在子樹\(T''\),其期望搜索代價比\(T'\)低,那么將\(T'\)從\(T\)中刪除,將\(T''\)粘貼到相應位置上,則可以得到一棵比\(T\)期望搜索代價更低的二叉搜索樹,與\(T\)是最優的假設矛盾。
構造最優二叉搜索樹
利用最優二叉搜索樹的最優子結構性來構造最優二叉搜索樹。
分析: 對給定的關鍵字\(k_i,…,k_j\),若其最優二叉搜索(子)樹的根結點是\(k_r(i\leq r \leq j)\),則\(k_r\)的左子樹中包含關鍵字\(k_i,…,k_{r-1}\)及偽關鍵字\(d_{i-1} , …,d_{r-1}\),右子樹中將含關鍵字\(k_{i+1},…,k_j\)及偽關鍵字\(d_r,…,d_j\)。
計算過程:求解包含關鍵字\(k_i,...,k_j\)的最優二叉搜索樹,其中\(i \geq 1 , j \leq n , j \geq i - 1\)。定義\(e[i , j]\)表示包含關鍵字\(k_i , ...,k_j\)的最優二叉搜索樹的期望搜索代價,最終解的期望搜索代價為\(e[1 , n]\)。
-
當\(i \leq j\)時,從\(k_i , ..., k_j\)中選擇出根結點\(k_r\)。其左子樹包含關鍵字\(k_i , ... , k_{r - 1}\)且是最優二叉搜索子樹;其右子樹包含關鍵字\(k_{r + 1} , ... , k_j\)且同樣為最優二叉搜索樹。
-
當一棵樹成為另一個結點的子樹時,有以下變化:子樹的每個結點的深度增加\(1\),根據搜索代價期望值計算公式,子樹對根為\(k_r\)的樹的期望搜索代價的貢獻是其期望搜索代價+其所含有結點的概率之和。對於包含關鍵字\(k_i , ... , k_j\)的子樹,所有結點的概率之和為(包含外部結點):\(\omega(i ,j) = \sum_{l = i}^j p_l + \sum_{l= i - 1}^j q_l\) 。
-
若\(k_r\)為包含關鍵字\(k_i , ...,k_j\)的最優二叉搜索樹的根,則其期望搜索代價\(e[i , j]\)與左右子樹的期望搜索代價\(e[i , r - 1]\)和\(e[r + 1 , j]\)的遞推關系式為:
\[e[i , j] = p_r + (e[i , r - 1] + \omega(i , r - 1)) + (e[r + 1 , j] + w(r + 1 , j)) \]其中\(\omega(i , r - 1)\)和\(\omega(r + 1 , j)\)是左右子樹所有結點的概率之和。且有\(\omega(i , j) = \omega(i , r - 1) + p_r + \omega(r + 1 , j)\)
故遞推關系式等價於:\(e[i , j] = e[i , r - 1] + e[r + 1 , j] + w(i , j)\)
總的遞推關系式為:
\[e[i , j] = \begin{cases} q_{i - 1} & j = i - 1\\ \mathop{min}\limits_{i \leq r \leq j} \{e[i , r - 1] + e[r + 1 , j] + w(i , j)\} & i \leq j \end{cases} \] -
邊界條件
上述遞推關系式存在\(e[i , i - 1]\)和\(e[j + 1 , j]\)的邊界情況。此時子樹不包含實際的關鍵字,而只包含偽關鍵字\(d_{i - 1}\),其期望搜索代價僅為\(e[i , i - 1] = q_{i - 1}\)
-
構造最優二叉搜索樹
定義\(root[i , j]\),保存計算\(e[i , j]\)時,使\(e[i, j]\)取得最小值的\(r\),\(k_r\)即為關鍵字\(k_i,…,k_j\)的最優二叉搜索(子)樹的樹根。在求出\(e[1,n]\)后,利用\(root\)即可構造出最終的最優二叉搜索樹。
計算最優二叉搜索樹的期望值
定義三個數組:
- \(e[1...n + 1 , 0...n]\):用於記錄所有\(e[i , j]\)的值,其中\(e[n + 1 , n]\)表示偽關鍵字\(d_n\)對應的子樹;\(e[1 , 0]\)表示偽關鍵字\(d_0\)對應的子樹
- \(root[1...n]\):用於記錄所有最優二叉搜索子樹的根節點
- \(\omega[1...n + 1 , 0...n]\):用於保存子樹的結點的概率之和,且有\(\omega(i , j) = \omega(i , j - 1) + p_j + q _j\),這樣每個\(\omega(i , j)\)的計算時間僅為\(\Theta(1)\)。
偽代碼:
時間復雜度:\(O(n^3)\)
空間復雜度:\(O(n^2)\)
一個簡單的示例: