Download Trees - Applied Computer Science

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Quadtree wikipedia , lookup

B-tree wikipedia , lookup

Lattice model (finance) wikipedia , lookup

Red–black tree wikipedia , lookup

Interval tree wikipedia , lookup

Binary tree wikipedia , lookup

Binary search tree wikipedia , lookup

Transcript
17-03-09
Trees
• 
Tree structures are a breakthrough in data organization,
for they allow us to implement a host of algorithms much
faster than when using linear data structures, such as
arrays or linked lists. • 
Trees also provide a natural organization for data, and
consequently have become ubiquitous structures in file
systems, graphical user interfaces, databases, websites,
and many other computer systems. Trees
ACS-2947 Week 8
What is a Tree?
• 
• 
• 
Formal Definition of a Tree
In computer science, a
tree is an abstract model
of a hierarchical structure A tree consists of nodes
with a parent-child
Sales
relation Applications:
• 
Organization charts
• 
File systems • 
Programming
environments US
Europe
• 
Computers”R”Us
Manufacturing
InternaAonal
Laptops
Asia
R&D
Desktops
Canada
Node Relationships
• 
• 
• 
A node v is internal if it
has one or more
children.
If T is nonempty, it has a special node, called the root of T ,
that has no parent. • 
Each node v of T different from the root has a unique parent
node w; every node with parent w is a child of w. • 
Note that a tree can be empty, meaning that it does not
have any nodes. • 
This convention also allows us to define a tree recursively
such that a tree T is either empty or consists of a node r,
called the root of T, and a (possibly empty) set of subtrees
whose roots are the children of r. • 
A
• 
A node v is external if v
has no children
also known as leaves. • 
Node Relationships
Two nodes that are
children of the same
parent are siblings • 
Formally, we define a tree T as a set of nodes storing
elements such that the nodes have a parent-child
relationship that satisfies the following properties: B
E
C
F
G
D
H
• 
I
J
K
A node u is an ancestor of
a node v if u = v or u is an
ancestor of the parent of v. Conversely, we say that a
node v is a descendant of
a node u if u is an ancestor
of v. The subtree of T rooted at
a node v is the tree
consisting of all the
descendants of v in T
(including v itself). A
B
E
C
F
I
J
G
D
H
K
1
17-03-09
Tree terminology
• 
Edges and Paths in Trees
Root: node without a
parent
• 
Depth of a node: number
of ancestors • 
Height of a tree: maximum
depth of any node (3) • 
A
2
B
E
C
D
3
F
I
J
• 
G
H
K
An edge of tree T is a
pair of nodes (u,v) such
that u is the parent of v,
or vice versa. A path of T is a
sequence of nodes such
that any two consecutive
nodes in the sequence
form an edge. A
B
E
C
F
I
J
G
D
H
K
Ordered Trees
• 
A tree is ordered if there is a meaningful linear order
among the children of each node; • 
That is, we purposefully identify the children of a
node as being the first, second, third, and so on. • 
Such an order is usually visualized by arranging
siblings left to right, according to their order. 2
17-03-09
The Tree Abstract Data Type • 
As we did with positional lists in Section 7.3, we
define a tree ADT using the concept of a position
as an abstraction for a node of a tree. • 
An element is stored at each position, and positions
satisfy parent-child relationships that define the tree
structure. • 
The Tree Abstract Data Type
Position
• 
Accessor Methods
A position object for a tree supports the method:
• 
getElement(): Returns the element stored at this
position. The Tree Abstract Data Type
• 
• 
Query Methods
The Tree Interface
public interface Tree<E> extends Iterable{
Position<E> root( );
Position<E> parent(Position<E> p) throws IllegalArgumentException;
Iterable<Position<E>> children(Position<E> p) throws IllegalArgumentException;
int numChildren(Position<E> p) throws IllegalArgumentException;
• 
boolean isInternal(Position<E> p) throws IllegalArgumentException;
General Methods
boolean isExternal(Position<E> p) throws IllegalArgumentException;
boolean isRoot(Position<E> p) throws IllegalArgumentException;
int size( );
boolean isEmpty( );
Iterator<E> iterator();
Iterable<Position<E>> positions();
}
3
17-03-09
An AbstractTree Base Class
• 
While an interface is a type definition that includes
public declarations of various methods, an interface
cannot include definitions for any of those methods. • 
In contrast, an abstract class may define concrete
implementations for some of its methods, while leaving
other abstract methods without definition. • 
An abstract class is designed to serve as a base class,
through inheritance, for one or more concrete
implementations of an interface. • 
When some of the functionality of an interface is
implemented in an abstract class, less work remains to
complete a concrete implementation. • 
We will define an AbstractTree base class,
demonstrating how many tree-based algorithms
can be described independently of the low-level
representation of a tree data structure. • 
If a concrete implementation provides three
fundamental methods—root(), parent(p), and
children(p)— all other behaviors of the Tree
interface can be derived within the AbstractTree
base class. Tree Depth
Let p be a position within tree T.
• 
• 
We define the height of a tree to be equal to the
maximum of the depths of its positions (or zero, if
the tree is empty). • 
It is easy to see that the position with maximum
depth must be a leaf. The depth of p is the number of ancestors of p, other than p itself.
• 
Note that this definition implies that the depth of the root of T is 0. The depth of p can also be recursively defined as follows: • 
Tree Height
• 
• 
If p is the root, then the depth of p is 0
• 
Otherwise, the depth of p is one plus the depth of the parent of p
BINARY TREES
• 
A binary tree is an ordered tree with the following
properties: 1. 
Every node has at most two children.
2. 
Each child node is labeled as being either a left
child or a right child. 3. 
A left child precedes a right child in the order of
children of a node. 4
17-03-09
Binary Trees
• 
The subtree rooted at a left or right child of an
internal node v is called a left subtree or right
subtree, respectively, of v. • 
A binary tree is proper if each node has either zero
or two children. Some people also refer to such
trees as being full binary trees. • 
Thus, in a proper binary tree, every internal node
has exactly two children. • 
A binary tree that is not proper is improper. E.g.
• 
• 
An arithmetic expression can be represented by a
binary tree whose leaves are associated with variables
or constants, and whose internal nodes are associated
with one of the operators +, −, ∗, and /, as
demonstrated in Figure 8.6. Each node in such a tree
has a value associated with it. • 
If a node is leaf, then its value is that of its variable or
constant. • 
If a node is internal, then its value is defined by applying
its operation to the values of its children. A typical arithmetic expression tree is a proper binary
tree, since each operator +, −, ∗, and / takes exactly
two operands. A Recursive Binary Tree Definition
• 
Incidentally, we can also define a binary tree in a
recursive way. In that case, a binary tree is either: • 
An empty tree. • 
A nonempty tree having a root node r, which
stores an element, and two binary trees that are
respectively the left and right subtrees of r. We
note that one or both of those subtrees can be
empty by this definition. This tree represents the expression ((((3+1)∗3)/((9−5)+2))−((3∗(7−4))+6))
The value associated with the internal node labeled “/”
is 2. A Binary Tree ADT
• 
A binary tree is a specialization of a tree that
supports three additional accessor methods: 5
17-03-09
Our Binary Tree Interface
• 
Java interface corresponding to our Binary Tree ADT
• 
This interface extends the Tree to add the three new
behaviors. • 
Defining an Abstract Tree Base Class
Binary tree is expected to support all the functionality that
was defined for general trees (e.g., root, isExternal, parent),
and the new behaviors left, right, and sibling. public interface BinaryTree<E> extends Tree<E>{
Position<E> left(Position<E> p) throws IllegalArgumentException;
Position<E> right(Position<E> p) throws IllegalArgumentException;
Position<E> sibling(Position<E> p) throws IllegalArgumentException;
}
Implementing Trees
• 
The AbstractTree and AbstractBinaryTree classes
that we have defined thus far in this chapter are
both abstract base classes. • 
Although they provide a great deal of support,
neither of them can be directly instantiated. • 
We have not yet defined key implementation details
for how a tree will be represented internally, and
how we can effectively navigate between parents
and children. Linked Structure for Binary Trees
• 
A natural way to realize a binary tree T is to use a
linked structure
• 
with a node that maintains references to the
element stored at a position p and to the nodes
associated with the children and parent of p. 6
17-03-09
LinkedBinaryTree Update Methods
• 
The Tree and BinaryTree interfaces defines
methods for inspecting an existing tree, yet they do
not declare any update methods. • 
We now need to have ways for changing the
structure of content of a tree. 7
17-03-09
Performance of the Linked Binary Tree
8
17-03-09
Array-Based Implementation of a Binary Tree
• 
An alternative representation of a binary tree T is
based on a way of numbering the positions of T . For
every position p of T , let f (p) be the integer defined
as follows. • 
If p is the root of T, then f(p)=0
• 
If p is the left child of position q, then f(p) = 2f(q) + 1 • 
If p is the right child of position q, then f(p) = 2f(q) + 2
Level Numbering
• 
For example, in
Figure (b), there are
no nodes with level
numbering 13 or
14, because the
node with level
numbering 6 has
no children. • 
The numbering function f is known as a level
numbering of the positions in a binary tree T, for it
numbers the positions on each level of T in
increasing order from left to right. • 
Note well that the level numbering is based on
potential positions within a tree, not the actual
shape of a specific tree, so they are not necessarily
consecutive. Example of Array-Based Binary Tree
a)
b)
Analyzing an Array-Based Binary Tree
• 
One advantage is that a position p can be
represented by the single integer f(p), and that
position-based methods such as root, parent, left,
and right can be implemented using simple
arithmetic operations on the number f(p). • 
A drawback of an array representation is that many
update operations for trees cannot be efficiently
supported. • 
Array-Based Implementation of a Binary Tree
For example, removing a node and promoting its
child takes O(n) time because it is not just the child
that moves locations within the array, but all
descendants of that child. Linked Structure of General Trees
• 
When representing a binary tree with a linked
structure, each node maintains fields left and right
as references to individual children. • 
For a general tree, there is no limit on the number
of children that a node may have. • 
A natural way to realize a general tree T as a linked
structure is to have each node store a single
container of references to its children. 9
17-03-09
Linked Structure of General Trees
Performance of a Linked General Tree
• 
We let cp denote the number of children of a
position p, and dp its depth. The space usage is
O(n). The structure
of a node
A larger portion of the data structure
associated with a node and its children
Tree Traversal Algorithms
• 
The traversal of a tree T is a systematic way of
accessing, or “visiting,” all the positions of T . • 
The action associated with the “visit” of a position p
depends on the application of this traversal, and
could involve anything from incrementing a counter
to performing some complex computation for p. Preorder Traversal
• 
In a preorder traversal of a tree T , the root of T is
visited first and then the sub-trees rooted at its
children are traversed recursively. • 
If the tree is ordered, then the subtrees are
traversed according to the order of the children. Postorder Traversal
• 
The postorder traversal algorithm can be viewed as
the opposite of the preorder traversal
• 
it recursively traverses the subtrees rooted at the
children of the root first, and then visits the root
(hence, the name “postorder”)
10
17-03-09
Breadth-First Tree Traversal
• 
Another approach is to traverse a tree so that we
visit all the positions at depth d before we visit the
positions at depth d + 1. Such an algorithm is
known as a breadth-first traversal. Inorder traversal of a Binary Tree
• 
During an inorder traversal, we visit a position between the
recursive traversals of its left and right subtrees. • 
• 
The inorder traversal of a binary tree T can be informally viewed as
visiting the nodes of T “from left to right.” Indeed, for every position p, the inorder traversal visits p after all
the positions in the left subtree of p and before all the positions
in the right subtree of p. Implementing Tree Traversals in Java
• 
Recall: When first defining the tree ADT, we stated
that tree T must include the following supporting
methods:
• 
iterator(): Returns an iterator for all elements in the
tree. • 
positions(): Returns an iterable collection of all
positions of the tree. 11
17-03-09
Implementing Tree Traversals in Java • 
We did not make any assumption about the order
in which these iterations report their results. • 
In this section, we will demonstrate how any of the
tree traversal algorithms we have introduced can be
used to produce these iterations as concrete
implementations within the AbstractTree or
AbstractBinaryTree base classes. Implementing Tree Traversals In Java
• 
First, we note that an iteration of all elements of a
tree can easily be produced if we have an iteration
of all positions of that tree. Preorder Traversals
• 
To implement the positions() method, we have a
choice of tree traversal algorithms. • 
Given that there are advantages to each of those
traversal orders, we provide public implementations
of each strategy that can be called directly by a
user of our class. • 
• 
Our goal is to provide a public method preorder(),
as part of the AbstractTree class, which returns an
iterable container of the positions of the tree in
preorder. • 
For ease of implementation, we choose to produce
a snapshot iterator, returning a list of all positions. • 
The public preorder method below has the
responsibility of creating an empty list for the
snapshot buffer, and invoking the recursive method
at the root of the tree (assuming the tree is
nonempty). We rely on a java.util.ArrayList instance
as an Iterable instance for the snapshot buffer. We can then trivially adapt one of those as a default
order for the positions method of the AbstractTree
class. Preorder Traversals
• 
We begin by defining a private utility method,
preorderSubtree, which allows us to parameterize
the recursive process with a specific position of the
tree that serves as the root of a subtree to traverse. • 
(We also pass a list as a parameter that serves as a
buffer to which “visited” positions are added.) 12
17-03-09
Postorder Traversal
• 
We implement a postorder traversal using a similar
design as we used for a preorder traversal. • 
• 
Difference: “visited” position is not added to a
postorder snapshot until after all of its subtrees have
been traversed
Both the recursive utility and the top-level public method
are given
Breadth-First Traversal • 
The breadth-first traversal algorithm is not
recursive; it relies on a queue of positions to
manage the traversal process
• 
We will use the LinkedQueue class Inorder Traversal
• 
• 
The inorder traversal algorithm, because it explicitly
relies on the notion of a left and right child of a node,
only applies to binary trees. • 
We therefore include its definition within the body of the
AbstractBinaryTree class. • 
We use a similar design to our preorder and postorder
traversals, with a private recursive utility for traversing
subtrees. Because the iterator( ) method relies on positions(), it
will also use inorder when reporting the elements of a
binary tree. 13