I have a graph that is not binary, and is of single direction. It can look like the following:
I would like to find the shortest path, for example Team "G" to Team "D". What methods can I use?
By "of single direction" I imagine what you mean is that the tree is represented by nodes which only point at the children, not at the parents. Given that, user3386109's comment provides a simple way to get the answer you are looking for.
Find the path from the root to the first node by doing any tree traversal, like in-order (even if the order of children is insignificant, in practice, there will be some way to enumerate them in some order), and record the sequence of nodes from the root to the first node. In your example, we would get G-B-A (assuming a recursive solution where we are printing these nodes in reverse order).
Find the path from the root to the second node in the same way. Here, we'd get a path like D-A.
Find the first common ancestor of the two nodes; assuming the nodes are labeled uniquely as in this example, we can simply find the first symbol in either string of nodes, that is also in the other string of nodes. Regardless of which string we start with, we should get the same answer, as we do in your example: A
Chop off everything in both strings after the common ancestor, reverse one of the strings, and concatenate them with the common ancestor in the middle. This gives a path starting with node1 going to node2. Note that the problem asks for the shortest path; however, in a tree, there will be exactly one path between any two nodes. In your example, we get G-B-A-D.
Some pseudocode...
class Node {
char label;
Node[] children;
}
string FindPath(Node root, Node node1, Node node2) {
// make sure we have valid inputs
if (root == null || node1 == null || node2 == null) return null;
// look for paths to the nodes from the root
string path1 = FindPath(root, node1);
string path2 = FindPath(root, node2);
// one of the nodes wasn't found
if (path1 == null || path2 == null) return null;
// look for first common node
// note: this isn't the most efficient approach, see
// comments on time complexity below
for (int i = 0; i < path1.Length; i++) {
char label = path1[i];
if (path2.Contains(label) {
path1 = path1.Substring(0, i);
path2 = path2.Substring(0, path2.IndexOf(label);
return path1 + label + ReverseString(path2);
}
}
// will never reach here because it's guaranteed we will find
// a common ancestor in a tree
throw new Exception("Unreachable statement");
}
string FindPath(Node root, Node node) {
// make sure inputs are valid
if (root == null || node == null) return null;
if (root.label == node.label) {
// found the node
return node.label;
} else {
// this is not the node, exit early if no children
if (root.children == null || root.children.Count == 0) return null;
// check each child and if we find a path, return it
foreach (Node child in root.children) {
string path = FindPath(child, node);
if (path != null && path.Length > 0) {
return path + root.label;
}
}
// it's possible that the target node is not in this subtree
return null;
}
}
In terms of the number of nodes in the tree, the complexity should look like...
Getting the path from the root to each node should at worst visit each node in the tree, so O(|V|)
Looking for the first common node... well, a naive approach would be O(|V|^2) if we use the code as proposed above, since in the worst case, the tree is split in two long branches. But, we could be a little smarter and start at the end and work our way back as long as the strings match, and return the last matching node we saw as soon as we see that they don't match anymore (or we run out of symbols to check). Coding that is left as an exercise and that should be O(|V|)
The actual question is :
Write a program that takes as input a general tree T and a position p of T and converts T to another tree with the same set of position adjacencies, but now with p as its root.
I am not sure what does it means by the position adjacencies exactly but from what I understood is that the relation between the parent as the nodes should be maintained.
But if a node is made to be the root then they wont be having the same positional adjacency. I would like to implement this question using a binary tree for starters.
Can someone help me out with how should I implement it?
The quote uses some terms which should be further defined, but I will try to make some assumptions here:
...but now with p as its root.
This implies that the tree given as input is a so-called rooted tree and not just a general tree as it states at the outset. It is important to note this, as in graph theory a tree is just a graph where each pair of nodes is connected by a single path. The concept of root only enters the story when we speak of a rooted tree.
...a position p of T...
This is uncommon terminology. I'll assume that position is a synonym for what is generally called a vertex or node in graph theory.
... position adjacencies
I'll assume that this is referring to the edges of the tree.
... the relation between the parent as the nodes should be maintained.
If you phrase it that way, then it is impossible to change the tree, as the set of parent-child relationships uniquely defines the rooted tree. So we must assume that this is not about maintaining the parent-child relationship, but just the relationship between two vertices, where possibly the role of parent may be changing.
I would like to implement this question using a binary tree for starters.
That is not a good idea: a binary tree may need to transition to a non-binary tree. For example, let's say the input tree is this binary tree:
4
/
2
/ \
1 3
And the input vertex is the one with value 2. That means the output tree will not be binary, but will be:
2
/|\
1 3 4
So, we have a rooted tree and a vertex in that tree as input, and need to produce a rooted tree as output whose root is that given vertex.
Algorithm
The algorithm can be recursive:
If the given node p (that should become the root) has no parent, nothing needs to change: exit
Solve the problem of making that parent the root recursively. Once that is done the p's parent has no parent, since p's parent has become the root.
Detach p from its parent, and instead make that parent a child of p. So these two nodes remain connected, but the role of parent-child switches to child-parent.
Here is an implementation in JavaScript. You can run the snippet here on an example graph:
8
/ \
4 10
/
2 <-- to become new root
/ \
1 3
Resulting tree should be:
2
/|\
1 3 4
\
8
\
10
class Node {
constructor(value) {
this.value = value;
this.children = new Set; // any number of children
this.parent = null;
}
addChild(node) {
this.children.add(node);
node.parent = this; // back reference
return node;
}
detachFromParent() {
if (this.parent != null) {
this.parent.children.delete(this);
this.parent = null;
}
}
makeRoot() {
let parent = this.parent;
if (parent != null) {
parent.makeRoot();
this.detachFromParent();
this.addChild(parent);
}
}
print(indent="") {
console.log(indent + this.value);
indent += " ";
for (const child of this.children) {
child.print(indent);
}
}
}
// demo
let eight = new Node(8);
let ten = new Node(10);
let four = new Node(4);
let two = new Node(2);
let one = new Node(1);
let three = new Node(3);
eight.addChild(four);
eight.addChild(ten);
four.addChild(two);
two.addChild(one);
two.addChild(three);
console.log("input:");
eight.print();
console.log("change root to 2...");
two.makeRoot();
two.print();
I'm trying to solve the following algorithm:
You have an n-ary tree. Find all the nodes satisfying the following
condition:
the node has child node(s) but all of the child nodes are leafs (they have no children ). Return a list of leaf only parent nodes and
their depth in the tree.
So if I have the tree below, the only node satisfying the above condition is D, because it has descendants (E) but they don't have children.
I am root!
/\ \
A B F
/\
C D
\
E
I'm trying to implement this in Java but pseudocode will also work for me.
I have the tree and node structures implemented here: N-ary trees in Java.
All I need is the algorithm.
start at root
while left son exists : go to left son
go back to father and check next son
if has no other sons : insert father to list
else insert father to list and go to step 2 but keep a depth counter and if found grandchildren : remove father from list
if finished all nodes : return list
root
/ \ \
A B F
/ \
C D
\
E
run example:
go to A
go back to root and insert root to list
go to B
go to C (remove root from potential because of counter)
go back to B and add B to list
go to D
go to E (remove B from potential because of counter)
go back to D and insert to list
go back to B
go back to root
go to F (don't insert root because root was already inserted [and removed]
return list which has only D
To make this work you should have a counter running for the node you are checking (to see if grandchildren exist) and also you should have a way of knowing if a node has been removed from the list so you would not insert it again (I didn't explicitly write it but I used 2 list - 1 for potentials and 1 for final)
OK, I got it. Here's the solution I've reached. I'm sure there are better solutions though - you're welcome to correct me.
// kick off the recursion
public Map<Integer, Integer> findLeafOnlyParents(GenericTree<Integer> tree){
Map<Integer, Integer> resultMap = new HashMap<>();
// start search from the root
traverseWithDepth(tree.getRoot(), resultMap, 0);
return resultMap;
}
private void traverseWithDepth(GenericTreeNode<Integer> node, Map<Integer, Integer> traversalResult, int depth) {
// check if the current note in the traversal is parent Of leaf-only nodes
if (isParentOfLeafOnly(node)){
traversalResult.put(node.data, depth);
}
// check the node's children
for(GenericTreeNode<Integer> child : node.getChildren()) {
traverseWithDepth(child, traversalResult, depth + 1);
}
}
// the main logic is here
private boolean isParentOfLeafOnly(GenericTreeNode<Integer> node){
boolean isParentOfLeafOnly = false;
// check if the node has children
if(node.getChildren().size() > 0){
// check the children of the node - they should not have children
List<GenericTreeNode<Integer>> children = node.getChildren();
boolean grandChildrenExist = false;
// for each child check if it has children of its own
for(GenericTreeNode<Integer> child : children) {
grandChildrenExist = child.getChildren().size() > 0;
// once found note that the current node has grandchildren,
// so we don't need to check the rest of the children of the node
if (grandChildrenExist){
break;
}
}
// we need only the parents who don't have great children
isParentOfLeafOnly = !grandChildrenExist;
}
return isParentOfLeafOnly;
}
1
/ \
2 3
/ \ / \
4 5 6 7
for the given binary tree we need to create a matrix a[7][7]
satisfying the ancestor property like a[2][1]=1 since 1 is an ancestor of 2 ....
i solved it by using extra space an array ...the solution i came up is
int a[n][n]={0};
void updatematrix(int a[][n],struct node *root,int temp[],int index){
if(root == NULL)
return ;
int i;
for(i=0;i< index;i++)
a[root->data][temp[i]]=1;
temp[index]=root->data;
updatematrix(a,root->left,temp,index+1);
updatematrix(a,root->right,temp,index+1);
}
is there any mistake in my solution ?
can we do this inplace ???(i mean without using the temp array )
temp contains the path from root to current node, i.e. the set of nodes visited while walking down the tree to arrive at the current node.
If you have a parent pointer in each node (but I guess not), you can follow those pointers and walk up the tree to traverse the same set of nodes as temp. But this uses more memory.
You can also walk down the tree several times (pseudocode):
def updatematrix(a,node):
if node is null: return
walkDown(a.data,node.left)
walkDown(a.data,node.right)
updatematrix(a,node.left)
updatematrix(a,node.right)
def walkDown(data,node):
if node is null: return
a[node][data] = 1
walkDown(data,node.left)
walkDown(data,node.right)
Same complexity, but the pattern of memory access looks less cache friendly.
I have the following text from an academic course I took a while ago about inorder traversal (they also call it pancaking) of a binary tree (not BST):
Inorder tree traversal
Draw a line around the outside of the
tree. Start to the left of the root,
and go around the outside of the tree,
to end up to the right of the root.
Stay as close to the tree as possible,
but do not cross the tree. (Think of
the tree — its branches and nodes — as
a solid barrier.) The order of the
nodes is the order in which this line
passes underneath them. If you are
unsure as to when you go “underneath”
a node, remember that a node “to the
left” always comes first.
Here's the example used (slightly different tree from below)
However when I do a search on google, I get a conflicting definition. For example the wikipedia example:
Inorder traversal sequence: A, B, C,
D, E, F, G, H, I
(leftchild,rootnode,right node)
But according to (my understanding of) definition #1, this should be
A, B, D, C, E, F, G, I, H
Can anyone clarify which definition is correct? They might be both describing different traversal methods, but happen to be using the same name. I'm having trouble believing the peer-reviewed academic text is wrong, but can't be certain.
In my bad attempt at the drawing here's the order that shows how they should be picked.
pretty much pick the node that is directly above the line being drawn,.
Forget the definitions, it's so much easier to just apply the algorithm:
void inOrderPrint(Node root)
{
if (root.left != null) inOrderPrint(root.left);
print(root.name);
if (root.right != null) inOrderPrint(root.right);
}
It's just three lines. Rearrange the order for pre- and post- order.
If you read carefully you see that the first "definition" says to start left of the root and that the order of the nodes is determined by when you pass under them. So B is not the first node, as you pass it from the left on the way to A, then first pass under A after which you go up and pass under B. Therefore it seems that both definitions give the same result.
I personally found this lecture quite helpful.
Both definitions give the same result. Don't be fooled by the letters in the first example - look at the numbers along the path. The second example does use letters to denote the path - perhaps that is what is throwing you off.
For example, in your example order showing how you thought the second tree would be traversed using the algorithm of the first one, you place "D" after "B" but you shouldn't because there is still a left-hand child node of D available (that's why the first item says "the order in which this line passes underneath them."
this may be late but it could be useful for anyone later ..
u just need not to ignore the dummy or null nodes e.g the Node G has a left null node .. considering this null node will make every thing alright ..
The proper traversal would be: as far left as possible with leaf nodes (not root nodes)
Left Root Right
A B NULL
C D E
Null F G
H I NULL
F is root or left, i am not sure
I think the first binary tree with the root of a is a Binary tree which is not correctly constructed.
Try to implement so that all the left side of the tree is less than the root and all the right side of the tree is greater than or equal to the root.
But according to (my understanding of)
definition #1, this should be
A, B, D, C, E, F, G, I, H
Unfortunately, your understanding is wrong.
Whenever you arrive at a node, you must descend to an available left node, before you look at the current node, then you look at an available right node.
When you chose D before C, you didn't descend to the left node first.
Hey according to me as mentioned in wiki is correct the sequence for a inorder traversal is left-root-right.
Till A, B, C, D, E, F i think you have understood already. Now after root F the next node is G that doesn't hav a left node but a right node so as per the rule (left-root-right) its null-g-right. Now I is the right node of G but I has a left node hence the traversal would be GHI. This is correct.
Hope this helps.
For an inline tree traversal you have to keep in mind that the order of traversal is left-node-right. For the above diagram that you are conflicted on, your error occurs when you read a parent node before reading any leaf(children) nodes to the left.
The proper traversal would be: as far left as possible with leaf nodes(A), return to parent node(B), move to the right, but since D has a child to its left you move down again(C), back up to C's parent(D), to D's right child(E), reverse back to the root(F), move to the right leaf(G), move to G's leaf but since it has a left leaf node move there(H), return to parent(I).
the above traversal reads the node when I have it listed in parenthesis.
package datastructure;
public class BinaryTreeTraversal {
public static Node<Integer> node;
public static Node<Integer> sortedArrayToBST(int arr[], int start, int end) {
if (start > end)
return null;
int mid = start + (end - start) / 2;
Node<Integer> node = new Node<Integer>();
node.setValue(arr[mid]);
node.left = sortedArrayToBST(arr, start, mid - 1);
node.right = sortedArrayToBST(arr, mid + 1, end);
return node;
}
public static void main(String[] args) {
int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 };
Node<Integer> node = sortedArrayToBST(test, 0, test.length - 1);
System.out.println("preOrderTraversal >> ");
preOrderTraversal(node);
System.out.println("");
System.out.println("inOrderTraversal >> ");
inOrderTraversal(node);
System.out.println("");
System.out.println("postOrderTraversal >> ");
postOrderTraversal(node);
}
public static void preOrderTraversal(Node<Integer> node) {
if (node != null) {
System.out.print(" " + node.toString());
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
public static void inOrderTraversal(Node<Integer> node) {
if (node != null) {
inOrderTraversal(node.left);
System.out.print(" " + node.toString());
inOrderTraversal(node.right);
}
}
public static void postOrderTraversal(Node<Integer> node) {
if (node != null) {
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(" " + node.toString());
}
}
}
package datastructure;
public class Node {
E value = null;
Node<E> left;
Node<E> right;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
public Node<E> getLeft() {
return left;
}
public void setLeft(Node<E> left) {
this.left = left;
}
public Node<E> getRight() {
return right;
}
public void setRight(Node<E> right) {
this.right = right;
}
#Override
public String toString() {
return " " +value;
}
}
preOrderTraversal >>
4 2 1 3 6 5 7
inOrderTraversal >>
1 2 3 4 5 6 7
postOrderTraversal >>
1 3 2 5 7 6 4
void
inorder (NODE root)
{
if (root != NULL)
{
inorder (root->llink);
printf ("%d\t", root->info);
inorder (root->rlink);
}
}
This the most simplest approach to recursive definition of in-order traversal, just call this function in the main function to get the in-order traversal of a given binary tree.
It is correct for preorder,nt for inorder