📚 DAA Tutorial

Design and Analysis of Algorithms

Learn Design and Analysis of Algorithms concepts with simple explanations, algorithms, examples and practical notes.

← Back to DAA

Optimal Binary Search Tree

Given a fixed set of identifiers, the goal is to create a binary search tree. Different binary trees for the same identifier set have different performance characteristics.

fordowhileintif(a) fordointifwhile(b)
Two possible search trees
  • Fig (a) requires four comparisons in the worst case, and the average is 1+2+2+3+45=125.
  • Fig (b) requires three comparisons in the worst case, and the average is 115 comparisons.
  • The average number of comparisons is calculated assuming that each identifier is searched for with equal probability and that no unsuccessful searches are made.
  • But in a practical situation, different identifiers are searched for with different frequencies or probabilities. Also, unsuccessful searches are present.

Probabilities

Assume the given set of identifiers is {a1, a2, …, an} with a1 < a2 < … < an.

  • Let p(i) be the probability with which we search for ai.
  • Let q(i) be the probability that the identifier x being searched for satisfies ai<x<ai+1, 0 ≤ i ≤ n.

Assume a0=−∞ and an+1=+∞.

∑0≤i≤nq(i)

is the probability of an unsuccessful search, and

∑1≤i≤np(i)+∑0≤i≤nq(i)=1
10202225273032
An example binary search tree

External nodes

Add a fictitious (external) node in place of every empty subtree.

doifwhile1234
The tree of Fig (a) with external (square) nodes. Level numbers are shown on the right, with the root at level 1.
  • If a binary search tree represents n identifiers, then there will be exactly n internal nodes and n + 1 external nodes.
  • An internal node represents a point where a successful search terminates.
  • An external node represents a point where an unsuccessful search terminates.

The identifiers not in the BST can be partitioned into n + 1 equivalence classes Ei, 0 ≤ i ≤ n:

  • E0 contains all identifiers x such that x < a1.
  • Ei contains all identifiers x such that ai < x < ai+1, 1 ≤ i < n.
  • En contains all identifiers x such that x > an.

Cost of a binary search tree

Cost=∑1≤i≤np(i)∗level(ai)+∑0≤i≤nq(i)∗(level(Ei)−1)

The goal is to define an OBST for the identifier set {a1, a2, …, an}: a BST for which the cost is minimum.

Example

Define an OBST for (a1, a2, a3) = (do, if, while) with equal probabilities.

The number of possible BSTs for n nodes is

C(2n,n)n+1=2n!n!(n+1)!(for n = 3 this is 5)

Solution: Given equal probabilities, i.e. p(i)=q(i)=17 for every i. The possible trees are:

doifwhile
Tree a: cost = 157
doifwhile
Tree b: cost = 137 (optimal)
doifwhile
Tree c: cost = 157
doifwhile
Tree d: cost = 157
doifwhile
Tree e: cost = 157

Tree b is optimal.

Changed probabilities

If the probabilities are changed to p(1) = 0.5, p(2) = 0.1, p(3) = 0.05 and q(0) = 0.15, q(1) = 0.1, q(2) = 0.05, q(3) = 0.05, the cost of tree a is:

Cost(tree a)=(3×0.5+2×0.1+0.05)+(3×0.15+3×0.1+2×0.05+0.05)=2.65
TreeCost with equal probabilitiesCost with the changed probabilities
a15/72.65
b13/71.90
c15/71.50
d15/72.15
e15/71.60

With the changed probabilities, tree c has the least cost (1.5), so it is the optimal tree.

The handwritten page gives 2.05 for tree d. Computing it with the same formula gives 2.15, so 2.15 is shown here.

Applying dynamic programming to OBST

Make a decision as to which of the ai's should be assigned to the root node of the tree. If we choose ak, then the internal nodes for a1, a2, …, ak−1 and the external nodes for E0, E1, …, Ek−1 lie in the left subtree l of ak. The remaining nodes will be in the right subtree r of ak.

Cost(l)=∑1≤i<kp(i)∗level(ai)+∑0≤i<kq(i)∗(level(Ei)−1)

and

Cost(r)=∑k<i≤np(i)∗level(ai)+∑k≤i≤nq(i)∗(level(Ei)−1)

If w(i, j) is the sum

w(i,j)=q(i)+∑l=i+1j(q(l)+p(l))

then the expected cost of the search tree is

p(k)+Cost(l)+Cost(r)+w(0,k−1)+w(k,n)

If the tree is optimal, then its cost should be minimum, i.e. Cost(l) and Cost(r) should be minimum.

Let c(i,j) be the cost of an OBST tij containing ai+1, …, aj and Ei, …, Ej. Then

Cost(l)=c(0,k−1)Cost(r)=c(k,n)

In addition, k must be chosen such that the following is minimum:

p(k)+c(0,k−1)+c(k,n)+w(0,k−1)+w(k,n)

⇒ The recurrence is:

c(i,j)=mini<k≤j{c(i,k−1)+c(k,j)}+w(i,j)(1)

r(i,j) is the value of k that minimizes c(i, j) in (1). Compute c(i, j) such that j − i = 2, then for all c(i, j) with j − i = 3, and so on. (The cases j − i = 0 and j − i = 1 are set directly, as in the algorithm below.)

Example: n = 4, (a1, a2, a3, a4) = (do, if, int, while)

Use dynamic programming to generate an OBST for n = 4, (a1, a2, a3, a4) = (do, if, int, while), with P(1:4) = (3, 3, 1, 1) and q(0:4) = (2, 3, 1, 1, 1).

The probabilities are multiplied by 16 for convenience, so the actual values are P = (3/16, 3/16, 1/16, 1/16) and q = (2/16, 3/16, 1/16, 1/16, 1/16). If probabilities are given in this form, multiply them by their LCM.

There are two parts: (1) table construction and (2) OBST construction. Initially, for the first row:

w(i,i)=q(i),c(i,i)=0,r(i,i)=0for 0 ≤ i ≤ 4

For all other entries:

w(i,j)=P(j)+q(j)+w(i,j−1) c(i,j)=w(i,j)+mini<k≤j{c(i,k−1)+c(k,j)} r(i,j)=k (the k with minimum cost c(i, j))

The completed table

i = 0i = 1i = 2i = 3i = 4
j − i = 0w00 = 2
c00 = 0
r00 = 0
w11 = 3
c11 = 0
r11 = 0
w22 = 1
c22 = 0
r22 = 0
w33 = 1
c33 = 0
r33 = 0
w44 = 1
c44 = 0
r44 = 0
j − i = 1w01 = 8
c01 = 8
r01 = 1
w12 = 7
c12 = 7
r12 = 2
w23 = 3
c23 = 3
r23 = 3
w34 = 3
c34 = 3
r34 = 4
j − i = 2w02 = 12
c02 = 19
r02 = 1
w13 = 9
c13 = 12
r13 = 2
w24 = 5
c24 = 8
r24 = 3
j − i = 3w03 = 14
c03 = 25
r03 = 2
w14 = 11
c14 = 19
r14 = 2
j − i = 4w04 = 16
c04 = 32
r04 = 2

Step-by-step calculations

w, c, r for (0, 1)

w(0,1)=P(1)+q(1)+w(0,0)=3+3+2=8c(0,1)=w(0,1)+min{c(0,0)+c(1,1)}=8+min{0+0}=8+0=8r(0,1)=k=1

w, c, r for (1, 2)

w(1,2)=P(2)+q(2)+w(1,1)=3+1+3=7c(1,2)=w(1,2)+min{c(1,1)+c(2,2)}=7+min{0+0}=7+0=7r(1,2)=k=2

w, c, r for (2, 3)

w(2,3)=P(3)+q(3)+w(2,2)=1+1+1=3c(2,3)=w(2,3)+min{c(2,2)+c(3,3)}=3+min{0+0}=3+0=3r(2,3)=k=3

w, c, r for (3, 4)

w(3,4)=P(4)+q(4)+w(3,3)=1+1+1=3c(3,4)=w(3,4)+min{c(3,3)+c(4,4)}=3+min{0+0}=3+0=3r(3,4)=k=4

w, c, r for (0, 2)

w(0,2)=P(2)+q(2)+w(0,1)=3+1+8=12c(0,2)=w(0,2)+min{c(0,0)+c(1,2),c(0,1)+c(2,2)}=12+min{0+7,8+0}=12+7=19r(0,2)=k=1

w, c, r for (1, 3)

w(1,3)=P(3)+q(3)+w(1,2)=1+1+7=9c(1,3)=w(1,3)+min{c(1,1)+c(2,3),c(1,2)+c(3,3)}=9+min{0+3,7+0}=9+3=12r(1,3)=k=2

w, c, r for (2, 4)

w(2,4)=P(4)+q(4)+w(2,3)=1+1+3=5c(2,4)=w(2,4)+min{c(2,2)+c(3,4),c(2,3)+c(4,4)}=5+min{0+3,3+0}=5+3=8r(2,4)=k=3

w, c, r for (0, 3)

w(0,3)=P(3)+q(3)+w(0,2)=1+1+12=14c(0,3)=w(0,3)+min{c(0,0)+c(1,3),c(0,1)+c(2,3),c(0,2)+c(3,3)}=14+min{0+12,8+3,19+0}=14+11=25r(0,3)=k=2

w, c, r for (1, 4)

w(1,4)=P(4)+q(4)+w(1,3)=1+1+9=11c(1,4)=w(1,4)+min{c(1,1)+c(2,4),c(1,2)+c(3,4),c(1,3)+c(4,4)}=11+min{0+8,7+3,12+0}=11+8=19r(1,4)=k=2

w, c, r for (0, 4)

w(0,4)=P(4)+q(4)+w(0,3)=1+1+14=16c(0,4)=w(0,4)+min{c(0,0)+c(1,4),c(0,1)+c(2,4),c(0,2)+c(3,4),c(0,3)+c(4,4)}=16+min{0+19,8+8,19+3,25+0}=16+16=32r(0,4)=k=2

Building the tree

c04=32 is the minimum cost of a BST for (a1, a2, a3, a4).

  • As r04 = 2, the root is a2, i.e. the left subtree is t01 and the right subtree is t24.
  • As r01 = 1, a1 is the root of t01, with subtrees t00 and t11.
  • As r24 = 3, a3 is the root of t24, with subtrees t22 and t34.
  • As r34 = 4, a4 is the root of t34.
T₀₀T₀₁T₁₁T₀₄T₂₂T₂₄T₃₃T₃₄T₄₄
Structure of T04
doifintwhile
The resulting OBST

The total time to evaluate all the c(i, j)'s and r(i, j)'s is O(n3).

Algorithm OBST(P, q, n)

Algorithm OBST(P, q, n)
/* Given n distinct identifiers a1 < a2 < ... < an and probabilities
   P[i], 1 ≤ i ≤ n, and q[i], 0 ≤ i ≤ n, this algorithm computes c[i,j]
   of OBSTs t_ij for identifiers a_{i+1}, ..., a_j. It also computes
   r[i,j], the root of t_ij, and w[i,j], the weight of t_ij. */
{
    for i := 0 to n-1 do
    {
        // Initialize
        w[i,i] := q[i];  r[i,i] := 0;  c[i,i] := 0.0;
        // OBSTs with one node
        w[i,i+1] := q[i] + q[i+1] + P[i+1];
        r[i,i+1] := i + 1;
        c[i,i+1] := q[i] + q[i+1] + P[i+1];
    }
    w[n,n] := q[n];  r[n,n] := 0;  c[n,n] := 0.0;
    for m := 2 to n do          // Find optimal trees with m nodes
        for i := 0 to n-m do
        {
            j := i + m;
            w[i,j] := w[i,j-1] + P[j] + q[j];
            k := Find(c, r, i, j);
            c[i,j] := w[i,j] + c[i,k-1] + c[k,j];
            r[i,j] := k;
        }
    write(c[0,n], w[0,n], r[0,n]);
}

Algorithm Find(c, r, i, j)

Algorithm Find(c, r, i, j)
{
    min := ∞;
    for m := r[i,j-1] to r[i+1,j] do
        if (c[i,m-1] + c[m,j]) < min then
        {
            min := c[i,m-1] + c[m,j];  l := m;
        }
    return l;
}