Stackless pre-order traversal in a binary tree - algorithm

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.

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.

Tree traversal - starting at leaves with only parent pointers?

Is it conceptually possible to have a tree where you traverse it by starting at a given leaf node (rather than the root node) and use parent pointers to get to the root?
I ask this since I saw someone implement a tree and they used an array to hold all of the leaf nodes/external nodes and each of the leaf/external nodes point only to their parent nodes and those parent point to their parent node etc. until you get to the root node which has no parents. Their implementation thus would require you to start at one of the leaves to get to anywhere in the tree and you would cannot go "down" the tree since her tree nodes do not have any children pointers, only parent pointers.
I found this implementation interesting since I haven't seen anything like it but I was curious if it could still be considered it a "tree". I have never seen a tree where you start traversal at the leaves, instead of root. I have also never seen a tree where the tree nodes only have parent pointers and no children pointers.
Yep, this structure exists. It's often called a spaghetti stack.
Spaghetti stacks are useful for representing the "is a part of" relation. For example, if you want to represent a class hierarchy in a way that makes upcasting efficient, then you might represent the class hierarchy as a spaghetti stack in which the node for each type stores a pointer to its parent type. That way, it's easy to find whether an upcast is valid by just walking upward from the node.
They're also often used in compilers to track scoping information. Each node represents one scope in the program, and each node has a pointer to the node representing the scope one level above it.
You can also think of a blockchain this way. Each block stores a backreference to its parent block. By starting at any block and tracing backwards to the root, you can recover the state encoded by that block.
Hope this helps!
If an array A of leaf nodes are given, traversal is possible. If only a single leaf node is given, I don't know how to traverse the tree. Pseudocode:
// initial step
add all nodes in A to a queue Q
//removeNode(Q) returns pointer to node at front of Q
while((node = removeNode(Q)) != NULL)
/* do your operation on node */
add node->parent to Q

Find a loop in a binary tree

How to find a loop in a binary tree? I am looking for a solution other than marking the visited nodes as visited or doing a address hashing. Any ideas?
Suppose you have a binary tree but you don't trust it and you think it might be a graph, the general case will dictate to remember the visited nodes. It is, somewhat, the same algorithm to construct a minimum spanning tree from a graph and this means the space and time complexity will be an issue.
Another approach would be to consider the data you save in the tree. Consider you have numbers of hashes so you can compare.
A pseudocode would test for this conditions:
Every node would have to have a maximum of 2 children and 1 parent (max 3 connections). More then 3 connections => not a binary tree.
The parent must not be a child.
If a node has two children, then the left child has a smaller value than the parent and the right child has a bigger value. So considering this, if a leaf, or inner node has as a child some node on a higher level (like parent's parent) you can determine a loop based on the values. If a child is a right node then it's value must be bigger then it's parent but if that child forms a loop, it means he is from the left part or the right part of the parent.
3.a. So if it is from the left part then it's value is smaller than it's sibling. So => not a binary tree. The idea is somewhat the same for the other part.
Testing aside, in what form is the tree that you want to test? Remeber that every node has a pointer to it's parent. An this pointer points to a single parent. So depending of the format you tree is in, you can take advantage from this.
As mentioned already: A tree does not (by definition) contain cycles (loops).
To test if your directed graph contains cycles (references to nodes already added to the tree) you can iterate trough the tree and add each node to a visited-list (or the hash of it if you rather prefer) and check each new node if it is in the list.
Plenty of algorithms for cycle-detection in graphs are just a google-search away.

Resources