Você está na página 1de 4

Computer Science CSC263H February 17, 2011

St. George Campus University of Toronto

Solutions for Homework Assignment #2

Answer to Question 1.

• The tree resulting after the sequence of insertions is:


14

+ +
8 17

− + 0 +
7 10 15 19

0 0 − 0
6 9 12 21

0
11

• The tree resulting after the deletion of 14 is:

0
10

− 0
8 15

− 0 − 0
7 9 12 19

0 0 0 0
6 11 17 21

1
Answer to Question 2.
a. It is easy to see that:
m0 = 1.
m1 = 2.
m2 = 3.
Now consider h ≥ 3. Let T be a slightly balanced binary search tree of height ≥ h. That means that
either the left or the right subtree of T must have height ≥ h − 1. Without loss of generality, say that the
left subtree has height ≥ h − 1. Since T is slightly balanced, the right subtree must have height ≥ h − 3.
(And note that h − 3 ≥ 0).
So T has size ≥ 1 + mh−1 + mh−3 . So mh ≥ 1 + mh−1 + mh−3 (and it is not hard to see that this is in
fact an equality).
b. We will prove by strong induction on h ≥ 0 that mh ≥ 1.4h − 1.
Let h ≥ 0 and assume that for every i such that 0 ≤ i < h, mi ≥ 1.4i − 1. We will show that mh ≥ 1.4h − 1.
BASE CASES: h ∈ {0, 1, 2}.
Since m0 = 1, m0 ≥ 0 = 1.40 − 1.
Since m1 = 2, m1 ≥ .4 = 1.41 − 1.
Since m2 = 3, m2 ≥ .96 = 1.42 − 1.
INDUCTION CASES: h ≥ 3.
mh ≥ 1 + mh−1 + mh−3 . Since 0 ≤ h − 3 ≤ h − 1 < h, we have mh−1 ≥ 1.4h−1 − 1 and mh−3 ≥ 1.4h−3 − 1.
So mh ≥ 1 + (1.4h−1 − 1) + (1.4h−3 − 1) = 1.4h (1/1.4 + 1/1.43 ) − 1 ≥ 1.4h − 1.
(In the last inequality, we used the fact that 1/1.4 + 1/1.43 ≥ 1.)

2
Answer to Question 3.
a. We can use an AVL tree, but instead of the keys satisfying the binary search tree property, they have
the property that an in-order traversal of the tree yields the sequence that is being represented. Each node
u contains the following fields:
• lchild(u): pointer to left child
• rchild(u): pointer to right child
• parent(u): pointer to the parent
• BF(u): balance factor (−1, 0, or 1)
• elmt(u): element (or key) stored at u
• sum(u): sum of all the keys in subtree rooted at u
• size(u): size (i.e., number of nodes) in subtree rooted at u.

b. One possibility is shown in the figure below (for clarity parent pointers are not included).

7 19 6 0

−2 3 2 −1 1 9 3 0

5 5 1 0 5 5 1 0 3 3 1 0

elmt sum size BF

c.
Let root be a pointer to the root of the tree that represents A.
The Query(A, i) operation: The procedure Query(r, i) below returns the element in the i-th position
of the sequence represented by the tree pointed to by r. (Our convention is that size(Λ) = 0.)

Query(r, i)
if i = 1 + size(lchild(r)) then
return elmt(r)
elsif i ≤ size(lchild(r)) then
return Query(lchild(r), i)
else
return Query(rchild(r), i − 1 − size(lchild(r)))
end if

To find the i-th element of A we call Query(root, i).


This algorithm, as well as all the others in this question, takes time at most linear in the height of the
tree, and therefore runs in time O(log n) in the worst case. By choosing i to correspond to a node that is
a leaf of the AVL tree, we can force the algorithm to take time at least linear in the height of the tree, and
so it also runs in time Ω(log n), in the worst case.

3
The Sum(A, i, j) operation: We first give an algorithm for computing Sum′ (r, i). This function
returns the sum of all the elements in positions ≥ i in the subtree pointed at by r; it can be called only if
1 ≤ i ≤ length(A).

Sum′ (r, i)
if i = 1 + size(lchild(r)) then
return elmt(r) + sum(rchild(r))
elsif i ≤ size(lchild(r)) then
return Sum′ (lchild(r), i) + elmt(r) + sum(rchild(r))
else
return Sum′ (rchild(r), i − 1 − size(lchild(r)))
end if

To compute Sum(A, i, j), we just compute Sum′ (root, i) − Sum′ (root, j) + Query(root, j).
The Insert(A, i, a) operation: We first create a new node with BF field 0, elmt field a, size field 1,
sum field a, and pointer fields Λ. This node will become a new leaf of the AVL tree. To find where to
insert the new leaf, we do the following. If i is less than or equal to the number of elements in the list (that
is, size(root)), then we call Query(root, i) to find the i-th node, say u, go to its left child (if it has one —
if not insert the leaf as the left child of u), then follow right child pointers as far as possible to node v, and
insert the leaf as a right child of v. If i is 1 more than the number of elements in the list, then follow right
child pointers from the root as far as possible, and insert the leaf here.
We now fix up the tree in two stages. (The stages can be combined, but the algorithm is simpler to
describe this way.) In the first stage, go up the tree from the new leaf to the root, adding a to every
sum field and 1 to every size field (excluding the new leaf itself). In the second stage, go up the path
from the new leaf towards the root, adjusting BF fields and performing rotations as in normal AVL tree
insertion. Note that rotations may require changing sum and size fields as well, but this can be done
in constant time for each rotation using the identities size(x) = size(lchild(x)) + 1 + size(rchild(x)) and
sum(x) = sum(lchild(x)) + elmt(x) + sum(rchild(x)).
The Delete(A, i) operation: Using Query(root, i), we first find the node we want to delete. Assume
for the moment that this is a leaf, say with key a. First, remove this leaf and go up to the root, reducing
by a the sum field and by 1 the size field of each node encountered. Then go up towards the root from
where the leaf was, adjusting BF fields and performing rotations as in normal AVL tree deletion; note that
rotations may require changing sum and size fields as well, but this can be done in constant time for each
rotation.
Now consider the case where we want to delete a node u that is not a leaf, where u has key a. If u does
not have a right child then it must have a left child v (because u is not a leaf) and v must be a leaf (why?).
We replace the key in u by the key in v, and we now delete the leaf v as above. Finally we consider the
case where u has a right child. Let v be the leftmost node of the right subtree of u, and let b be the key
of v. We now wish to replace u with v. We do this as follows: If v is a leaf, then remove it, otherwise
replace it with its right subtree (which is just a leaf). Go up from v to u (excluding v and u) subtracting
b from every sum field and 1 from every size field. Assign the value b to elmt(u), and go from u to the
root subtracting a from the sum field and 1 from the size field of each node encountered. In effect, we have
replaced the element at node u by the element at node v. Lastly, we go up towards the root from where
v was, adjusting BF fields and performing rotations as in normal AVL tree deletion, while updating the
size and sum fields of rotated nodes, as in the Insert operation.