Can somebody explain me this Binary tree transplant algorithm? - 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 }

Related

breadth of a binary tree

How do we determine breadth a of binary tree.
A simple bin tree
O
/ \
O O
\
O
\
O
\
O
Breadth of above tree is 4
You could use a recursive function that returns two values for a given node: the extent of the subtree at that node towards the left (a negative number or zero), and the extent to the right (zero or positive). So for the example tree given in the question it would return -1, and 3.
To find these extends is easy when you know the extents of the left child and of the right child. And that is where the recursion kicks in, which in fact represents a depth-first traversal.
Here is how that function would look in Python:
def extents(tree):
if not tree:
# If a tree with just one node has extents 0 and 0, then "nothing" should
# have a negative extent to the right and a positive on the left,
# representing a negative breadth
return 1, -1
leftleft, leftright = extents(tree.left)
rightleft, rightright = extents(tree.right)
return min(leftleft-1, rightleft+1), max(leftright-1, rightright+1)
The breadth is simply the difference between the two extents returned by the above function, plus 1 (to count for the root node):
def breadth(tree):
leftextent, rightextent = extents(tree)
return rightextent-leftextent+1
The complete Python code with the example tree, having 6 nodes, as input:
from collections import namedtuple
Node = namedtuple('Node', ['left', 'right'])
def extents(tree):
if not tree:
return 1, -1
leftleft, leftright = extents(tree.left)
rightleft, rightright = extents(tree.right)
return min(leftleft-1, rightleft+1), max(leftright-1, rightright+1)
def breadth(tree):
left, right = extents(tree)
return right-left+1
# example tree as given in question
tree = Node(
Node(
None,
Node(None, Node(None, Node(None, None)))
),
Node(None, None)
)
print(breadth(tree)) # outputs 4

print all paths from root to leaves n-ary tree

I am trying to print all paths from root to all leaves in n-ary tree. This code prints the paths to the leaves, but it also prints subpaths too.
For example, let's say one path is 1-5-7-11. It prints 1-5-7-11, but it also prints 1-5-7, 1-5, so on.
How can I avoid this printing subpaths ?
Here is my code in matlab
Thanks
stack=java.util.Stack();
stack.push(0);
CP = [];
Q = [];
labels = ones(1,size(output.vertices,2));
while ~stack.empty()
x = stack.peek();
for e = 1:size(output.edges,2)
if output.edges{e}(1) == x && labels(output.edges{e}(2)+1) == 1
w = output.edges{e}(2);
stack.push(w);
CP = union(CP,w);
break
end
end
if e == size(output.edges,2)
Q = [];
for v=1:size(CP,2)
Q = union(Q,CP(v));
end
disp(Q)
stack.pop();
labels(x+1) = 0;
CP = CP(find(CP~=x));
end
end
Let's split the problem in two parts.
1. Find all leaf-nodes in a tree
input: Tree (T), with nodes N
output: subset of N (L), such that each node in L is a leaf
initialize an empty stack
push the root node on the stack
while the stack is not empty
do
pop a node from the stack, call it M
if M is a leaf, add it to L
if M is not a leaf, push all its children on the stack
done
2. Given a leaf, find its path to the root
input: leaf node L
output: a path from L to R, with R being the root of the tree
initialize an empty list (P)
while L is not the root of the tree
do
append L to the list
L = parent of L
done
return P

Print all root to leaf paths with there relative positions

Given a binary tree, how do we print the root to the leaf path, but add “_” to indicate the relative position?
Example:
Input : Root of below tree
A
/ \
B C
/ \ / \
D E F G
Output : All root to leaf paths
_ _ A
_ B
D
_ A
B
_ E
A
_ C
F
A
_ C
_ _ G
You can use preorder travel to visit the tree. Record the path with the indent.
When visit left child decrease the indent, when visit right child increase the indent. Then you are able to get the path like,
(0, A), (-1, B), (-2, D)
(0, A), (-1, B), (0, E)
...
During the output phase, normalize the path, find the smallest indent for the path node and shift the path nodes to,
(2, A), (1, B), (0, D)
(1, A), (0, B), (1, E)
...
And then print the path accordingly.
Here's the sample code in python,
def travel(node, indent, path):
if not node:
print_path(path)
return
path.append((indent, node))
if node.left:
travel(node.left, indent - 1, path)
if node.right:
travel(node.right, indent + 1, path)
del path[-1]
def print_path(path):
min_indent = abs(min([x[0] for x in path]))
for indent, node in path:
p = []
for x in xrange(min_indent + indent):
p.append('_')
p.append(node.val)
print ' '.join(p)
The idea base on print path in vertical order.
1) We do Preorder traversal of the given Binary Tree. While traversing the tree, we can recursively calculate horizontal distances or HDs. We initially pass the horizontal distance as 0 for root. For left subtree, we pass the Horizontal Distance as Horizontal distance of root minus 1. For right subtree, we pass the Horizontal Distance as Horizontal Distance of root plus 1. For every HD value, we maintain a list of nodes in a vector (” that will store information of current node horizontal distance and key value of root “).we also maintain the order of node (order in which they appear in path from root to leaf). for maintaining the order.
2) While we reach to leaf node during traverse we print that path with underscore "_"
a) First find the minimum Horizontal distance of the current path.
b) After that we traverse current path
First Print number of underscore “_” : abs (current_node_HD – minimum-HD)
Print current node value.
Do this process for all root to leaf path.
I could not get Qiang Jin's response to work quite right. Switched a few things around.
class Node:
def __init__(self, val):
self.value = val
self.right = None
self.left = None
def printTreeRelativePaths(root):
indent = 0
path = []
preOrder(root, indent, path)
def preOrder(node, indent, path):
path.append((node, indent))
if not node.left and not node.right:
processPath(path)
if node.left:
preOrder(node.left, indent - 1, path)
if node.right:
preOrder(node.right, indent + 1, path)
del path[-1]
def processPath(path):
minIndent = 0
for element in path:
if element[1] < minIndent:
minIndent = element[1]
offset = abs(minIndent)
for element in path:
print ('_' * (offset + element[1])) + element[0].value
root = Node('A')
root.left = Node('B')
root.right = Node('C')
root.left.left = Node('D')
root.left.right = Node('E')
root.right.left = Node('F')
root.right.right = Node('G')
printTreeRelativePaths(root)

Morris inorder Traversal

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.

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;
}

Resources