0% found this document useful (0 votes)
32 views

Class 12

The document discusses different ways of representing trees in memory and traversing trees. It describes using arrays and linked lists to represent trees, with each node having references to its parent, left child, and right child. Preorder, inorder, and postorder traversals of binary trees are covered along with extending these to general trees. Loading a tree from a file into memory is also discussed.

Uploaded by

Kala Dharan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views

Class 12

The document discusses different ways of representing trees in memory and traversing trees. It describes using arrays and linked lists to represent trees, with each node having references to its parent, left child, and right child. Preorder, inorder, and postorder traversals of binary trees are covered along with extending these to general trees. Loading a tree from a file into memory is also discussed.

Uploaded by

Kala Dharan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 47

Tree representation and tree

search
- Ed. 2. and 3.: Chapter 6
- Ed. 4.: Chapter 10

Data Structures for Representing


Trees
Recall that we can use arrays or linked
lists to implement sequences.

How can a tree be represented in a


program?

b
2

Since a binary tree is an ordered tree and has levels, it is


convenient to assign a number to each node.
1
2

4
8

5
9

10

6
11

12

7
13

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

14

15

Formally, for every node v of a tree T, let p(v) be the integer


defined as follows.
If v is the root of T, then p(v) = 1.
If v is the left child of the node u, then p(v) = 2p(u)
If v is the right child of the node u, then p(v) = 2p(u) + 1.
2 u p(u)=2
2p(u)=4

2p(u)+1=5

4
8

p(u)=4

5
9

10

4
2p(u)+1=9

2p(u)=8 8

11

The function p() is called a level numbering of the nodes in a


binary tree T.

In general, the numbers for nodes may not be consecutive


when the number of nodes at some level does not reach its
maximum.
1
2

5
10

7
11

14

15

With a level numbering of the nodes, it is convenient to use a


vector S to represent a tree.
Recall that we use ranks to access elements in a vector. So we
can place the node v in a tree T at rank p(v).
1
2

5
10

2 3

7
11

4 5

14

10 11

15

14 15

We can also use a linked structure to represent a tree. In this


case, the node v of a tree T is represented by an object with
four references.
parent

left

right
element

providence

root
Chicago

5
size

Baltimore

Baltimore

Chicago

New York

Providence

Seattle

Seattle

New York

Class BTNode
public class BTNode implements Position {
private Object element;
private BTNode left, right, parent;
public BTNode() {}
public BTNode( Object o, BTNode u, BTNode v, BTNode w ) {
setElement( o );
setParent( u );
setLeft( v ):
setRight( w );
}
public Object element() { return element; }
public void setElement( Object o ) { element = o; }
public BTNode getLeft() { return left; }
public void setLeft( BTNode v ) { left = v; }
public BTNode getRight() { return right; }
public void setRight( BTNode v ) { right = v; }
public BTNode getParent() { return parent; }
public void setParent( BTNode v ) { parent = v; }
}

Interface Hierarchy for Positions


Position
element();
DNode
element(){};
getNext(){};
getPrev(){};
setNext(){};
setPrev(){};
setElement(){};

BTNnode
element(){};
getLeft(){};
getRight(){};
setLeft(){};
setRight(){};
getParent(){};
setElement(){};

Class LinkedBinaryTree
Additional methods are supported.
expandExternal(v): Transform the external node v into an internal node
by creating two new external nodes and making them
the left and right children of v, respectively; an error
condition occurs if v is an internal node.
Input: Position; Output: None

v
v

removeAboveExternal(w): Remove the external node w together with its


parent v, replacing v with the sibling of w; this
operation generates an error condition if w is an
internal node or w is the root.
Input: Position; Output: None

v
z

z
w

public class LinkedBinaryTree implements BinaryTree {


private Position root;
private int size;
public LinkedBinaryTree() {
root = new BTNode(null, null, null, null);
size = 1;
}
public int size() { return size; }
public boolean isEmpty() { return ( size == 0 ); }
public boolean isInternal( Position v ) {
return ((( BTNode )v ).getLeft() != null &&
(( BTNode )v ).getRight() != null );
}
public boolean isExternal( Position v ) {
return ((( BTNode )v ).getLeft() == null &&
(( BTNode )v ).getRight() == null );
}
public boolean isRoot( Position v ) {
return ( v == root());
}

public Position leftChild( Position v ) {


return (( BTNode )v ).getLeft();
}
public Position rightChild( Position v ) {
return (( BTNode )v ).getRight();
}
public Position sibling( Position v ) {
Position p = parent( v );
Position lc = leftChild( p );
if( v == lc )
return rightChild( p );
else
return lc;
}

p=paren(v)
lc=leftChild(p)
v

rightChild(p)

public Position parent( Position v ) {


return (( BTNode )v ).getParent();
}
public Object replaceElement( Position v, Object o ) {
Object temp = (( BTNode )v ).element();
(( BTNode )v ).setElement( o );
return temp;
}
public void swapElements( Position v, Position w ) {
Object temp = w.element();
(( BTNode )w ).setElement( v.element());
(( BTNode )v ).setElement( temp );
}

public void expandExternal( Position v ) {


if( isExternal( v )) {
(( BTNode )v ).setLeft( new BTNode( null,
( BTNode )v, null, null ));
(( BTNode )v ).setRight( new BTNode( null,
( BTNode )v, null, null ));
size += 2;
}
}

v
v

public void removeAboveExternal( Position v ) {


if( isExternal( v )) {
BTNode p = ( BTNode )parent( v );
BTNode s = ( BTNode )sibling( v );
if( isRoot( p )) {
s.setParent( null );
root = s;
} else {
BTNode g = ( BTNode )parent( p );
if( p == leftChild( g ))
g.setLeft( s );
else
g.setRight( s );
s.setParent( g );
}
size -= 2;
}
public Iterator elements() { }
}

p
s

s
v

public class ArrayPositionIterator implements Iterator {


protected Position a[]; // the underlying array
protected Position cur;
int i = 0;
// the current (next) position
public ArrayPositionIterator() { } // default constructor
public ArrayPositionIterator(Position[] L) {
// preferred constructor
a = L;
if (a[0] == null) cur = null; // array is empty
else cur = a[i];
// start with the first position
}
public boolean hasNext() { return (cur != null); }
public Position next() throws NoSuchElementException {
if (!hasNext())
throw new NoSuchElementException("No next position");
Position toReturn = cur;
if (cur == a[i+1]) cur = null;
// no positions left
else cur = a[i+1];
i++; // move cursor to the next position
return toReturn;
}
}

protected void inorderPosition (Position v, Positions[] pos, int i)


throws InvalidPositionException {
if (hasLeft(v))
inorderPosition(left(v), pos, i); // recurse on left child
pos[i] := v; i := i + 1;
//if (((BTPosition)v).element() instanceof Integer)
// System.out.print(((Integer)((BTPosition)v).element()).intValue() + " ");
//else System.out.print(((Character)((BTPosition)v).element()).charValue() + " ");
if (hasRight(v))
inorderPosition(right(v), pos, i); // recurse on right child
}

IspectableContainer
size
isElement
Elements
IspectablePositionContainer
positions

PositionContainer
swapElement
replaceElement

Tree

InspectableTree
root, parent, children, isRoot
isInternal, isExternal
InspectableBinaryTree
leftChild, rightChild, sibling
BinaryTree
imple.
LinkedBinaryTree
, replaceElement, swapElement, expandExternal,
removeAboveExternal

A Linked Structure for General


Trees
We can extend the linked structure for
binary tree to represent general trees.

parent
element
childrenContainer

An object of node has three references:


Parent, childrenContainer and element.

Example:

New York

Baltimore

Chicago

Providence

Seattle

Data Structure Exercises 12.1

Preorder Traversal
r

Recall that we can visit the


nodes in a binary tree with
inorder traversal.
What if the tree is not a
binary tree?

u
v

Are there any other ways


to visit the nodes
systematically?

Assume we have a tree T (not necessarily a binary tree).


preorder traversal of T: The root of T is visited first and then
the subtrees rooted at its children are traversed recursively. If
the tree is ordered, then the subtrees are traversed according to
the order of the children.
The action of visiting a node:
When we visit each node of T, what do we do?
We can do anything that makes sense such as incrementing a
counter or some complex computation based on the element at
each node.

Example: Preorder traversal of a book structure


Paper

Title Abstract
1.1

Ch. 1
1.2

Ch. 2
2.1

2.2

Ch. 3
2.3

3.1

3.2

References

Algorithm preorder(T,v):
perform the visit action for node v
for each child w of v
call preorder(T,w)
v
postorder(T,w)

postorder(T,v)

A Java implementation of preorder traversal for printing the elements.


In this case, the action of visiting a node is printing the element.
public static String preorderPrint( InspectableTree T, Position v ) {
String s = v.element().toString();
PositionIterator children = T.children( v );
while( children.hasNext())
s += " " + preorderPrint( T, children.nextPosition());
return s;
}

Example:
What is the string that preorderPrint(T,v) returns?
Sales
Domestic
Canada

International
S. America

Overseas

Preorder Traversal of a Binary


Tree
Since a binary tree is just a special case of trees, the algorithm
for preorder traversal of a binary tree is very similar.
Algorithm binaryPreorder(T,v):
perform the visit action for node v
if v is an internal node
call binaryPreorder(T, T.leftChild( v ))
call binaryPreorder(T, T.rightChild( v ))

Preorder Traversal Using Stack


S.push(root);
preorder
While (S is not empty) do
{
x := S.pop( );
access x;
let x1, , xk be the children of x;
for i = k to 1 do
{S.push(xi);}
}

traversal

breadth-first traversal

Q.enqueue(root);
While (Q is not empty) do
{
x := Q.dequeue( );
access x;
let x1, , xk be the children of x;
for i = 1 to k do
{Q.enqueue(xi);}

Load a tree from disk into main


memory
File:
a
b
e

c
f

a; b, c, d.
b; e, f.
e;
f;
c; g.
g;
d;

a
b

a
d

b
e

public class Node1


{ String x;
Node2 y;
}
public class Node2
{ Node1 x;
Node2 y;
}

f
c
g
d

Access 0th in the file to find the root of the tree;


S.push(root, null);
while (S is not empty) do
{ x := S.pop( );
generate a node n for x.node_info;
if x.point_to_parent is not null
then generate links between n and x.pointer_to_parent;
Access the corresponding line in the file
to find the children of x;
let x1, , xk be the children of x;
a; b, c, d.
for j = k to 1 do
b; e, f.
S.push(xj, n);
e;
}

stack S:

node_info Pointer_to_parent

f;
c; g.
g;
d;

(*Assume that the nodes are stored in preorder in the


file.*)
i := 0;
Access 0th line in the file to find the root of the tree;
S.push(root, null);
while (S is not empty) do
{ x := S.pop( );
generate a node n for x.node_id;
if x.point_to_parent is not null
then generate links between n and x.pointer_to_parent;
Access the ith line in the file to find the children
of x;
let x1, , xk be the children of x;
for j = k to 1 do
S.push(xj, n);
i := i + 1;
}

XML File
<book>
<title>
The Art of Programming
</title>
<author>
D. Knuth
</author>
<year>
1969
</year>
</book>

<book>
<title>

<author>

The Art of D. Knuth


Programming

<year>
1969

XML File
Read a file into a character array A:
< b o o k > < t i t l e > T h e

stack S:

node_value Pointer_to_node

A r t

XML File
Algorithm:
Scan array A;
If A[i] is < and A[i+1] is a character then {
generate a node x for A[i.e.],
where A[j] is > directly after A[i];
let y = S.top().pointer_to_node;
make x be a child of y; S.push(A[i..j], x);
If A[i] is , then {
genearte a node x for A[i.e.],
where A[j] is directly after A[i];
let y = S.top().pointer_to_node;
make x be a child of y;
If A[i] is < and A[i+1] is /, then S.pop();

You might also like