Morris inorder Traversal - algorithm

learning morris inorder traversal from here: http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ and Explain Morris inorder tree traversal without using stacks or recursion
I am confused. 3 questions are in the comments. Help will be welcomed. Thanks
while (current != null) {
if (current.left == null) {
visit(current);
current = current.right;
} else {
pre = current.left;
while (pre.right != null && pre.right != current) {
pre = pre.right;
} // Q1: why "pre.right != current"?
// pre is initialized as current.left and will go right until null,
// why compare pre.right with current?
if (pre.right == null) {
pre.right = current;
current = current.left;
} else { // Q2: In which case, pre.right is not null and program gets here?
pre.right = null;// Q3: why set pre.right to null?
visit(current);
current = current.right;
}
}
}

OK, if I understand correctly, this traversal essentially restructures the tree so that the left most node is at the root of the tree. So something that starts off like this:
D
/ \
B F
/ \ / \
A C E G
Will look like this:
A
\
B
/ \
A' C
\
D
/ \
B' F
/ \
E G
Where A' is A and all its subtrees.
After visiting, it will reconstruct the tree back.
To answer your questions:
Q1
Before the reconstruction, pre.right != current will never be a loop-ending condition, i.e. it will never be true. However, after the reconstruction, imagine if current held B. pre would be set to A', which is the same as A. pre.right == A'.right == A.right == current. Since this means that the A' node was already visited, it breaks the loop and reconstructs it, which leads to your next question.
Q2
Again, this case never happens prior to the reconstruction of the tree, but after the reconstruction, this is the "what to do" when you reach a node that's already been visited. Which again leads to your next question.
Q3
pre.right is set to null because it means prior to the reconstruction, the pre.right was originally null. Looking at the case post-reconstruction, node B, pre is set to A, which was a leaf node, and had no right child. Thus fixing it back:
B
/ \
A C
\
D
/ \
B' F
/ \
E G
As you can see, A' turned into just A since it's right child is no longer B but null.
Essentially, to help you understand it a bit better:
Morris traversal reconstructs the tree to have it's root as it's left most node(Also note that it now has cyclic paths)
Once it's been reconstructed, it will then visit, then fix the reconstruction back to the original form.

Related

Finding all paths between two nodes on a DAG

I have a DAG that has the following adjacency list
L | G, B, P
G | P, I
B | I
P | I
I | R
R | \
I want to find all paths from L to R. I know that I have to do some kind of DFS, and this is what I have so far. (Excuse the Javascript)
function dfs(G, start_vertex) {
const fringe = []
const visited = new Set()
const output = []
fringe.push(start_vertex)
while (fringe.length != 0) {
const vertex = fringe.pop()
if (!visited.has(vertex)) {
output.push(vertex)
for (neighbor in G[vertex].neighbors) {
fringe.push(neighbor)
}
visited.add(vertex)
}
}
return output
}
The output of dfs(G, "L") is [ 'L', 'P', 'I', 'R', 'B', 'G' ] which is indeed a depth first traversal of this graph, but not the result I'm looking for. After doing some searching, I realize there may be a recursive solution, but there were some comments about this problem being "NP-hard" and something about "exponential paths" which I don't understand.
The problem is indeed np-hard because the number of possible paths between two nodes is exponential to the number of nodes. so no way around having a worst-case exponential runtime.
All paths with start head to vertex vertex can be split into paths with heads head||v where v is adjacent to final vertex of head, unless final vertex of head is already vertex: (pseudo-javascript, can have syntax problems)
function print_all_rec(G, head, vertex){
if(head[head.length-1] == vertex){
print(head); //we're here
return;
}
for(v in head[head.length-1].neighbors){
var newHead = head; newHead.append(v);
print_all_rec(G, newHead, vertex);
}
}
function print_all_routes(G, from, to){
var start = [];
start.append(from);
print_all_rec(G, start, to);
}

Least Common Ancestor algorithm variation

root
/ \
A B
/ | \ / \
C D E F G
| |
H I
Given a tree and a list of types {C,D,E,F}. The summary is {A,F}
(as CDE implies A)
If the list of types was {C,D,E,F, I}. The summary is root (as cde implies a, i implies g, and gf implies b, and ab implies root).
At a high level, how would the algorithm for finding the summary work? (pseudo code only)
Pseudo Code, a simple tree traversal
String getSummary(Node node){
if(node contains element in the set)
return node name;
else
String result = "";
for(Node child : node.getChildren){
if(child contains element in the set)
result += getSummary(child);
}
if(result are all the name of its children)
return node name;
return result;

Pseudocode to compare two trees

This is a problem I've encountered a few times, and haven't been convinced that I've used the most efficient logic.
As an example, presume I have two trees: one is a folder structure, the other is an in-memory 'model' of that folder structure. I wish to compare the two trees, and produce a list of nodes that are present in one tree and not the other - and vice versa.
Is there an accepted algorithm to handle this?
Seems like you just want to do a pre-order traversal, essentially. Where "visiting" a node means checking for children that are in one version but not the other.
More precisely: start at the root. At each node, get a set of items in each of the two versions of the node. The symmetric difference of the two sets contains the items in one but not the other. Print/output those. The intersection contains the items that are common to both. For each item in the intersection (I assume you aren't going to look further into the items that are missing from one tree), call "visit" recursively on that node to check its contents. It's a O(n) operation, with a little recursion overhead.
public boolean compareTrees(TreeNode root1, TreeNode root2) {
if ((root1 == null && root2 != null) ||
(root1 != null && root2 == null)) {
return false;
}
if (root1 == null && root2 == null) {
return true;
}
if (root1.data != root2.data) {
return false;
}
return compareTrees(root1.left, root2.left) &&
compareTrees(root1.right, root2.right);
}
If you use a sort tree, like an AVL tree, you can also traverse your tree efficiently in-order. That will return your paths in sorted order from "low" to "high".
Then you can sort your directory array (e.g. Using quicksort) using the same compare method as you use in your tree algorithm.
Then start comparing the two side by side, advancing to the next item by traversing your tree in-order and checking the next item in your sorted directory array.
This should be more efficient in practice, but only benchmarking can tell.
A simple example code in python.
class Node(object):
def __init__(self, val):
self.val = val
self.child = {}
def get_left(self):
# if left is not in the child dictionary that means the element does not have a left child
if 'left' in self.child:
return self.child['left']
else:
return None
def get_right(self):
# if right is not in the child dictionary that means the element does not have a right child
if 'right' in self.child:
return self.child['right']
else:
return None
def traverse_tree(a):
if a is not None:
print 'current_node : %s' % a.val
if 'left' in a.child:
traverse_tree(a.child['left'])
if 'right' in a.child:
traverse_tree(a.child['right'])
def compare_tree(a, b):
if (a is not None and b is None) or (a is None and b is not None):
return 0
elif a is not None and b is not None:
print a.val, b.val
# print 'currently comparing a : %s, b : %s, left : %s, %s , right : %s, %s' % (a.val, b.val, a.child['left'].val, b.child['left'].val, a.child['right'].val, b.child['right'].val)
if a.val==b.val and compare_tree(a.get_left(), b.get_left()) and compare_tree(a.get_right(), b.get_right()):
return 1
else:
return 0
else:
return 1
# Example
a = Node(1)
b = Node(0)
a.child['left'] = Node(2)
a.child['right'] = Node(3)
a.child['left'].child['left'] = Node(4)
a.child['left'].child['right'] = Node(5)
a.child['right'].child['left'] = Node(6)
a.child['right'].child['right'] = Node(7)
b.child['left'] = Node(2)
b.child['right'] = Node(3)
b.child['left'].child['left'] = Node(4)
#b.child['left'].child['right'] = Node(5)
b.child['right'].child['left'] = Node(6)
b.child['right'].child['right'] = Node(7)
if compare_tree(a, b):
print 'trees are equal'
else:
print 'trees are unequal'
# DFS traversal
traverse_tree(a)
Also pasted an example that you can run.
You may also want to have a look at how git does it. Essentially whenever you do a git diff, under the hood a tree comparison is done.

How to calculate parent based on successor in Binary Search Tree (BST)

As the title implies, if we have node x in a Binary Search Tree (BST) and we know the info of x.successor instead of x.parent, also we know x.left and x.right. How to calculate x.parent based on the above information.
I decide to analyze it on two cases: (root have height 0)
if x does not have right child, x.successor's height must less than x. In other words, x.successor is in the "upper level" of x.
if x have right child, x.successor's height must greater than x. It means x.successor is in the "lower level" of x.
For the first case, we could have the following pseudo-code.
y = x.succ
if x.right == NIL
z = y.left
while x != z
y = z;
z = z.right
return z
How to handle the second case? what happened if x.right != NIL ?
15
6 18
3 7 17 19
2 4 13 20
9
How to retrieve the parent of node 18 and 19, since there rightmost node 20 does not have successor, so it will return NIL.
we can not get the parent always based on your info.
for instance, 2 nodes, nodeOne.right = x
we only know x left = null, right = null, successor = null
we are not able to retrieve nodeOne
we can get the parent when x is not at the right-most branch(which means it has some ancestor whose left branch includes the x).
the algorithm could be:
continue find the right son, right grandson, ..., till there is none
then get the successor, and go into your code(your code is a little bit err?)
function getParent(Node node){
Node right = node;
for(;right.right != null; right = right.right){
}
Node successor = right.successor;
if (successor == null)
return null;
if (successor.left == node)
return successor;
for(Node p = successor.left; p!= null; p=p.right){
if (p.right == node){
return p;
}
}
return null;
}

Can somebody explain me this Binary tree transplant algorithm?

I found this algorithm in a textbook and I'm not sure I understand it.
TRANSPLANT(T,u,v){
1 if u.p == NIL
2 T.root = v
3 else if u == u.p.left
4 u.p.left=v
5 else u.p.right == v
6 if v != NIL
7 v.p=u.p
}
Also, what do you think is p inside the node?
Why can't he just compare the node with the node?
Notes from textbook:
In order to move subtrees around within the binary search tree, we define a
subroutine TRANSPLANT, which replaces one subtree as a child of its parent with
another subtree. When TRANSPLANT replaces the subtree rooted at node u with
the subtree rooted at node , node u's parent becomes node ’s parent, and u's
parent ends up having as its appropriate child.
As far as I understood the code, it tries to replace the node u and its corresponding subtree with some other node v and its subtree. I assume that p stands for the parent of a node.
TRANSPLANT(T,u,v) {
1 if u.p == NIL -- if u doesn't have a parent => u is the root
2 T.root = v -- then v must replace u as the root of the tree T
3 else if u == u.p.left -- if u is a left subtree of its parent
4 u.p.left = v -- then v must replace u as the left
- -- subtree of u's parent
5 else u.p.right == v -- otherwise u is a right subtree
- -- (as the tree is binary) and v must replace
- -- u as the right subtree of u's parent
6 if v != NIL -- if v has replaced u (and thus is not NIL)
7 v.p = u.p -- v must have the same parent as u
8 }

Resources