Dynamic Programming

Optimal Binary Search Trees

Section 3.5

 

Some redefinitions of BST

•      The text, “Foundations of Algorithms” defines the level, height and depth of a tree a little differently than Carrano/Prichard

•      The depth of a node is the number of edges in the path from the root to the node

–   This is also the level of the node

•      So the root is at level zero, instead of level one as defined in Carrano/Prichard

 

Optimal binary search tree

•      The goal is to organize the keys in a  BST so that the average time to locate a any key is minimized.

•      We want to optimize a search where the keys do not all have the same probability of success

•      An example would be a search in one of the trees on the overhead (Fig 3.10) for a name picked at random from people in the US

–    Since Tom is a more common name than Ursula, it would be assigned a greater probability

•      We will consider only those cases where what we are searching for is in the tree

–    So the trees have to be built knowing all the keys that may be searched for, as well as the probability for each key

–    Not being in the tree is a little different problem.

 

Search Time

•      The number of comparisons done by a procedure to locate a key is called the search time.

•      The goal is to determine a tree for which the average search time is minimal.

–    We must know the probability that the key is in the search tree

–    The probability will always be between 0 and 1

–    The sum of the probabilities of all the keys will be 1

•      The search time for a given key is depth(key) + 1 where depth(key) is the depth of the node in the tree

 

Average Search Time

•      Let k1, k2, k3, …kn be the keys in a BST

•      Let pi be the probability that ki is the search key

–    Associated with each key is a probability that that key will be in the tree

•       If ci is the number of comparisons needed to find Ki in a given tree, the average search time for that tree is
Sum cipi
i=1 to n

•      The number of comparisons depends on the depth of the key in the tree; which depends on the shape of the tree

–    So, we are not talking about balanced binary search trees

 

A simple example

•      Suppose we have three keys we want to put in an optimal BST

•      The probabilities are
p1 = 0.7     p2 = 0.2     p3 = 0.1

•        Find the average search time for the tree on the overhead (fig 3.11)
Sum cipi      This is an in class assignment to hand in
  
i=1 to n

–    Tree 1 is 3(0.7) + 2(0.2) + 1(0.1) = 2.6

•      On the next overhead are four other possibilities of trees.  Find the search time for each; then state which tree has the optimal average search time

–    Tree2 is 2(0.7) + 3(0.2) + 1(0.1) = 2.1

–    Tree3 is 2(0.7) + 1(0.2) + 2(0.1) = 1.8

–    Tree4 is 1(0.7) + 3(0.2) + 2(0.1) = 1.5

–    Tree5 is 1(0.7) + 2(0.2) + 3(0.1) = 1.4

 

Create this Optimal BST

•      Draw two different possible BSTs using the following data, then calculate the average search time for each tree

•      Try for an optimal BST in the second tree

•      The probability for each key is given in parentheses 
case(.05), else(.35), end(.05), if(.15) of(.05) then(.35)

•      Be sure to maintain BST ordering

How to find the optimal BST

•      It is not practical to find the optimal BST by considering all possibilities, since that is at least exponential in n

•      Instead, we divide the problem into smaller problems, and keep the results in a table to use when solving bigger problems

•      This is the classic dynamic programming solution;  solve the problem for the smallest case, save that to solve a problem on step bigger, etc

•      We want the nodes with the lowest probability to be lowest in our tree

 

Optimal solutions

•      Suppose we have an optimal BST with Keyk at the root

–    We know that the left subtree must also be optimal;

•    The average search time for the left subtree is  A[1][k-1]

–    The right subtree must also be optimal

•    The average search time for the right subtree is A[k+1][n]

•      Since trees are defined recursively, the subtrees can also be considered the root, and its subtrees must be optimal.

–    So starting from the bottom up, we find the minimum average search time for each subtree, and keep it in a table

 

Storing the data

•      The probability of each key is kept in a 1-D array

–    The probability of key1 is kept at index 1; etc

•      The minimum average search time of each subtree is kept in a 2-D array

•      The data for each subtree is kept in A[i][j] with Ki being the smallest key in the subtree, and Ki the largest key in the subtree

–     A[i][i] = pi

–   A[i][i-1] and A[j+1][j] are defined to be 0

 

Example

•      p1 = 0.4     p2 = 0.1     p3 = 0.2    p4 = 0.3

•      Put the probabilities in the 1-D array

•      Build the 2-D array on the
board

–      A[i][i] = pi

–    A[i][i-1] and A[j+1][j] are defined to be 0

•      To find the other A[i][j] we use the formula

•       A[i][j] = min(A[i][k-1] + A[k+1][j] +Sum pm     
           i ≤
k j                                  m=1 to j

•      In order to actually build the optimal BST, we have to keep track of the k that was used for the minimum average time

–    This is kept also kept in a 2-D array

 

Analyzing the algorithm

•      This algorithm is much like the algorithm for finding chained matrix multiplication

•      So it has the same time complexity, O(n3)

•      One of the reasons for presenting this algorithm is to show that a balanced BST is not necessarily the “best” BS

•      If you have the necessary data to build an optimal BST, then you can speed up searches.

•      What is necessary to build a optimal BST?

–    Know all the keys to be searched

–    Know the probability of each key