View
12
Download
0
Category
Preview:
Citation preview
Datastructuren
DatastructurenData Structures
Fenia AivaloglouHendrik Jan Hoogeboom
Informatica – LIACSUniversiteit Leiden
najaar 2019
Datastructuren
Tree Traversal
Contents
2 Tree TraversalDefinitions and representationRecursionUsing a StackUsing Inorder ThreadsMorris TraversalLink Inversion
Datastructuren
Tree Traversal
Definitions and representation
Traversal
The process of visiting each node (precisely once) in a systematicway:
breadth-first
NLR preorder
LNR inorder
LRN postorder
recursion
(parent pointer)
iterative, with stack
threads
link inversion
Datastructuren
Tree Traversal
Recursion
recursion (binary trees)
recursivetraversal( node )
if (node != nil) then
// pre-visit(node)
traversal(node.left)
// in-visit(node)
traversal(node.right)
// post-visit(node)
fi
end // traversal
pre
in
post
Datastructuren
Tree Traversal
Recursion
Algoritmiek2
class knoop { // struct mag ook
public:
knoop ( ) { // constructor
info = 0;
links = NULL;
rechts = NULL;
}
// maar misschien private
int info;
knoop* links;
knoop* rechts;
}; // knoop
void preorde (knoop* root) {
if ( root != NULL ) {
cout << root->info << endl;
preorde (root->links);
preorde (root->rechts);
} // if
} // preorde
void symmetrisch (knoop* root) {
if ( root != NULL ) {
symmetrisch (root->links);
cout << root->info << endl;
symmetrisch (root->rechts);
} // if
} // symmetrisch
2ja, dat hebben we gezien
Datastructuren
Tree Traversal
Recursion
pre-traversal( node )
if (node != nil) then
pre-visit(node)
pre-traversal(node.left)
pre-traversal(node.right)
fi
end
b2
d3
a1
g6
i7
e5
j9
h8
k10
c4
f11
NLR = preordera b d c e g i h j k f
Datastructuren
Tree Traversal
Recursion
in-traversal( node )
if (node != nil) then
in-traversal(node.left)
in-visit(node)
in-traversal(node.right)
fi
end
b1
d2
a
3
g
4
i5
e
6
j
7
h8
k9
c
10
f11
LNR = inorderb d a g i e j h k c f
Datastructuren
Tree Traversal
Recursion
post-traversal( node )
if (node != nil) then
post-traversal(node.left)
post-traversal(node.right)
post-visit(node)
fi
end
b 2
d 1
a 11
g 4
i 3
e 8
j 5
h 7
k 6
c 10
f 9
LRN = postorderd b i g j k h e f c a
Datastructuren
Tree Traversal
Using a Stack
generic binary tree traversal
visit direction visit at next node
1 down-left 1(stay) 2 node has no left-child
2 down-right 1(stay) 3 node has no right-child
3 up 2 at left-child3 at right-child
1
current
1next
2
current
1next
3
next
3current
2
next
3current
problem: going up to parent
Datastructuren
Tree Traversal
Using a Stack
visit = 1; node = root
while (visit != 3 or not S.isEmpty() )
case visit of
1 : if (node.left != nil) then
S.push(node)
node = node.left
else
visit = 2
fi
2 : if (node.left != nil) then
S.push(node)
node = node.right
visit = 1
else
visit = 3
fi
3 : parent = S.pop()
if (parent.left != node) then
visit = 2
else
visit = 3
fi
node = parent
end//case
end//while
1node
1next
2node
1 next
3 next
3 node
2 next
3node
Datastructuren
Tree Traversal
Using a Stack
which nodes on stack
pre: right children
b2
d3
a
1
g
6
i7
e
5
j
9
h8
k10
c
4
f11
end
in: left parents
b1
d2
a
3
g
5
i4
e
6
j
7
h8
k9
c
10
f11
end
Datastructuren
Tree Traversal
Using a Stack
pre-orderiterative-preorder( root )
S : Stack
S.create()
S.push( root )
while ( not S.isEmpty() ) do
node = S.pop()
if (node != nil) then
visit( node )
S.push( node.right )
S.push( node.left )
fi
do
end // iterative-preorder
* currentX visitedX on stack
X
X X
X X
X X
X X
X X
X *current
Datastructuren
Tree Traversal
Using a Stack
pre-orderiterative-preorder( root )
S : Stack
S.create()
S.push( root )
while ( not S.isEmpty() ) do
node = S.pop()
if (node != nil) then
visit( node )
S.push( node.right )
S.push( node.left )
fi
do
end // iterative-preorder
pre-order (2)iterative-preorder( root )
S : Stack
S.create()
S.push( root )
while ( not S.isEmpty() ) do
node = S.pop()
while (node != nil) do
visit( node )
S.push( node.right )
node = node.left
od
do
end // iterative-preorder [bis]
Datastructuren
Tree Traversal
Using a Stack
in-orderiterative-inorder( root : Node)
S : Stack
S.create()
// move to first node (left-most)
walkLeft( root, S )
while ( not S.isEmpty() ) do
node = S.pop()
visit( node )
walkLeft( node.right, S )
do
end // iterative-inorder
walkLeft( node : Node, S : Stack)
while (node != nil) do
S.push( node )
node = node.left
od
end // walkLeft
X
X
X X
X X
X
X
X *current
X
Datastructuren
Tree Traversal
Using a Stack
in-orderiterative-inorder( root : Node)
S : Stack
S.create()
// move to first node (left-most)
walkLeft( root, S )
while ( not S.isEmpty() ) do
node = S.pop()
visit( node )
walkLeft( node.right, S )
do
end // iterative-inorder
walkLeft( node : Node, S : Stack)
while (node != nil) do
S.push( node )
node = node.left
od
end // walkLeft
in-order (2)iterative-inorder( root )
S : Stack
S.create()
node = root;
while (node != nil or
not S.isEmpty() ) do
if (node != nil) then
S.push( node )
node = node.left
else
node = S.pop()
visit( node )
node = node.right
fi
od
end // iterative-inorder [bis]
Datastructuren
Tree Traversal
Using a Stack
post-orderiterative-postorder( root )
S : Stack; // contains path from root
S.create();
last = nil
node = root
while (not S.isEmpty() or node != nil) do
if (node != nil) then
S.push(node)
node = node.left
else
peek = S.top()
if (peek.right != nil and last != peek.right) then
// right child exists AND traversing from left, move right
node = peek.right
else
visit(peek)
last = S.pop()
fi
fi
od
end // iterative-postorder
Datastructuren
Tree Traversal
Using a Stack
post-orderiterative-postorder( root )
S : Stack; // contains path from root
S.create();
last = nil
node = root
while (not S.isEmpty() or node != nil) do
if (node != nil) then
S.push(node)
node = node.left
else
peek = S.top()
if (peek.right != nil and last != peek.right) then
// right child exists AND traversing from left, move right
node = peek.right
else
visit(peek)
last = S.pop()
fi
fi
od
end // iterative-postorder
X
X
X X
X X
X
X
X *current
X X
Datastructuren
Tree Traversal
Using Inorder Threads
using inorder threads
threads:replace nil-pointers, explicitly store inorder successors
can be used to perform stack-less traversal
need one bit [boolean] per node to mark thread
Morris-variant: temporary threads, no extra bit
nb. inorder = symmetric
Datastructuren
Tree Traversal
Using Inorder Threads
inorder successor with threads
xcurr
Λ
succ
succ
x
Λ
curr
9
5
3
2
1
4
7
6 8
12
10
11
nil
Datastructuren
Tree Traversal
Using Inorder Threads
traversal with symmetric threads
inorder threads// assuming Root != nil, find first position in inorder
Curr = walkLeft( Root );
while (Curr != nil) do
inOrderVisit( Curr );
if (Curr.IsThread) then
Curr = Curr.right; // to inorder successor
else
Curr = walkLeft (Curr.right)
fi
od
walkLeft( node : Node)
while (node.left != nil) do
node = node.left
od
return node
end // walkLeft
Datastructuren
Tree Traversal
Using Inorder Threads
what about
pre-order traversal with inorder threads
Datastructuren
Tree Traversal
Morris Traversal
Morris: temporary threads
inorder successor(to left parents)
b1
d2
a
3
g
5
i4
e
6
j
7
h8
k9
c
10
f11
end
stack vs. threads
*1
d2
X3
g
5
i4
e
6
*7
X8
k9
X10
f11
nil
Datastructuren
Tree Traversal
Morris Traversal
Morris: basics
inorder successor(to left parents)
b1
d2
a
3
g
5
i4
e
6
j
7
h8
k9
c
10
f11
end
two visits
1 (pre-order)from parentvia child-link (left or right)add thread to current node
2 (inorder)from subtree, via threaddelete thread
algorithm does not know threadsso does not know which visitbut will check!
Datastructuren
Tree Traversal
Morris Traversal
Morris traversal - algorithm
no left subtree:
1st and 2nd visitgo right
(by edge or by thread)
Λ
Curr
new subtree: 1st visitconstruct thread
go left
Λ
Curr
Pred
been there: 2nd visitdelete thread
go right
Curr
Pred
Datastructuren
Tree Traversal
Morris Traversal
Morris traversal - pseudo codemorris-algo
Curr = Root;
while (Curr != nil) do
if (Curr.left = nil) then
inOrderVisit( Curr )
Curr = Curr.right
else
// find predecessor
Pred = Curr.left
while (Pred.right != Curr && Pred.right != nil) do
Pred = Pred.right
od
if (Pred.right=nil) then
// no thread: subtree not yet visited
Pred.right = Curr
Curr = Curr.left
else
// been there, remove thread
Pred.right = nil
inOrderVisit( Curr )
Curr = Curr.right
fi
fi
od
Datastructuren
Tree Traversal
Morris Traversal
alternative view: tree transformation
6
2
1 4
3 5
8
7 9
2
1 4
3 5
6
8
7 9
1
2
4
3 5
6
8
7 9
6
2
1 4
3 5
8
7 9
6
2
1 4
3 5
8
7 9
6
2
1 4
3 5
8
7 9
Datastructuren
Tree Traversal
Link Inversion
features
– use generic traversal– at each step we know which visit– no stack, invert links on path from root– use bit on path (tag) to distinguish left/right
bit stack?– keep parent– global visit counter (pre-/in-/post-order)– single traversal at a time
Datastructuren
Tree Traversal
Link Inversion
inverted links
*
binary tree
parent
tag=1
* curr
tag=0
3 visits at *
tag=1
* parent
tag=0
curr
tag=0
after 1st visit
curr
*
tag=0
parent
after 3rd visit
Datastructuren
Tree Traversal
Link Inversion
end.
Recommended