Transcript part4-trees
CSE 326: Data Structures
Part Four: Trees
Henry Kautz
Autumn 2002
1
Material
Weiss Chapter 4:
• N-ary trees
• Binary Search Trees
• AVL Trees
• Splay Trees
2
Other Applications of Trees?
3
Tree Jargon
• Length of a path =
number of edges
• Depth of a node N =
length of path from
root to N
• Height of node N =
length of longest
path from N to a leaf
depth=0, height = 2 A
B
depth = 2, height=0 E
C
D
F
• Depth and height of
tree = height of root
4
Definition and Tree Trivia
Recursive Definition of a Tree:
A tree is a set of nodes that is
a. an empty set of nodes, or
b. has one node called the root from which
zero or more trees (subtrees) descend.
• A tree with N nodes always has ___ edges
• Two nodes in a tree have at most how many
paths between them?
5
Implementation of Trees
• Obvious Pointer-Based Implementation: Node with
value and pointers to children
– Problem?
A
C
B
E
D
F
6
1st Child/Next Sibling
Representation
• Each node has 2 pointers: one to its first child and
one to next sibling
A
A
C
B
E
D
F
C
B
E
D
F
7
Nested List Implementation 1
Tree := ( label {Tree}* )
a
b
d
c
8
Nested List Implementation 2
Tree := label || (label {Tree}+ )
a
b
d
c
9
Application: Arithmetic
Expression Trees
Example Arithmetic Expression:
+
A + (B * (C / D) )
A
*
Tree for the above expression:
• Used in most compilers
• No parenthesis need – use tree structure
• Can speed up calculations e.g. replace
/ node with C/D if C and D are known
• Calculate by traversing tree (how?)
B
/
C
D
10
Traversing Trees
+
• Preorder: Root, then Children
– +A*B/CD
A
*
• Postorder: Children, then Root
– ABCD/*+
B
• Inorder: Left child, Root, Right child
/
– A+B*C/D
D
C
11
Example Code for Recursive
Preorder
void print_preorder ( TreeNode T)
{
TreeNode P;
if ( T == NULL ) return;
else { print_element(T.Element);
P = T.FirstChild;
while (P != NULL) {
print_preorder ( P );
P = P.NextSibling; }
}
}
What is the running time for a tree with N nodes?
12
Binary Trees
• Properties
Notation:
depth(tree) = MAX {depth(leaf)} = height(root)
–
–
–
–
max # of leaves = 2depth(tree)
max # of nodes = 2depth(tree)+1 – 1
max depth = n-1
average depth for n nodes = n D
(over all possible binary trees)
• Representation:
A
B
C
E
F
G
H
Data
left
right
pointer pointer
I
J
13
Dictionary & Search ADTs
• Operations
–
–
–
–
–
create
destroy
insert
find
delete
•
insert
•kohlrabi
- upscale tuber
–
•
find(kreplach) •
• kreplach
- tasty stuffed dough
kim chi
spicy cabbage
kreplach
–
tasty stuffed dough
kiwi
–
Australian fruit
• Dictionary: Stores values associated with userspecified keys
– keys may be any (homogenous) comparable type
– values may be any (homogenous) type
– implementation: data field is a struct with two parts
• Search ADT: keys = values
14
Naïve Implementations
unsorted
array
sorted
array
linked
list
insert
(w/o duplicates)
find
delete
Goal: fast find like sorted array,
dynamic inserts/deletes like linked list
15
Naïve Implementations
unsorted
array
insert
sorted
array
linked
list
find + O(1) O(n)
find + O(1)
find
O(n)
O(n)
delete
find + O(1) O(n)
(w/o duplicates)
O(log n)
find + O(1)
Goal: fast find like sorted array,
dynamic inserts/deletes like linked list
16
Binary Search Tree
Dictionary Data Structure
• Search tree property
– all keys in left subtree
smaller than root’s key
– all keys in right subtree
larger than root’s key
– result:
• easy to find any given
key
• inserts/deletes by
changing links
8
5
2
11
6
4
10
7
9
12
14
13
17
In Order Listing
visit left subtree
visit node
visit right subtree
10
5
15
2
9
7
20
17 30
In order listing:
18
In Order Listing
visit left subtree
visit node
visit right subtree
10
5
15
2
9
7
20
17 30
In order listing:
25791015172030
19
Finding a Node
10
5
2
9
7
Node find(Comparable x, Node
root)
{
if (root == NULL)
return root;
15
else if (x < root.key)
return find(x,root.left);
20
else if (x > root.key)
return find(x, root.right);
else
17 30
return root;
}
runtime:
20
Insert
Concept: proceed down tree as in Find; if new key not found,
then insert a new node at last spot traversed
void insert(Comparable x, Node root) {
// Does not work for empty tree – when root is
NULL
if (x < root.key){
if (root.left == NULL)
root.left = new Node(x);
else insert( x, root.left ); }
else if (x > root.key){
if (root.right == NULL)
root.right = new Node(x);
else insert( x, root.right ); } }
21
Time to Build a Tree
Suppose a1, a2, …, an are inserted into an initially empty BST:
1. a1, a2, …, an are in increasing order
2. a1, a2, …, an are in decreasing order
3. a1 is the median of all, a2 is the median of elements
less than a1, a3 is the median of elements greater than
a1, etc.
4. data is randomly ordered
22
Analysis of BuildTree
• Increasing / Decreasing: (n2)
1 + 2 + 3 + … + n = (n2)
• Medians – yields perfectly balanced tree
(n log n)
• Average case assuming all input sequences
are equally likely is (n log n)
– equivalently: average depth of a node is log n
Total time = sum of depths of nodes
23
Proof that Average Depth of a Node in a BST
Constructed from Random Data is (log n)
Method: Calculate sum of all depths, divide by number
of nodes
• D(n) = sum of depths of all nodes in a random BST
containing n nodes
• D(n) = D(left subtree)+D(right subtree)
+ adjustment for distance from root to subtree
+ depth of root
• D(n) = D(left subtree)+D(right subtree)
+ (number of nodes in left and right subtrees)
+0
• D(n) = D(L)+D(n-L-1)+(n-1)
24
Random BST, cont.
• D(n) = D(L)+D(n-L-1)+(n-1)
• For random data, all subtree sizes equally likely
n 1
E[ D(n)] Prob(left tree size is L)E[ D(n) when left tree size is L]
L 0
n 1
1
E[ D( L)] E[ D(n L 1)] (n 1)
L 0 n
E[ D(n)]
2 n 1
E[ D(n)] E[ D( L)] (n 1)
n L 0
E[ D(n)] O(n log n)
E[ D(n) / n] O(log n)
this looks just like the
Quicksort average case
equation!
25
n versus log n
Why is average depth of BST's made from
random inputs different from the average
depth of all possible BST's?
log n
n
Because there are more ways to build shallow
trees than deep trees!
26
Random Input vs. Random Trees
For three items, the
shallowest tree is
twice as likely as
any other – effect
grows as n
increases. For n=4,
probability of
getting a shallow
tree > 50%
Inputs
1,2,3
3,2,1
1,3,2
3,1,2
2,1,3
2,3,1
Trees
27
Deletion
10
5
15
2
9
7
20
17 30
Why might deletion be harder than insertion?
28
FindMin/FindMax
10
5
2
Node min(Node root) {
if (root.left == NULL) 7
return root;
else
return min(root.left);
}
15
9
How many children can the min of a node have?
20
17 30
29
Successor
Find the next larger node
in this node’s subtree.
– not next larger in entire
tree
10
5
Node succ(Node root) {
2
9
if (root.right == NULL)
return NULL;
7
else
return
min(root.right);
}
How many children can the successor of a node have?
15
20
17 30
30
Deletion - Leaf Case
10
Delete(17)
5
15
2
9
7
20
17 30
31
Deletion - One Child Case
10
Delete(15)
5
15
2
9
7
20
30
32
Deletion - Two Child Case
10
Delete(5)
5
20
2
9
30
7
replace node with value guaranteed to be between the left and
right subtrees: the successor
Could we have used the predecessor instead?
33
Deletion - Two Child Case
10
Delete(5)
5
20
2
9
30
7
always easy to delete the successor – always has either 0 or 1
children!
34
Deletion - Two Child Case
10
Delete(5)
7
20
2
9
30
7
Finally copy data value from deleted successor into original
node
35
Lazy Deletion
• Instead of physically deleting
nodes, just mark them as
deleted
+
+
+
–
–
–
simpler
physical deletions done in batches
some adds just flip deleted flag
extra memory for deleted flag
2
many lazy deletions slow finds
some operations may have to be
modified (e.g., min and max)
10
5
15
9
7
20
17 30
36
Dictionary Implementations
unsorted
array
find +
O(1)
sorted
array
O(n)
linked
list
find +
O(1)
BST
find
O(n)
O(log n)
O(n)
O(Depth)
delete
find +
O(1)
O(n)
find +
O(1)
O(Depth)
insert
O(Depth)
BST’s looking good for shallow trees, i.e. the depth D is
small (log n), otherwise as bad as a linked list!
37
CSE 326: Data Structures
Part 3: Trees, continued
Balancing Act
Henry Kautz
Autumn Quarter 2002
38
Beauty is Only (log n) Deep
• Binary Search Trees are fast if they’re shallow
e.g.: complete
• Problems occur when one branch is much
longer than the other
How to capture the notion of a “sort of” complete
tree?
39
Balance
t
5
6
balance = height(left subtree) - height(right subtree)
• convention: height of a “null” subtree is -1
• zero everywhere perfectly balanced
• small everywhere balanced enough: (log n)
– Precisely: Maximum depth is 1.44 log n
40
AVL Tree
Dictionary Data Structure
• Binary search tree
properties
• Balance of every node is
-1 b 1
• Tree re-balances itself
after every insert or
delete
8
5
2
11
6
4
10
7
9
What is the balance of each node in this tree?
12
13 14
15
41
AVL Tree Data Structure
3
10
1
3
height
15
0
0
2
data
children
2
5
10
9
0
1
12
20
0
17
0
30
42
Not An AVL Tree
4
10
1
4
height
15
0
0
2
data
children
3
5
10
9
0
2
12
20
1
0
17
30
0
18
43
Bad Case #1
Insert(small)
Insert(middle)
Insert(tall)
S
2
1
M
0
T
44
Single Rotation
S
2
1
M
1
M
0
0
T
0
S
T
Basic operation used in AVL trees:
A right child could legally have its
parent as its left child.
45
General Case: Insert Unbalances
a
h
h+1
a
h-1
h+1 b
h-1
b
X
X
h-1
h
h-1
Z
Y
h+2
h-1
Y
h+1
Z
b
h
h
a
h-1
h-1
Z
Y
X
46
Properties of General Insert +
Single Rotation
• Restores balance to a lowest point in tree
where imbalance occurs
• After rotation, height of the subtree (in the
example, h+1) is the same as it was before
the insert that imbalanced it
• Thus, no further rotations are needed
anywhere in the tree!
47
Bad Case #2
Insert(small)
Insert(tall)
Insert(middle)
S
2
1
Why won’t a single
rotation (bringing T up to
the top) fix this?
T
0
M
48
Double Rotation
S
2
S
1
T
M
0
2
1
M
1
M
0
T
0
0
S
T
49
General Double Rotation
a
h+3
h+2
h+2
c
h
b
h+1
h+1
b
h
h+1
Z
c
a
h
h
h
Y
h
W
Y
W
X
Z
X
• Initially: insert into X unbalances tree (root height goes to h+3)
• “Zig zag” to pull up c – restores root height to h+2, left subtree
height to h
50
Another Double Rotation Case
a
h+3
h+2
h+2
c
h
b
h+1
h+1
b
h
h+1
Z
c
h
h
h
W
X
a
h
X
W
Y
Z
Y
• Initially: insert into Y unbalances tree (root height goes to h+2)
• “Zig zag” to pull up c – restores root height to h+1, left subtree
height to h
51
Insert Algorithm
•
•
•
•
Find spot for value
Hang new node
Search back up looking for imbalance
If there is an imbalance:
“outside”: Perform single rotation and exit
“inside”: Perform double rotation and exit
52
AVL Insert Algorithm
Node insert(Comparable x, Node root){
// returns root of revised tree
if ( root == NULL )
return new Node(x);
if (x <= root.key){
root.left = insert( x, root.left );
if (root unbalanced) { rotate... } }
else { // x > root.key
root.right = insert( x, root.right );
if (root unbalanced) { rotate... } }
root.height = max(root.left.height,
root.right.height)+1;
return root;
53
}
Deletion (Really Easy Case)
3
10
Delete(17)
2
2
5
15
1
0
2
9
0
0
1
12
20
0
3
0
17 30
54
Deletion (Pretty Easy Case)
3
10
Delete(15)
2
2
5
15
1
0
2
9
0
0
1
12
20
0
3
0
17 30
55
Deletion (Pretty Easy Case cont.)
3
10
Delete(15)
2
2
5
17
1
0
2
9
0
0
12
1
20
0
3
30
56
Deletion (Hard Case #1)
3
10
Delete(12)
2
2
5
17
1
0
2
9
0
0
12
1
20
0
3
30
57
Single Rotation on Deletion
3
3
10
2
2
5
0
9
0
2
17
1
2
10
5
20
1
1
20
0
2
0
3
1
30
9
0
0
17
30
0
3
What is different about
deletion than insertion?
58
Deletion (Hard Case)
4
10
Delete(9)
2
3
5
17
1
0
2
2
12
9
0
2
0
3
20
1 0
1
11 15 18 30
0
13
0
33
59
Double Rotation on Deletion
4
10
10
2
3
5
2
0
0
2
1
0
2
12
5
20
1 0
1
11 15 18 30
0
33
2
0
11 15 18 30
13
17
0
20
1 0
3
3
2
12
2
3
1
17
1
0
Not
finished!
4
0
0
33
13
60
Deletion with Propagation
4
10
1
3
17
0
0
2
What different
about this case?
3
2
2
12
5
0
20
1 0
1
We get to choose whether
to single or double rotate!
11 15 18 30
0
13
0
33
61
Propagated Single Rotation
4
4
10
17
1
3
17
0
0
2
3
3
2
10
0
20
1 0
2
1
0
0
18
0 0
1
30
1
0
2 5 11 15
0
33
0
12
3
11 15 18 30
13
20
1
2
12
5
2
33
0
13
62
Propagated Double Rotation
4
4
10
12
1
3
17
0
0
2
2
3
2
10
1
2
12
5
0
20
1 0
1
0
0
17
0
1
0
2 5
2
15
11
3
11 15 18 30
13
3
0
13
20
0
1
18 30
0
0
33
33
63
AVL Deletion Algorithm
• Recursive
• Iterative
1. If at node, delete it
2. Otherwise recurse to
find it in
3. Correct heights
a. If imbalance #1,
single rotate
b. If imbalance #2
(or don’t care),
double rotate
1. Search downward for
node, stacking
parent nodes
2. Delete node
3. Unwind stack,
correcting heights
a. If imbalance #1,
single rotate
b. If imbalance #2
(or don’t care)
double rotate
64
AVL
•
•
•
•
•
Automatically Virtually Leveled
Architecture for inVisible Leveling
Articulating Various Lines
Amortizing? Very Lousy!
Amazingly Vexing Letters
65
AVL
•
•
•
•
•
Automatically Virtually Leveled
Architecture for inVisible Leveling
Articulating Various Lines
Amortizing? Very Lousy!
Amazingly Vexing Letters
Adelson-Velskii Landis
66
Pros and Cons of AVL Trees
Pro:
• All operations guaranteed O(log N)
• The height balancing adds no more than a
constant factor to the speed of insertion
Con:
• Space consumed by height field in each node
• Slower than ordinary BST on random data
Can we guarantee O(log N) performance with less
overhead?
67
Splay
CSE 326: Data Structures
Part 3: Trees, continued
Trees
68
Today: Splay Trees
• Fast both in worst-case amortized analysis
and in practice
• Are used in the kernel of NT for keep track of
process information!
• Invented by Sleator and Tarjan (1985)
• Details:
• Weiss 4.5 (basic splay trees)
• 11.5 (amortized analysis)
• 12.1 (better “top down” implementation)
69
Basic Idea
“Blind” rebalancing – no height info kept!
• Worst-case time per operation is O(n)
• Worst-case amortized time is O(log n)
• Insert/find always rotates node to the root!
• Good locality:
– Most commonly accessed keys move high in
tree – become easier and easier to find
70
Idea
10
You’re forced to make
a really deep access:
17
move n to root by
series of zig-zag
and zig-zig
rotations, followed
by a final single
rotation (zig) if
necessary
Since you’re down there anyway,
fix up a lot of deep nodes!
5
2
9
3
71
Helped
Zig-Zag*
Unchanged
Hurt
g
n
p
g
X
up 2
p
down 1
down 1
up 1
n
W
Y
Z
X
*This
Y
Z
W
is just a double rotation
72
Zig-Zig
n
g
p
p
W
Z
n
g
X
Y
Y
Z
W
X
73
Why Splaying Helps
• Node n and its children are always helped (raised)
• Except for last step, nodes that are hurt by a zigzag or zig-zig are later helped by a rotation higher
up the tree!
• Result:
– shallow nodes may increase depth by one or two
– helped nodes decrease depth by a large amount
• If a node n on the access path is at depth d before
the splay, it’s at about depth d/2 after the splay
– Exceptions are the root, the child of the root, and the
node splayed
74
Splaying Example
1
1
2
2
zig-zig
3
3
Find(6)
4
6
5
5
6
4
75
Still Splaying 6
1
1
2
6
zig-zig
3
3
6
5
4
2
5
4
76
Almost There, Stay on Target
1
6
6
1
zig
3
2
3
5
4
2
5
4
77
Splay Again
6
6
1
1
zig-zag
3
4
Find(4)
2
5
4
3
5
2
78
Example Splayed Out
6
4
1
1
6
zig-zag
3
4
3
5
5
2
2
79
Locality
• “Locality” – if an item is accessed, it is likely to
be accessed again soon
– Why?
• Assume m n access in a tree of size n
– Total worst case time is O(m log n)
– O(log n) per access amortized time
• Suppose only k distinct items are accessed in the
m accesses.
– Time is O(n log n + m log k )
getting those k items
near root
those k items are all at
the top of the tree
– Compare with O( m log n ) for AVL tree
80
Splay Operations: Insert
• To insert, could do an ordinary BST insert
– but would not fix up tree
– A BST insert followed by a find (splay)?
• Better idea: do the splay before the insert!
• How?
81
Split
Split(T, x) creates two BST’s L and R:
–
–
–
–
All elements of T are in either L or R
All elements in L are x
All elements in R are x
L and R share no elements
Then how do we do the insert?
82
Split
Split(T, x) creates two BST’s L and R:
–
–
–
–
All elements of T are in either L or R
All elements in L are x
All elements in R are > x
L and R share no elements
Then how do we do the insert?
Insert as root, with children L and R
83
Splitting in Splay Trees
• How can we split?
– We have the splay operation
– We can find x or the parent of where x would
be if we were to insert it as an ordinary BST
– We can splay x or the parent to the root
– Then break one of the links from the root to a
child
84
Split
could be x, or
what would
have been the
parent of x
split(x)
splay
if root is > x
T
L
R
if root is x
OR
L
x
R
>x
L
<x
R
85
>x
Back to Insert
x
split(x)
L
x
R
>x
L
R
Insert(x):
Split on x
Join subtrees using x as root
86
Insert Example
Insert(5)
6
4
1
9
4
2
7
split(5)
1
4
6
1
9
2
6
9
2
7
7
5
4
6
1
9
2
787
Splay Operations: Delete
x
find(x)
delete x
L
R
L
<x
R
>x
Now what?
88
Join
• Join(L, R): given two trees such that L < R,
merge them
splay
L
R
L
R
• Splay on the maximum element in L then
attach R
89
Delete Completed
x
find(x)
T
delete x
L
R
L
<x
R
>x
Join(L,R)
T-x
90
Delete Example
Delete(4)
6
4
1
9
4
find(4)
6
1
7
6
1
9
2
2
2
1
7
Find max
7
2
9
2
6
1
6
9
7
9
7
91
Splay Trees, Summary
• Splay trees are arguably the most practical
kind of self-balancing trees
• If number of finds is much larger than n,
then locality is crucial!
– Example: word-counting
• Also supports efficient Split and Join
operations – useful for other tasks
– E.g., range queries
92