iterative k-ary tree pre- and postorder traversal - algorithm

I have a k-ary tree, and I want to traverse it using iteration.
It is a scene graph, so every time I encounter a transform node I put its matrix on a stack, and every time a encounter a mesh node it is rendered using the matrix-stack. This both must be pre order.
But when all children of a transform node are handled, its matrix has to be popped from the matrix-stack. So I also need a post-order operation.
I found some algorithms for iterative post-order traversal, but always for binary trees and without the additional pre-order operations.

This is untested, so treat with caution.
The basic idea to solve this is to mark the nodes as visited when first encountering them. Then put all the children on the stack.
If encountering a leaf-node without children, it can be savely printed/handled and popped from stack.
When the next node on the stack is already visited, all children must have been handled before, else the stack would not have been cleared this far.
We now know for interim nodes with arbitrary number of children that it can be handled in post-order.

Related

How to check if two binary trees share a node

Given an array of binary trees find whether any two trees share a node, not value wise, but "pointer" wise. At the bottom I provided an example.
My approach was to iterate through all the trees and store all the leaves (pointers) from each tree into a list, then check if list has any duplicates, but that's a rather slow approach. Is there perhaps a quicker way to solve this?
In the worst case you will have to traverse all nodes (all pointers) to find a shared node (pointer), as it might happen to be the last one visited. So the best time complexity we can expect to have is O(𝑚+𝑛) where 𝑚 and 𝑛 represent the number of nodes in either tree.
We can achieve this time complexity if we store the pointers from the first tree in a hash set and then traverse the pointers of the second tree to see if any of those is in the set. Assuming that get/set operations on a hash set have an amortized constant time complexity, the overal time complexity will be O(𝑚+𝑛).
If the same program is responsible for constructing the trees, then a reuse of the same node can be detected upon insertion. For instance, reuse of the same node in multiple trees can be completely avoided by having the insert method of your tree only take a value as argument, never a node instance. The method will then encapsulate the actual creation of the node, guaranteeing its uniqueness.
An idea for O(#nodes) time and O(1) space. It does more traversal work than simple traversals using a hash table, but it doesn't have the cost of using a hash table. I don't know what's better. Might depend on the language.
For two trees
Create one extra node. Do a Morris traversal of the first tree. It only modifies right child pointers, so we can use left child pointers for marking nodes as seen. For every tree node without left child, set our extra node as left child. Whenever checking a left child pointer, treat our extra node like a null pointer, i.e., don't visit it. After the traversal, the tree structure is restored, and all originally left-child-less tree nodes now point to our extra node as left child. That includes all leaf nodes.
Do a Morris traversal of the second tree. Again treat pointers to our extra node like null pointers. If we ever do encounter our extra node, we know the trees share a node. If not, then we know the trees don't share a node, since if they did share any, they'd also share a leaf node (just go down from any shared node to a leaf node, that's also shared), and all leafs nodes of the first tree are marked. After the traversal, the second tree is restored.
Do a Morris traversal of the first tree again, this time removing our extra node, restoring the original null pointers.
For an array of more than two trees
Mark the first tree as above. Check the second tree as above. Mark the second tree. Check the third. Mark the third. Check the fourth. Mark the fourth. Etc. When you found a shared node or there are no more trees, unmark the marked trees.
Every shared node must have two parents, or an ancestor with two parents.
LOOP over nodes
IF node has two parents
MARK node as shared
Mark all descendants as shared.

Idiomatic Traversal Binary Tree (Perhaps Any Tree)

A Doubly Linked List enables idiomatic traversal of a Linked List and I thought why not for a Binary Tree? Traditionally, Binary Trees or Trees ingeneral are unidirectional and that implies, given a large tree with sufficient number of nodes, the running time to find a leaf node can be costly.
If, after finding such a node, to find the next I could traverse the tree back toward the root, would that not be advantageous as compared to another depth-first search through every node of the tree? I have never considered this before until realizing the marriage of a Doubly Linked List and a Binary Tree could potentially add benefit.
For example, if I employed an inner class
class Tree<T> {
private class TwoWayNode {
var data : T
var left : TwoWayNode
var right : TwoWayNode
var previous : TwoWayNode
}
}
The use of left and right are as normal to traverse the respective subtrees from each node and previous would hold a pointer to the parent node enable idiomatic traversal. Would someting like this work well and what are some of the potential problems or pitfalls?
Given you store a previous reference, you can walk leftmost first. Upon arrival at the leaf node, you back one up again, traverse right.
You can always compare the current node, your "walker", with the child nodes, so you can check if you went left or right the last time. This makes your traversal stateless and you do not even need recursion; suitable for very large datasets.
Now, everytime you just left the right leaf, you back one up again.
This algorithm is a Depth-First-Search.*
Making it faster:
Given that you could define some deterministic condition for the order of traversal, this can become quite flexible, and even be used in applications like ray tracing.
*: http://en.wikipedia.org/wiki/Depth-first_search
Bonus: This paper on traversal algorithms for Kd-trees in Ray Tracing: Review: Kd-tree Traversal Algorithms for Ray Tracing (http://dcgi.felk.cvut.cz/home/havran/ARTICLES)/cgf2011.pdf
Indeed nodes of a binary tree are often implemented with pointers to the left and right child and the parent (see this implementation of red black trees).
But you not always need a parent pointer:
For an inorder-traversal you can use a recursive algorithm so that the call stack takes care of that for you.
If you want to access the min or max node you can simply maintain a extra pointer to them.
Sometimes you can use a finger tree.
Or organize your pointers extra clever (see Self adjusting binary search trees page 666):
The left pointer of a node points to the first (left) child
The right pointer of a node points to either the sibling (if it is a left child) or back to the parent (if it is a right child)
Extra cool: Threaded binary search trees for extra easy inorder (and reverse order) traversal without a stack - so O(1) space!

iterative approach for tree traversal

Can someone help me out with an algorithm to traverse a binary tree iteratively without using any other data structure like a stack
I read somewhere we can have a flag named visited for each node and turn in on if the node is visited but my BinaryTreeNode class does not have a visited variable defined. So I can not potentially do something like node.left.visited = false
Is there any other way to traverse iteratively?
One option would be to thread the binary tree.
Whenever some node points to NULL (be it left or right), make that node point to the node which comes next in its traversal (pre-order, post-order, etc). In this way, you can traverse the entire tree in one iteration.
Sample threaded binary tree:
Note that left node of each node points to the largest value smaller than it. And the right node of each node points to the smallest value larger than it. So this gives an in-order traversal.

Stackless pre-order traversal in a binary tree

Is it possible to perform iterative *pre-order* traversal on a binary tree without using node-stacks or "visited" flags?
As far as I know, such approaches usually require the nodes in the tree to have pointers to their parents. Now, to be sure, I know how to perform pre-order traversal using parent-pointers and visited-flags thus eliminating any requirement of stacks of nodes for iterative traversal.
But, I was wondering if visited-flags are really necessary. They would occupy a lot of memory if the tree has a lot of nodes. Also, having them would not make much sense if many pre-order tree traversals of a binary-tree are going on simultaneously in parallel.
If it is possible to perform this, some pseudo-code or better a short C++ code sample would be really useful.
EDIT: I specifically do not want to use recursion for pre-order traversal. The context for my question is that I have an octree (which is like a binary tree) which I have constructed on the GPU. I want to launch many threads, each of which does a tree-traversal independently and in parallel.
Firstly, CUDA does not support recursion.
Seoncdly, the concept of visited flags applies only for a single traversal. Since many traversals are going on simultaneously , having visited-flags field in the node data structure is of no use. They would make sense only on the CPU where all independent tree traversals are/can be serialised. To be more specific, after every tree-traversal we can set the visited-flags to false before performing another pre-order tree-traversal
You can use this algorithm, which only needs parent pointers and no additional storage:
For an inner node, the next node in a pre-order traversal is its leftmost child.
For a leaf node: Keep going upwards in the tree until you are coming from the left child of a node with two children. That node's right child will then be the next node to traverse.
function nextNode(node):
# inner node: return leftmost child
if node.left != null:
return node.left
if node.right != null:
return node.right
# leaf node
while (node.parent != null)
if node == node.parent.left and node.parent.right != null:
return node.parent.right
node = node.parent
return null #no more nodes
You can give each leaf node a pointer to the node that would come next in according to a preorder traversal.
For example, given the binary tree:
A
/ \
B C
/ \
D E
\
F
D would need to store a pointer to E, and F would need to store a pointer to C. Then you can simply traverse the tree iteratively as if it were a linked list.
You can do it with no extra storage by storing the same pointer in both the left and right subtree nodes. Since such a structure is not allowed in a tree (that would make it a DAG), you can safely infer that any node where all "child" pointers point to the same place is a leaf node.
You could add a single bit at each node signifying whether the first sub-branch addition went left-ward or rightward... Then, iterating through the tree allows choosing the original direction at every branch.
If you insist on doing this, you could number every possible path through the tree, and then set each worker to follow that path.
Your numbering scheme can simply be that each zero-bit means take the left child, and each one-bit means take the right child. To execute a depth-first search, process your number from least-significant bit to most-significant.
While it is not necessary to know the depth of the tree in advance, if you don't you will need to handle the case where all further numbers hit a leaf before the number is fully consumed.
There is a hack using the absolute values of the {->left,->right} pointers to encode one bit per node. It needs a first pass to get the initial pointer-"polarity" right.
It seems to be called DSW.
You can find more in this https://groups.google.com/group/comp.programming/browse_thread/thread/3552ea0af2006b28/6323076923faec26?hl=nl&q=tree+transversal&lnk=nl& usenet thread.
I don't know if it can be expanded to quad-trees or oct-trees, and I seriously doubt if it can be extended to multithreaded access. Adding a parent pointer is probably easier...
One direction you might want to consider is to delete the nodes of the tree as you traverse them and insert those nodes into a new tree. If you insert nodes in preorder, the new tree is going to be exactly same. But the problem here is how do you maintain integrity of the original tree as you delete items.

tree traverse recursive in level-first order and depth-first order

Is there any algorithm can traverse a tree recursively in level-first order and non-recursively in postorder.Thanks a lot.
To get an effectively recursive breadth-first search you can use iterative deepening depth-first search. It's particularly good for situations where the branching factor is high, where regular breadth-first search tends to choke from excessive memory consumption.
Edit: Marcos Marin already mentioned it, but for the sake of completeness, the Wikipedia page on breadth-first traversal describes the algorithm thus:
Enqueue the root node.
Dequeue a node and examine it.
If the element sought is found in this node, quit the search and return a result.
Otherwise enqueue any successors (the direct child nodes) that have not yet been discovered.
If the queue is empty, every node on the graph has been examined – quit the search and return "not found".
Repeat from Step 2.
Note: Using a stack instead of a queue would turn this algorithm into a depth-first search.
That last line is, obviously, interesting to you if you want to do a non-recursive depth-first traversal. Getting pre- or post-order is just a matter of modifying how you append the nodes in step 2.b.
You can recurse a tree in post order iteratively by using a stack instead of the implicit call stack used in recursion.
Wikipedia says,
Traversal
Compared to linear data structures
like linked lists and one dimensional
arrays, which have only one logical
means of traversal, tree structures
can be traversed in many different
ways. Starting at the root of a binary
tree, there are three main steps that
can be performed and the order in
which they are performed defines the
traversal type.
These steps (in no
particular order) are: performing an
action on the current node (referred
to as "visiting" the node), traversing
to the left child node, and traversing
to the right child node. Thus the
process is most easily described
through recursion.
To traverse a non-empty binary tree in
preorder, perform the following
operations recursively at each node,
starting with the root node:
Visit the node.
Traverse the left subtree.
Traverse the right subtree. (This is also called Depth-first
traversal.)
To traverse a non-empty binary tree in
inorder, perform the following
operations recursively at each node:
Traverse the left subtree.
Visit the node.
Traverse the right subtree. (This is also called Symmetric traversal.)
To traverse a non-empty binary tree in
postorder, perform the following
operations recursively at each node:
Traverse the left subtree.
Traverse the right subtree.
Visit the node.
Finally, trees can also be traversed
in level-order, where we visit every
node on a level before going to a
lower level. This is also called
Breadth-first traversal.

Resources