Trees 1: Theory, Models, Generic Heap Algorithms, Priority Queues Andy Wang

advertisement
Trees 1: Theory, Models,
Generic Heap Algorithms,
Priority Queues
Andy Wang
Data Structures, Algorithms,
and Generic Programming
Trees 1: Overview
General trees—theory and terminology
Tree traversals
Binary trees
Vector implementation of binary trees
Partially ordered trees (POT)
Heap algorithms
Heapsort
Priority queue
Theory and Terminology
Definition: A tree is a connected
graph with no cycles
Consequences:
Between any two vertices, there is
exactly one unique path
8
3
4
1
9
10
7
2
5
6
A Tree?
11
12
A Tree? Nope
5
9
10
6
7
8
2
3
4
1
11
12
A Tree?
5
9
10
6
7
8
2
3
4
1
11
12
A Tree? Yup
5
9
10
6
7
8
2
3
4
1
11
12
Theory and Terminology
Definition: A rooted tree is a graph G
such that:
G is connected
G has no cycles
G has exactly one vertex called the root
of the tree
Theory and Terminology
Consequences
The depth of a vertex v is the length of
the unique path from root to v
G can be arranged so that the root is at
the top, its neighboring vertices are
vertices of depth 1, and so on…
The set of all vertices of depth k is called
level k of the tree
A Rooted Tree
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Definition: A descending path in a
rooted tree is a path, whose edges go
from a vertex to a deeper vertex
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Consequences:
A unique path from the root to any vertex
is a descending path
The length of this path is the depth of the
vertex
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Definition: If there is a descending
path from v1 to v2, v1 is an ancestor
of v2, and v2 is a descendant of v1.
Theory and Terminology
Suppose v is a vertex of depth k:
Any vertex that is adjacent to v must
have depth k - 1 or k + 1.
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Suppose v is a vertex of depth k:
Vertices adjacent to v of depth k + 1 are
called children of v.
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Suppose v is a vertex of depth k:
If k > 0, there is exactly one vertex of
depth k – 1 that is adjacent to v in the
graph. This vertex is called the parent of
v. depth = 0
root 1
depth = 1
depth = 2
depth = 3
5
2
3
4
6
7
8
9
10
11
12
Theory and Terminology
Definitions
A vertex with no children is called a leaf
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Theory and Terminology
Definitions
The height of a tree is the maximum
depth of its vertices
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
height
depth = 2
depth = 3
5
11
12
Theory and Terminology
Definitions
The root is the only vertex of depth 0.
The root has no parent.
depth = 0
root
1
depth = 1
2
3
4
6
7
8
9
10
depth = 2
depth = 3
5
11
12
Tree Traversals
Definition: A traversal is the process
for “visiting” all of the vertices in a tree
Often defined recursively
Each kind corresponds to an iterator
type
Iterators are implemented nonrecursively
Preorder Traversal
Visit vertex, then visit child vertices
(recursive definition)
Depth-first search
Begin at root
Visit vertex on arrival
Implementation may be recursive,
stack-based, or nested loop
Preorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Preorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Postorder Traversal
Visit child vertices, then visit vertex
(recursive definition)
Depth-first search
Begin at root
Visit vertex on departure
Implementation may be recursive,
stack-based, or nested loop
Postorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Postorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Postorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Postorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Levelorder Traversal
Visit all vertices in level, starting with
level 0 and increasing
Breadth-first search
Begin at root
Visit vertex on departure
Only practical implementation is
queue-based
Levelorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Levelorder Traversal
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
5
5
root
1
2
3
4
6
7
8
root
1
2
3
4
6
7
8
Tree Traversals
Preoder: depth-first search (possibly
stack-based), visit on arrival
Postorder: depth-first search
(possibly stack-based), visit on
departure
Levelorder: breadth-first search
(queue-based), visit on departure
Binary Trees
Definition: A binary tree is a rooted
tree in which no vertex has more than
two children
root
4
1
2
3
5
6
7
Binary Trees
Definition: A binary tree is complete
iff every layer but the bottom is fully
populated with vertices.
root
4
1
2
3
5
6
7
Binary Trees
A complete binary tree with n vertices
and high H satisfies:
2H <= n < 2H + 1
22 <= 7 < 22 + 1
root
4
1
2
3
5
6
7
Binary Trees
A complete binary tree with n vertices
and high H satisfies:
2H <= n < 2H + 1
H <= lg n < H + 1
H = floor(lg n)
Binary Trees
Theorem: In a complete binary tree
with n vertices and height H
2H <= n < 2H + 1
Binary Trees
Proof:
For level k, there are 2k vertices
Total number of vertices:
n = 20 + 21 + …2k
n = 1 + 21 + 22 +…2k
n = 1 + 2(1 + 21 +…2k-1)
n = 1 + 2(n - 2k)
n = 1 + 2n – 2k + 1
n = 2k + 1 - 1
Binary Trees
Let k = H
number of vertices for height H = 2H + 1 – 1
number of vertices for height H < 2H + 1
Let k = H – 1
number of vertices for height H - 1 = 2H – 1
number of vertices for height H >= 2H
2H <= n < 2H + 1
Binary Tree Traversals
Inorder traversal
Definition: left child, visit, right child
(recursive)
Algorithm: depth-first search (visit
between children)
Inorder Traversal
root
4
root
2
3
5
6
root
4
1
7
4
1
2
3
5
6
root
2
3
5
6
7
4
1
7
1
2
3
5
6
7
Inorder Traversal
root
4
root
2
3
5
6
root
4
1
7
4
1
2
3
5
6
root
2
3
5
6
7
4
1
7
1
2
3
5
6
7
Inorder Traversal
root
4
root
2
3
5
6
root
4
1
7
4
1
2
3
5
6
root
2
3
5
6
7
4
1
7
1
2
3
5
6
7
Inorder Traversal
root
4
1
root
2
3
5
6
7
4
1
2
3
5
6
7
Binary Tree Traversals
Other traversal apply to binary case:
Preorder traversal
vertex, left subtree, right subtree
Inorder traversal
left subtree, vertex, right subtree
Postorder traversal
left subtree, right subtree, vertex
Levelorder traversal
vertex, left children, right children
Vector Representation of Complete
Binary Tree
Tree data
Vector elements carry data
Tree structure
Vector indices carry tree structure
Index order = levelorder
Tree structure is implicit
Uses integer arithmetic for tree
navigation
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
root
ll
0
l
r
lr
rl
rr
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
0
1
2
3
4
5
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
0
l
2
3
4
5
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
2
0
l
r
3
4
5
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
2
3
0
l
r
ll
4
5
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
2
3
4
0
l
r
ll
lr
5
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
2
3
4
5
0
l
r
ll
lr
rl
6
Vector Representation of Complete
Binary Tree
Tree navigation
Parent of v[k] = v[(k – 1)/2]
Left child of v[k] = v[2*k + 1]
Right child of v[k] = v[2*k + 2]
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
Partially Ordered Trees
Definition: A partially ordered tree is a
tree T such that:
There is an order relation >= defined for
the vertices of T
For any vertex p and any child c of p, p
>= c
Partially Ordered Trees
Consequences:
The largest element in a partially
ordered tree (POT) is the root
No conclusion can be drawn about the
order of children
Heaps
Definition: A heap is a partially
ordered complete (almost) binary
tree. The tree is completely filled on
all levels except possibly the lowest.
root
3
1
0
4
2
Heaps
Consequences:
The largest element in a heap is the root
A heap can be stored using the vector
implementation of binary tree
Heap algorithms:
Push Heap
Pop Heap
The Push Heap Algorithm
Add new data at next leaf
Repair upward
Repeat
Locate parent
if POT not satisfied
swap
else
stop
Until POT
The Push Heap Algorithm
Add new data at next leaf
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
5
4
3
The Push Heap Algorithm
Add new data at next leaf
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
5
4
3
8
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
5
4
3
8
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
5
4
3
8
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
8
4
3
5
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
8
4
3
5
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
8
4
3
5
The Push Heap Algorithm
Repeat
Locate parent of v[k] = v[(k – 1)/2]
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
8
6
7
4
3
5
The Pop Heap Algorithm
Copy last leaf to root
Remove last leaf
Repeat
find the larger child
if POT not satisfied
swap
else
stop
Until POT
The Pop Heap Algorithm
Copy last leaf to root
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
8
6
7
4
3
5
The Pop Heap Algorithm
Copy last leaf to root
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
5
6
7
4
3
5
The Pop Heap Algorithm
Remove last leaf
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
5
6
7
4
3
The Pop Heap Algorithm
Repeat
find the larger child
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
5
6
7
4
3
The Pop Heap Algorithm
Repeat
find the larger child
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
5
6
7
4
3
The Pop Heap Algorithm
Repeat
find the larger child
if POT not satisfied
swap
else
stop
0
1
2
3
4
5
6
0
l
r
ll
lr
rl
rr
7
6
5
4
3
Generic Heap Algorithms
Apply to ranges
Specified by random access iterators
Current support
Arrays
TVector<T>
TDeque<T>
Source code file: gheap.h
Test code file: fgss.cpp
Priority Queues
Element type with priority
typename T t
Predicate class P p
Associative queue operations
void Push(t)
void Pop()
T& Front()
Priority Queues
Associative property
Priority value determined by p
Push(t) inserts t, increases size by 1
Pop() removes element with highest
priority value, decreases size by 1
Front() returns element with highest
priority value, no state change
The Priority Queue Generic Adaptor
template <typename T, class C, class P>
class CPriorityQueue {
C c;
P LessThan;
public:
typedef typename C::value_type value_type;
int Empty() const { return c.Empty(); }
unsigned int Size() const { return c.Size(); }
void Clear() { c.Clear(); }
CPriorityQueue& operator=(const CPriorityQueue& q) {
if (this != &q) {
c = q.c;
LessThan = q.LessThan;
}
return *this;
}
The Priority Queue Generic Adaptor
void Display(ostream& os, char ofc = ‘\0’) const {
c.Display(os, ofc);
}
void Push(const value_type& t) {
c.PushBack(t);
g_push_heap(c.Begin(), c.End(), LessThan);
}
void Pop() {
if (Empty()) {
cerr << “error” << endl;
exit(EXIT_FALIURE);
}
g_pop_heap(c.Begin(), c.End(), LessThan);
c.PopBack();
}
};
Download