Upload
others
View
15
Download
0
Embed Size (px)
Citation preview
Binary Search Tree 1
Gnarly Trees: visualization system for tree algorithms,
http://people.ksp.sk/~kuko/bak/index.html
try BST binary search tree (might take awhile to display).
standalone app works better
A random Binary Search Tree
Binary Search Tree
Binary Search Tree 2traversal
BSTNode {
Integer key
BSTNode right, left;
BSTNode(Integer k){
key = k
right = null
left = null }
Integer get() {
return key }
int compareTo(...)
{...};
}
BSTNode root; // “n”...
inorder(BSTNode n) { // iterator
if (n == null) return;
inorder(n.left)
visit() // print?
inorder(n.right)
}
element
left right
n 32
v e
v 17
b g
e 41
u w
b 11
null null
g 23
null null
u 38
null null
w 42
null null
Write w/ generics <Element>
Change order of
“go left”
“visit”
“go right”
root
Binary Search Tree 3Binary Search Tree (BST)
Search Binary Tree to find a target node with specific <Element>
if key is in the list return a reference to the BSTNode
if key is not in the list return null
BSTNode find (Element target) { // public call
return find(root, target; } // private recursive call
BSTNode find(BSTNode current, Element target) {
if (current == null) return current; // empty list
int result = target.compareTo(current.get());
if (result == 0) // target == current
return current;
else if (result < 0) // target < current
return find(current.getLeft(), target);
else // target > 0
return find(current.getRight(), target);
}
Write this algorithm to work with your generic BSTNode<Element> ?
Write this algorithm with a while loop ?
Binary Search Tree 4BSTree <E>
Element is an example
class type for <E>
In application classprivate BSTree bst = new BSTree<Element>();
Binary Search Tree 5Full balanced BST
v 0
null null
p 3
null, n null
n 1
null, v null
v 0
null null
n 1
null,
v
null,
c
c 2
null null
v 0
null null
n 1
v c
c 2
null null
f 4
null null
u 5
f w
w 6
null null
p 3
n u
0 1 2 3 4 5 6
3
1 5
0 2 4 6
root
p
see BinaryPartitionArrayList.java
Binary Search Tree 6Balanced BST growth
height n leafs average log(n,2) difference ceil(log(n,2))
1 1 1 1.00 0.00 -1.000 0
2 3 2 1.67 1.58 -0.082 2
3 7 4 2.43 2.81 0.379 3
4 15 8 3.27 3.91 0.640 4
5 31 16 4.16 4.95 0.793 5
6 63 32 5.10 5.98 0.882 6
7 127 64 6.06 6.99 0.934 7
8 255 128 7.03 7.99 0.963 8
9 511 256 8.02 9.00 0.980 9
10 1,023 512 9.01 10.00 0.989 10
11 2,047 1,024 10.01 11.00 0.994 11
12 4,095 2,048 11.00 12.00 0.997 12
13 8,191 4,096 12.00 13.00 0.998 13
14 16,383 8,192 13.00 14.00 0.999 14
15 32,767 16,384 14.00 15.00 0.999 15
16 65,535 32,768 15.00 16.00 1.000 16
17 131,071 65,536 16.00 17.00 1.000 17
18 262,143 131,072 17.00 18.00 1.000 18
19 524,287 262,144 18.00 19.00 1.000 19
20 1,048,575 524,288 19.00 20.00 1.000 20
Binary Search Tree 7
-1.500
-1.000
-0.500
0.000
0.500
1.000
1.500
1 3 5 7 9 11 13 15 17 19 21 23 25
height
Binary Tree height
ceil( log(n,2)) - average
Binary Search Tree 8initial insertion example
n 32
v e
v 17
b null
g
e 41
u w
b 11
null null
u 38
null null
w 42
null null
root
Assume no duplicates allowed
insert (g ) // 23
C1 root
g < C1 && C1.left != null
T: C2 C1.left
g > C2 && C2.right != null
T: C3 C2.right
F: g > C2 && C2.right == null
T: C2.right g
done
insert (t ) // 7
C1
C2
g 23
null null
Binary Search Tree 92 insertion cases
Assumes no duplicate Elements allowed in BST
void insert (BSTNode newNode)
1. Empty tree
root == null && size == 0
root newNode
size 1
2. Non-empty tree // all insertions result in ordered search tree
current root
Search for insertion place // insertion is always at a leaf
newNode < current && current.left ! null ?
current current.left
newNode < current && current.left == null ?
current.left newNode
// 2 similar situations when newNode > current
size++
BST Recursive insert Binary Search Tree 10
Algorithms (insert and delete) adapted from C. Shaffer, Data Structures
& Algorithm Analysis in Java, 3rd edition, Dover, 2011.
BSTNode<E> insertR (BSTNode<E> node, BSTNode<E> newNode) {
if (node == null) return newNode; // at leaf
if (node.compareTo(newNode) > 0) // node.key >nNode.key
node.setLeft(insertR (node.left(), newNode)
else node.setRight(insertR (node.right(), newNode)
return node
}
initial call
bst.setRoot(insertR(bst.getRoot,
new BSTNode<E>( new E(key)) ))
insert: 3, 1, 0, 2, 5, 4, 6
Binary Search Tree 11trace of recursive insert
RBSTDemo run:
aBST: size = 0 root = null
insert [3,null,null] leaf root <-- 3
insert [1,null,null] 1<3 L leaf 3L <-- 1 root <-- 3
insert [0,null,null] 0<3 L 0<1 L leaf 1L <-- 0
3L <-- 1 root <-- 3
insert [2,null,null] 2<3 L 2>1 R || leaf 1R <-- 2
3L <-- 1 root <-- 3
insert [5,null,null] 5>3 R || leaf 3R <-- 5 root <-- 3
insert [4,null,null] 4>3 R || 4<5 L leaf 5L <-- 4
3R <-- 5 root <-- 3
insert [6,null,null] 6>3 R || 6>5 R || leaf 5R <-- 6
3R <-- 5 root <-- 3
aBST: size = 7 root = [3,1,5]
inorder: [0,null,null]3 [1,0,2]2 [2,null,null]3 [3,1,5]1
[4,null,null]3 [5,4,6]2 [6,null,null]3
Binary Search Tree 12initial deletion example
n 32
v e
e 41
u w
w 42
null null
root
delete (e ) // 41
C1 root
e > C1 && C1.right != null ?
T: C2 C1.right
C2 == e && C2.right != null ?
T: M C2
// find greater replacement
C3 C2
C3.right == null ?
T: replace M.<E> with C3.<E>
replace M.right with C3.right
Replacement with immediate
predecessor is an equivalent
alternative to immediate successor.
Notes will use successor.
n 32
v e
root
e 42
u null
C1 C2 M
C3
Binary Search Tree 137 deletion cases
Assumes no duplicate Elements allowed in BST
deletedNode BSTNode delete(BSTNode target)
BSTNode current, last, marked, temp;
initially current root, last null, marked null, temp null
1. Empty tree
root == null, size == 0,
return null
Find target, last current before current updated, mark for deletion
2. target is root, root only node in tree
root.left == null && root.right == null
root null
size --
return current
nullroot
root target
null null
current
nullroot
target
null null
current
Binary Search Tree 14case 3
3. target is root, no successor, has predecessor
root.right == null && root.left != null
root root.left
size --
return current
roottarget
null
value
? ?
current
roottarget
null
value
? ?
current
Binary Search Tree 15cases 4
4. target is a leaf has no successor && no predecessor
current.left == null && current.right == null
2 situations:
last < current : last.right null // shown below
last > current : last.left null // draw as an exercise
size --
return current
rootvaluei
target
null null
last
current
rootvaluei
null
target
null null
last
current
there can be many nodes between root and target
Binary Search Tree 16case 5
Mark target and search for immediate successor cases.
marked current
5. target's has a left, but no right (no successor) , propogate left up tree
2 situations:
last < current : last.right current.left
last > current : last.left current.left // shown
size --
return current
root
valuej
target
null
last
mark
valuei
current
root
valuej
target
? null
valuei
Binary Search Tree 17cases 6
target has a successor (cases 6 and 7)
last current, current current.right
6. target's immediate right has no left predecessor branch
current.left == null, current.right != null
copy marked into temp
copy current's value and left into marked
size --
last.right current.right, return temp
temp
target
root
targetlast
valuei
null
mark
current
valueilast
mark
Binary Search Tree 18case 7
7. target's immediate right has a left predecessor
that leads to an immediate successor.
copy marked into temp
copy current into marked
size --
last.left null
return temp
root
target
last
valuei
null null
mark
current
valuei
last
marktemp
target
valuej
null
BST Recursive delete
BSTNode<E> deleteR (BSTNode<E> node, BSTNode<E> target) {
if (node == null) return null; // halt, leaf not found
// find target
if (node.compareTo(target) > 0) // node.key > target.key
node.setLeft() = deleteR(node.getLeft(), target)
else if (node.compareTo(target) < 0) // n.key < t.key
node.setRight() = deleteR(node.getRight(), target)
else // found target
// only right child
if(node.getLeft() == null) return node.getRight();
else // two children
BSTNode<E> temp = getMinR(node.getRight())
node.set(temp.get()); // sets E
node.setRight(deleteMinR(node.getRight())
return node
}
Binary Search Tree 19
getMinR(…), deleteMinR(…)
BSTNode<E> getMinR (BSTNode<E> node) {
if (node.getLeft() == null) return node
return getMinR(node.getLeft();
}
BSTNode<E> deleteMinR (BSTNode<E> node) {
if (node.getLeft() == null) return node.getRight()
node.setLeft(deleteMinR(node.getLeft())
return node;
}
Binary Search Tree 20
trace recursive deleteBinary Search Tree 21
Tree 37
/ \
24 42
/ \
40 43
\ \
41 120
delete 42
[37,24,42], < 0 setR(n.R), [42,40,43], == found,
getMin(n.R), [43,null,120][43,null,120], halt GetMin <--
[43,null,120], replace w/ 43, R <-- DeleteMin(n.R),
[43,null,120], halt DeleteMin <-- [120,null,null],
Tree 37
/ \
24 43
/ \
40 120
\
41
Try to trace delete of 37
recursive Vs non-recursiveBinary Search Tree 22
Non recursive create delete re-insertbalanced 73.58 126.09 105.85random 95.22 131.76 109.79% difference 29% 4% 4%
Recursive create delete re-insertbalanced 84.87 153.84 129.93random 116.47 168.61 136.61% difference 37% 10% 5%
% Recursive > Non Recursive create delete re-insert
balanced 15% 22% 23%random 22% 28% 24%
Consider a BST simulation experiment recursive and non-recursive
implementations in Java. The experiment created either a random or a
balanced tree with 210-1 nodes, deleted 29-1 nodes, and then re-inserted
28-1 (half of the deleted) nodes.
The results are time in nanoseconds / operation.
Why is creation faster than
either delete or re-insert?
Why are delete and
re-insert about the same?
Why is recursion slower?
Binary Search Tree 23Duplicate keys
Walkthrough: create aBSTree // do operations below in order
insert: 3, 1, 0, 2, 5, 4, 6 // state the cases
delete: 0, 1, 3, 5, 6, 4, 2, 2 // state the cases
Consider a BST with duplicate key values
but <E> element's other values are different. (Each E is unique).
Duplicate collection holds all E elements that share "key"
ArrayList<E> size() <= store, unused "?i" allocations
SinglyLinkedList <E>
key
left
ArrayList<E>
right
key
left
SinglyLinkedList<E>
right
E0 E1 En... ?0 ?1 ?n...
E0 E1 En
Key V0 V1 ... Vn
<E>
Binary Search Tree 24Huffman codes
Frequency Symbol
47 " "46 E45 T44 043 142 2
...26 "25 '24 A23 O22 I
...5 K4 X3 J2 Q1 Z
Normal symbol encoding is fixed
length (unicode, utf16).
Symbols can be coded with variable
length codes assigned by their
relative requency.
Here is graph of relative frequncy
for English letters, digits, and
punctuation.
Huffman coding uses
relative frequency and
binary tree to assign
variable codes.
http://en.wikipedia.org/wiki/Letter_frequency
Binary Search Tree 25
Consider a more limited vocabulary and relative frequency
Vocabulary Vocabulary length
symbol A B C D E F G 16 bit fixed code = 112 bits
frequency 6 5 4 1 2 2 3 Huffman code = 21 bits
while (more than 1 parentless node)
select 2 parentless nodes with smallest weights (frequency)
(break ties arbitrarily)
create a new node as their parent,
its weight sum child weights
label branches of tree all non-leaf nodes
left branch '0', right branch '1'
symbol code is concatenation of edge labels (0 or 1)
on path from root to symbol.
Applied Data Structures with C++, P. Smith, Jones Bartlett, 2004, pp 291-295
D (1) E (2)
3
F (2) G (3)
5
C (4)B (5)A (6)
Symbol code is the traversal from root to symbol leaf
Decode string: from root traverse tree using current digit to leaf
100001101011
100 C
00 A
110 F
1011 E
1011111001010
??
Binary Search Tree 26
D (1) E (2)
3
F (2) G (3)
5
C (4)B (5)A (6)
7
11
12
23
0
0
0
0
0 0
1
1
1
1
11
Binary Search Tree 27expressions as grammar
Grammar rules
x | y means x or y
x y means x followed by y
<word> means instance of "word" that is defined
Algebraic expression can be written as grammars.
Assume only binary operators like a + 10, not unary like –t
<op> = + | - | * | /
<term> = <constant> | <variable>
in-fix expression use "( ...)" to indicate operator precedence
pre- and post- fix expressions do not require "( ... )" for precedence
in-fix pre-fix remove matching parens, replace first with <op>
in-fix post-fix remove matching parens, replace second with <op>
prefix expression = <op> <term> <term>
postfix expression = <term> <term> <op>
Binary Search Tree 28expression as parse tree
*
+ *
A B / G
- +
C D E F
Consider this "in-fix" expression:
(A + B) * ((C – D) / (E + F) * G)
Traversals:
pre-order (VLR)
* + A B * / - C D + E F G
post-order (LRV)
A B + C D – E F + / G * *
t1 A + B t2 C – D
t3 E + F t4 t2 / t3
t5 t4 * G t1 * t5
post-order is a "post-fix" evaluation
of a fully parenthesized "in-fix"
expression.
aka RPN (Reverse Polish Notation)
Build expression parse tree using a stack ADT, later course topic...
Binary Search Tree 29Heap, BST in ArrayList
BST – insertion and deletion
O(log n) to O(n) // balanced to list
Better if full and balanced ... if balanced consider array based heap
Heap is a tree with weak (partially sorted) ordering
Heap is empty or its root references its highest priority value and
whose subtrees are also heaps.
Heaps are complete binary trees O(log n)
ArrayList based implementationclass Heap {
ArrayList <T> item;
// assume <T> implements Comparable's compareTo(...)
// or change for Comparator's compare(...)
// assume following method to swap item[i], item[j]
public void swap(int i, int j);
Binary Search Tree 30Heap – insert
insert(<T> value) {
int current, parent;
item.add(value) // add appends at end of arraylist
current = item.size() - 1
parent = (current - 1) / 2
while (parent >= 0 && item.get(current) >
item.get(parent))
{
swap(current, parent)
current = parent
parent = (current -1) /2
}
}
insert 92, 37, 78, 19 // no swap all inserts at end
insert: 57 heap 92, 37, 78, 19, 57 swap(4, 1)
92, 57, 78, 19, 37
insert 98 heap 92, 57, 78, 19, 37, 98 swap(5, 2)
98, 57, 92, 19, 37, 78 swap(2, 0)
insert 29, 77, 68, 52 heap 98 77 92 68 52 78 29 19 57 37
Binary Search Tree 31
98
77 92
68 52 78 29
19 57 3757
52 37
19 29
After 10 insertion:
Heap 98, 77, 92, 68, 52, 78, 29, 19, 57, 37
After 5 deletions:
Heap 57, 52, 37, 19, 29
Binary Search Tree 32Heap – delete
delete() { // assume ! heap.isEmpty()
value = item.get(0) // root is first element
item.set(0) = item.get(size() -1) // replace w/ last
item.remove(size() – 1) // remove last item
rebuild(0) // rebuild sub-heaps
return value
}
Delete 98
Heap 37, 77, 92, 68, 52, 78, 29, 19, 57 swap (0, 2)
92, 77, 37, 68, 52, 78, 29, 19, 57 swap (2, 5)
92, 77, 78, 68, 52, 37, 29, 19, 57
Delete 92
heap 57, 77, 78, 68, 52, 37, 29, 19 swap (0, 2)
78, 77, 57, 68, 52, 37, 29, 19
Delete 78
heap 19, 77, 57, 68, 52, 37, 29 swap (0, 1)
77, 19, 57, 68, 52, 37, 29 swap (1, 3)77, 68, 57, 19, 52, 37, 29
Binary Search Tree 33
rebuild(int root) {
int child, rChild
child = 2 * root + 1
if (child < item.size()) { // root ! leaf
rChild = child + 1
if ( (rChild < item.size()) &&
item.get(rChild).compareTo(item.get(child)) > 0 )
child = rChild // child is largest sibling
if (item.get(child).compareTo(item.get(root)) > 0)
{
swap(root, child)
rebuild(child)
}
}
}
Heap – rebuild
Binary Search Tree 34JCF PriorityQueue
maxHeap has largest value priority order (smallest value is minHeap)
JCF PriorityQueue <T> is a minHeap implementation.
O(log n) – offer(Element), add(Element), poll(), remove()
O(n) – remove(Object), contains(Object)
O(1) – peek(), element(), size()
Binary Search Tree 35exercises
1. Modify an inorder recursive traversal to print the node's value and
height. The height is not stored in the node, but determined at traversal.
2. Perform the following operations sequentially on a BSTree that is
initially empty. This is an on-paper exercise.
insert 10, 4, 2, 20, 8, 9, 15, 13, 50
delete 20, 2, 50, 15, 10, 4
3. trace the recursive insert (insertR) and delete (deleteR) algorithms for
#2
4. Do the BST operations in 2 using the Gnarly trees visual simulation
program.
5. Write a non-recursive BST insert and deletion algorithm using
BSTree and BSTNode classes on slide 4 (you can omit Element).
Binary Search Tree 36
23
2
9
6 12
50
36
29
32
75
61
53 72
6. Design a “visit-by level” traversal. For the example tree the visitation
order is:
23, 2, 50, 9, 36, 75, 6,
12, 29, 61, 32, 53, 72
7. Write a recursive "descend" traversal to visit a BST's key values in
descending order (assume integer keys, or implementation of
Comparable).