Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Definition of a tree
A tree is like a binary tree, except that a node may have any
number of children
Depending on the needs of the program, the children may or may not be
ordered
Like a binary tree, a tree has a
root, internal nodes, and leaves
A Each node contains an element
and has branches leading to other
B C D E nodes (its children)
Each node (other than the root)
F G H I J K has a parent
Each node has a depth (distance
L M N from the root)
2
More definitions
An empty tree has no nodes
The descendents of a node are its children and the descendents
of its children
The ancestors of a node are its parent (if any) and the
ancestors of its parent
The subtree rooted at a node consists of the given node and all
its descendents
An ordered tree is one in which the order of the children is
important; an unordered tree is one in which the children of a
node can be thought of as a set
The branching factor of a node is the number of children it has
The branching factor of a tree is the average branching factor
of its nodes
3
Data structure for a tree
A node in a binary tree can be represented as follows:
class BinaryTreeNode {
Object value;
BinaryTreeNode leftChild, rightChild;
}
4
ADT for a tree
It must be possible to:
Construct a new tree
If a tree can be empty, this may require a header node
Add a child to a node
Get (iterate through) the children of a node
Access (get and set) the value in a node
It should probably be possible to:
Remove a child (and the subtree rooted at that child)
Get the parent of a node
5
Traversing a tree
You can traverse a tree in preorder:
void preorderPrint(node) {
System.out.println(node);
Iterator iter = node.children.iterator();
while (iter.hasNext()) {
preorderPrint(iter.next());
}
}
You can traverse a tree in postorder:
void postorderPrint(node) {
Iterator iter = node.children.iterator();
while (iter.hasNext()) {
postorderPrint(iter.next());
}
System.out.println(node);
}
You can’t usually traverse a tree in inorder
Why not?
6
Other tree manipulations
There’s really nothing new to talk about; you’ve
seen it all with binary trees
8
Family trees
It turns out that a tree is not a good way to
represent a family tree
Every child has two parents, a mother and a father
Parents frequently remarry
An “upside down” binary tree almost works
Since it is a biological fact (so far) that every child has
exactly two parents, we can use left child = father and
right child = mother
The terminology gets a bit confusing
If you could go back far enough, it becomes a
mathematical certainty that the mother and father have
some ancestors in common
9
Part of a genealogy
Isaac
Steven Danielle
Paul
David Winfred Carol
a
10
Game trees
Trees are used heavily in implementing games, particularly
board games
A node represents a position on the board
The children of a node represent all the possible moves from
that position
More precisely, the branches from a node represent the possible moves;
the children represent the new positions
Planning ahead (in a game) means choosing a path through the
tree
However—
You can’t have a cycle in a tree
If you can return to a previous position in a game, you have a cycle
Graphs can have cycles
11
Binary trees for expressions
Ordered trees can be used to represent arithmetic expressions
+ + *
2 2 2 * + 4
The expression 2+2
3 4 2 3
The expression 2+3*4 The expression (2+3)*4
12
(General) trees for expressions
You can use binary trees for expressions if you have only unary
and binary operators
Java has a ternary operator
?: if
> x y > = =
x y x y max x max y
The expression x > y ? x : y The statement if (x > y) max = x;
else max = y;
13
More trees for statements
while (n >= 1) { for (int i = 0; i < n; i++)
exp = x * exp; a[i] = 0;
n--;
}
for
while
= < ++ =
>= ;
n 1 = -- int 0 i n i [] 0
exp * n i a i
x exp
14
Writing compilers and interpreters
A compiler does three things:
Parses the input program (converts it into an abstract syntax tree)
(Optionally) optimizes the abstract syntax tree
Traverses the tree and outputs assembly language or machine code
to do the same operations
An interpreter does three things:
Parses the input program (converts it into an abstract syntax tree)
(Optionally) optimizes the abstract syntax tree
Traverses the tree in an order controlled by the node contents, and
performs the operations as it goes
Parsing is usually the hard part, but there is a very simple
technique (called recursive descent parsing) that can be
used if the language is carefully designed and you don’t
care too much about efficiency or good error messages
15
I’ll never need to write a compiler...
Are you sure?
If you can’t parse text inputs, you are limited to reading simple
things like numbers and Strings
If you can parse text input, you can make sense of:
tell Mary "Meet me at noon"
fire phasers at 3, 7
17.25, 0.203 + 8.97i, 0.95i
28°12"48'
3:30pm-5pm
Parsing is less important in these days of GUIs, but it’s still pretty
important
Java provides basic support for parsing with its StringTokenizer and
StreamTokenizer classes
16
The End
17