1. 程式人生 > >15.5 最優二叉搜尋樹

15.5 最優二叉搜尋樹

背景

假定我們正在設計一個程式,實現英語文字到中文的翻譯。對英語文字中出現的每個單詞,我們需要查詢對應的中文。為了實現這些操作,我們可以建立一個二叉搜尋樹,將n個英語單詞作為關鍵字,對應的中文作為關聯資料。 #定義 給定一個n個不同關鍵字的已排序的序列K=<k1,k2,…,kn>,我們希望用這些關鍵字構造一顆二叉搜尋樹。對每個關鍵字ki,都有一個概率pi表示其搜尋頻率。有些要搜尋的值可能不在K中,因此我們還有n+1個“偽關鍵字”d0,d1,d2,…dn表示不在K中的值。d0表示所有小於k1的值,dn表示所有大於kn的值,對i=1,2…,n-1,偽關鍵字di表示所有在ki和ki+1之間的值。對每個偽關鍵字di,也都有一個概率qi表示對應的搜尋頻率。

相關公式

基本公式

頻率之和為1: i=1npi+i=0nqi=1\sum_{i=1}^n p_{i} + \sum_{i=0}^n q_{i} = 1 (15.10)

E[T中的搜尋代價]: =i=1n(depthT(ki)+1)pi+i=0n(depthT(di)+1)qi= \sum_{i=1}^n(depth_{T}(k_{i})+1)\cdot p_{i} + \sum_{i=0}^n(depth_{T}(d_{i})+1)\cdot q_{i}

)qi =1+i=1ndepthT(ki)pi+i=0ndepthT(di)qi= 1 + \sum_{i=1}^ndepth_{T}(k_{i})\cdot p_{i} + \sum_{i=0}^ndepth_{T}(d_{i})\cdot q_{i} (15.11)

拓展公式

當我們選取子問題域為:求解包含關鍵字ki,…,kj的最優二叉搜尋樹,其中i>=1,j<=n且j>=i-1(當j=i-1時,子樹不包含實際關鍵字,只包含偽關鍵字di-1)。定義e[ i, j]為在包含關鍵字ki,…,kj的最優二叉搜尋樹中進行一次搜尋的期望代價。最終,我們希望計算出e[ 1, n]。有如下公式:

對於包含關鍵字ki,…,kj的子樹,所有概率之和為: w(i,j)=l=ijpl+l=i1jqlw(i,j) = \sum_{l=i}^jp_{l} + \sum_{l=i-1}^jq_{l} (15.12)

若kr為包含關鍵字ki,…,kj的最優二叉搜尋樹的根節點,我們有如下公式: e[i,j]=pr+(e[i,r1]+w(i,r1))+(e[r+1,j]+w(r+1,j))e[i,j] = p_{r} + (e[i,r-1] + w(i,r-1)) + (e[r+1,j] + w(r+1,j))

注意 w(i,j)=w(i,r1)+pr+w(r+1,j)w(i,j) = w(i,r-1) + p_{r} + w(r+1,j)

因此e[i, j]可重寫為: e[i,j]=e[i,r1]+e[r+1,j]+w(i,j)e[i,j] = e[i,r-1]+e[r+1,j]+w(i,j) (15.13)

遞迴公式(15.13)假定我們知道哪個節點k應該作為根節點。如果選取期望搜尋代價最低者作為根節點,可得最終遞迴公式: e[i,j]=qi1e[i,j] = q_{i-1} ,若 j = i - 1 $= \min_{i\leq r\leq j}\left{ e[i,r-1]+e[r+1,j]+w(i,j)\right} $ ,若i<=j (15.14) 為了避免重新計算w(i,j),對於 j>=i 的情況,可如下計算: w[i,j]=w[i,j1]+pj+qjw[i,j] = w[i,j-1]+p_{j}+q_{j} (15.15)

#相關演算法 ###應用動態規劃的演算法optimalBST 虛擬碼 下面的虛擬碼接受概率列表 p1,…,pn 和 q0,…,qn 及規模 n 作為輸入,返回表 e 和 root。

optimalBST(p,q,n)
  let e[1..n+1,0..n],w[1..n+1,0..n],and root[1..n,1..n]be new tables
  for i=1 to n+1
    e[i,i-1] = q[i-1]
    w[i,i-1] = q[i-1]
  for l=1 to n
    for i=1 to n-l+1
      j = i+l-1
      e[i,j] = MAX_INT
      w[i,j] = w[i,j-1]+p[j]+q[j]
      for r=i to j
        t = e[i,r-1]+e[r+1,j]+w[i,j]
        if t<e[i,j]
          e[i,j] = t
          root[i,j] = r
return e and root