CS 3110 Lecture 11
Balanced Binary Trees: RedBlack Trees
Sets and maps are important and useful abstractions. We've seen various ways to implement an abstract data
type for sets and maps, since data structures that implement sets can be used to implement maps as well.
Today we will look at an implementation of sets that is asymptotically efficient and useful in practice. This
implementation is one of several
balanced binary tree
schemes.
Binary trees have two advantages above the asymptotically more efficient hash table: first, they support
nondestructive update with the same asymptotic efficiency. Second, they store their values (or keys, in the
case of a map) in order, which makes range queries and inorder iteration possible.
An important property of a search tree is that it can be used to implement an
ordered set
or ordered map
easily: a set (map) that abstractly keeps its elements in sorted order. Although we will not consider such
operations today, ordered sets generally provide operations for finding the minimum and maximum elements
of the set, for iterating over all the elements between two elements, and for extracting (or iterating over)
ordered subsets of the elements between a range:
Binary search trees
A binary tree is easy to define inductively in OCaml. We will use the following definition which represents a
node as a triple of a value and two children, and which explicitly represents leaf nodes.
type 'a tree = TNode of 'a * 'a tree * 'a tree  TLeaf
A
binary search tree
is a binary tree with the following representation invariant: For any node
n
, every node
in the left subtree of
n
has a value less than that of
n
, and every node in the right subtree of
n
has a value
more than that of
n
.
Given such a tree, how do you perform a lookup operation? Start from the root, and at every node, if the
value of the node is what you are looking for, you are done; otherwise, recursively look up in the left or right
subtree depending on the value stored at the node. In code:
let rec contains x = function
TLeaf > false
 TNode (y, l, r) >
if x=y then true else if x < y then contains x l else contains x r
Note the use of the keyword
function
so that the variable used in the pattern matching need not be named.
This is equivalent to (unneccessarily) naming a variable and then using
match
:
let rec contains x t =
match t with
TLeaf > false
 TNode (y, l, r) >
if x=y then true else if x < y then contains x l else contains x r
Adding an element is similar: you perform a lookup until you find the empty node that should contain the
value. This is a nondestructive update, so as the recursion completes, a new tree is constructed that is just like
the old one except that it has a new node (if needed):
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
This is the end of the preview.
Sign up
to
access the rest of the document.
 '07
 GIAMBATTISTA,A

Click to edit the document details