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
Related
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.
Assume we have a DAG with a single leaf Node leafN. Each node is an object containing list of parent nodes. Node class can be something like class Node(Object, List[Node].
How to construct a DAG from leafN?
For e.g., given leaf node leafD with two parents, leafD(Object#123, List(leafC(leafA(null)), leafB(leafA(null)))) it's DAG will be:
leafA
/ \
leafB leafC
\ /
leafD
i.e., leafA(leafB(leafD(null)), leafC(leafD(null))) (I am ignoring the objects from every node for clarity.)
In short we have a leaf node with parent pointers which themselves have parent pointers and finally, after applying an algorithm, we want a root node with pointers to children nodes which further have pointers to children nodes.
Code ain't required, algorithm or links to any will suffice.
This is pretty simple, once you realise that notionally only the direction of the edges in the DAG has changed.
Instead of the Parent ---> Child node relationship, you have a Child ---> Parent relationship.
As such, all you need to do is construct a DAG from the given relationships, assuming that the Child node is actually the parent, and the parent nodes are childs.
So you end up with
leafD
↙ ↘
leafB leafC
↘ ↙
leafA
Now, all you need to do is reverse the edges in the DAG.
This is pretty simple, One way to do it would be to walk through the DAG, and get all the edge relationships, and then reverse them one by one.
Another would be to do this recursively using level order traversal.
Check this question for more solutions around how to reverse a DAG.
All you need to do is to put your nodes into some data structure that allows you to find a node easily. If your integer values in your node are sequential (or close to it) and start at a low number then you can use an array and just put the node with integer i in position i of the array (This makes including the integer in the node somewhat redundant).
This is all explained well on this site (but note that in their implementation the list is of the edges to, not the edges from) http://algs4.cs.princeton.edu/42directed/
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.
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.
I have a data such that there are many parents each with 0-n children where each child can have 0-n nodes. Each node has a unique identifier (key) Ultimately, the parents are not connected to each other. It seems like this would be a list of trees, however that seems imprecise. I was thinking of joining them with a dummy root.
I need to be able to assembly a list of nodes that occur:
from any given node down (children)
from any given node down (children) then up to the root (up to the specific parent)
the top level parent of any given node (in an O(n) operation)
the level of the child in the tree (in an O(n) operation)
The structure will contain 300,000 nodes.
I was thinking perhaps I could implement a List of Trees and then also maintain a hash lookup structure that will reference a specific key value to provide me with a node as a starting point.
Is this a logical structure? Is there a better way to handle it? It seems crude to me.
If you are concerned in find a root node quickly you can think of create a tree where each node points to another tree.