Title: Binary Search Tree
1Binary Search Tree
- A kind of binary tree
- Each node stores an item
- For every node X, all items in its left subtree
are smaller than X and all items in its right
subtree are larger than X
2Binary Search Tree
3Algorithms for Binary Search Tree
- Most algorithms for binary search trees use
recursive function. - Recursively apply the same function on either
left or right subtree, depending on the value
stored in the root.
4Binary Search Tree Find
Recursively finds the node that contain X in
either left or right subtree.
5Binary Search Tree Insert
insert 5
Recursively inserts X into either left or right
subtree.
6Delete (with one child)
delete 4
Recursively delete X from either left or right
subtree.
7Delete (with two children)
delete 2
delete (3)
Replace data of the node (2) with the smallest
data of its right subtree (3) and delete that
node (3) from the right subtree
8Comparable Interface
- Read section 1.4.3 and B.2.3
- Searching and sorting algorithms work on Objects
that can be compared to each other. In other
words, these Objects must have some method for
comparing. - An interface declares a set of methods that a
class that implements the interface must have. - Comparable interface declares compareTo( )
method. - Searching and sorting algorithms work on any
Objects that implement Comparable interface.
9compareTo( )
- int compareTo( Object rhs ) returns negative if
this Object is less than rsh, zero if they are
equal, and positive if this Object is greater
than rhs - String and wrapper classes such as Integer all
implement Comparable interface and therefore have
compareTo( ) method.
10- public interface Comparable
-
- int compareTo( Comparable rhs )
-
- public class MyInterger implements Comparable
-
- public int compareTo( Comparable rhs )
-
- return value lt ((MyInteger)rhs).value ? -1
- value ((MyInteger)rhs).value ? 0
1 -
- ...
- ...
11Binary Search Tree
class BinaryNode //
Constructors BinaryNode( Comparable
theElement ) this(
theElement, null, null )
BinaryNode( Comparable theElement, BinaryNode lt,
BinaryNode rt ) element
theElement left lt
right rt //
Friendly data accessible by other package
routines Comparable element // The
data in the node BinaryNode left
// Left child BinaryNode right //
Right child
12 public class BinarySearchTree
public BinarySearchTree( ) root null
public void insert( Comparable
x ) public void remove(
Comparable x ) public Comparable
findMin( ) public Comparable findMax( )
public Comparable find( Comparable x )
public void makeEmpty( )
public boolean isEmpty( )
public void printTree( )
private Comparable elementAt( BinaryNode t )
private BinaryNode insert( Comparable x,
BinaryNode t ) private BinaryNode
remove( Comparable x, BinaryNode t )
private BinaryNode findMin( BinaryNode t )
private BinaryNode findMax( BinaryNode t )
private BinaryNode find( Comparable x,
BinaryNode t ) private void
printTree( BinaryNode t ) private
BinaryNode root
13 public static void main( String args
) final int NUMS 4000
BinarySearchTree t new
BinarySearchTree( )
for( int i 1 i lt NUMS i )
t.insert( new MyInteger( i ) )
for( int i 1 i lt NUMS i 2 )
t.remove( new MyInteger( i ) ) if(
NUMS lt 40 ) t.printTree( ) if(
((MyInteger)(t.findMin( ))).intValue( ) ! 2
((MyInteger)(t.findMax(
))).intValue( ) ! NUMS - 2 )
System.out.println( "FindMin or FindMax error!"
)
14 public void printTree( )
if( isEmpty( ) )
System.out.println( "Empty tree" )
else printTree( root )
private void printTree( BinaryNode t )
if( t ! null )
printTree( t.left )
System.out.println( t.element )
printTree( t.right )
15 public Comparable find( Comparable x )
return elementAt( find( x, root )
) private BinaryNode find(
Comparable x, BinaryNode t )
/ find() recursively finds the node that
contain x in either left or right subtree
and returns a reference to that node, and
returns null if not found / if( t
null ) return null
if( x.compareTo( t.element ) lt 0 )
return find( x, t.left ) else if(
x.compareTo( t.element ) gt 0 )
return find( x, t.right ) else
return t // Match
16 public Comparable findMin( )
return elementAt( findMin( root ) )
private BinaryNode findMin( BinaryNode t )
/ Find the left-most leaf node /
if( t null ) return
null else if( t.left null )
return t return findMin(
t.left ) / Nonrecursive
implementation private BinaryNode findMin(
BinaryNode t ) if( t !
null ) while ( t.left ! null )
t t.left
return t /
17 public Comparable findMax( )
return elementAt( findMax( root ) )
private BinaryNode findMax( BinaryNode t )
/ Find the right-most leaf node /
if( t null ) return
null else if( t.right null )
return t return findMax(
t.right ) / Nonrecursive
implementation private BinaryNode findMax(
BinaryNode t ) if( t !
null ) while( t.right ! null )
t t.right
return t /
18 public void insert( Comparable x )
root insert( x, root )
private BinaryNode insert( Comparable x,
BinaryNode t ) / insert() recursively
inserts data into either left or right subtree
and returns a reference to the root
of the new tree / / 1/ if( t
null ) / 2/ t new BinaryNode( x,
null, null ) / 3/ else if( x.compareTo(
t.element ) lt 0 ) / 4/ t.left
insert( x, t.left ) / 5/ else if(
x.compareTo( t.element ) gt 0 ) / 6/
t.right insert( x, t.right ) / 7/
else / 8/ // Duplicate do
nothing / 9/ return t
19 public void remove( Comparable x )
root remove( x, root ) private
BinaryNode remove( Comparable x, BinaryNode t )
/ remove() recursively removes data
from either left or right subtree and returns a
reference to the root of the new
tree / if( t null )
return t // Item not found do nothing
if( x.compareTo( t.element ) lt 0 )
t.left remove( x, t.left )
else if( x.compareTo( t.element ) gt 0 )
t.right remove( x, t.right )
else if( t.left ! null t.right ! null ) /
Two children. Replace data of this node with the
smallest data of the right subtree and delete
that node from the right subtree. /
t.element findMin( t.right
).element t.right remove(
t.element, t.right )
else t ( t.left ! null ) ?
t.left t.right return t
20Lazy Deletion
- When an element is to be deleted, it is left in
the tree and marked as being deleted. - If there are duplicate items, the variable that
keeps the number of duplicated items is just
decremented. - If a deleted item is reinserted, no need to
allocate new node.
21Shape, Height, and Size
- Given height, balanced tree hold maximum number
of nodes - Given number of nodes, balanced tree is the
shortest - When height increases by one, number of nodes in
balanced tree approximately doubles.
22Average-Case
- Balanced binary tree height log(n1) - 1
- Average binary tree height O(log N)
- After lots of insert/remove operations, binary
search tree becomes imbalance (remove operation
make the left subtree deeper than the right) - If insert presorted data into binary search tree,
the tree will have only nodes with right child.
23Balance Binary Search Trees
First attempt Left and right subtree must have
the same height
Second attempt Every node must have left and
right subtrees of the same height
24AVL Tree
- AVL Tree Adelson-Velskii and Landis Tree
- A binary search tree with balance condition
- Self-adjusting to maintain balance condition
- Ensure that the depth of the tree is O(log N)
25AVL Tree
- For every node, the height of the left and right
subtrees can differ by at most 1 - Height information is kept for each node
- Height is at most 1.44log(N2) - .328
or slightly more than logN
26An AVL Tree
Not an AVL Tree
8
12
4
2
6
5
7
27Smallest AVL Tree of Height 5
Minimum number of nodes in an AVL tree of height
h is S(h) S(h-1)S(h-2)1, S(0)1, S(1) 2
28Violation of the AVL Property
- Inserting a node could violate the AVL property
if it cause a height imbalance (two subtrees
height differ by two) - Solution The deepest node with imbalanced
subtrees must be rebalanced
29Insertion Causes Imbalance
30Four Cases of Violation
Insert into left subtree of the left child
Insert into right subtree of the right child
31Four Cases of Violation
Insert into right subtree of the left child
Insert into left subtree of the right child
32Four Cases of Violation
33Single Rotation
k1
After
Before
k2
k1
k2
Z
Y
X
Y
Z
X
Insertion of 1 causes X to be one level deeper
than Y and two level deeper than Z. The
violation occurs at k2. The rotation maintains
k1 lt Y lt k2. X is lifted up one level, Y remains
at the same level, and Z is lowered down one
level. The new height is the same as before the
insertion.
34Single Rotation
Before
After
35Single Rotation (this one does not work)
Before
After
Z
X
X
Z
Y
Y
Y remains at the same level, so it does not work.
36Double Rotation
Before
After double rotation
An insertion into Y1 or Y2 causes violation at
k3. k1 lt Y1 lt k2 lt Y2 lt k3
37Double Rotation
After first rotation
Before
8
12
4
2
38Double Rotation
After first rotation
After second rotation
39Double Rotation
After first rotation
Before
40Double Rotation
After first rotation
After second rotation
41class AvlNode Comparable element AvlNode
left AvlNode right int
height AvlNode( Comparable theElement )
this( theElement, null, null ) AvlNode(
Comparable theElement, AvlNode lt, AvlNode rt )
element theElement left lt right rt
height 0
42private AvlNode insert( Comparable x, AvlNode t
) if( t null ) t new AvlNode(
x, null, null ) else if( x.compareTo(
t.element ) lt 0 ) / insert into the left
subtree / t.left insert( x, t.left )
if(height( t.left ) - height( t.right )
2 ) if( x.compareTo( t.left.element )
lt 0 ) t rotateWithLeftChild( t
) else t
doubleWithLeftChild( t )
43 else if( x.compareTo( t.element ) gt 0 )
/ insert into the right subtree /
t.right insert( x, t.right ) if(
height( t.right ) - height( t.left ) 2 )
if( x.compareTo( t.right.element ) gt 0 )
t roteWithRightChild( t )
else t doubleWithRightChild(
t ) else t.height
max( height( t.left ), height( t.right ) ) 1
return t
44private static AvlNode rotateWithLeftChild(
AvlNode k2 ) AvlNode k1 k2.left
k2.left k1.right k1.right k2
k2.height max( height( k2.left ), height(
k2.right ) ) 1 k1.height max( height(
k1.left ), k2.height ) 1 return
k1 private static AvlNode doubleWithLeftChild(
AvlNode k3 ) k3.left rotateWithRightChild
( k3.left ) return rotateWithLeftChild( k3
)