I am working on writing red-black tree myself. But when I test the rotation that involves root to be rotated, somewhat it loses reference.
Tree structure:
45
/ \
40x 70
/ \ /
7 41 50
/ \
6 39
The rotate logic says:
"Rotate with 45(root) as top, in the direction that raises X (i.e. 40)"
So this means right rotate and result should look like:
40x
/ \
7 45
/ \ / \
6 39 41 70
/
50
Assuming that node 45 is grandparent and 7 is parent and 41 is current. (I know the order doesn't make sense but please ignore, this is because I've rotated once already)
Code:
//current is node 45
//parent is node 7
//grandparent is node 45 (root)
//first detach cross node (i.e. 41)
Node crossNode2 = grandparent.left.right;
grandparent.left.right = null; //detach
45
/ \
40x 70
/ \ /
7 null 50
/ \
6 39
grandparent.left = null;
45
/ \
null 70
/
50
current.right = grandparent;
40
/ \
7 45
/ \ / \
6 39 null 70
/
50
grandparent.left = crossNode2; //attach
40
/ \
7 45
/ \ / \
6 39 41 70
/
50
But somehow this code does not work. When I tested:
preorder
45, 39, 70, 50
breadth-first
45, 39, 70, 50
So I think the result is actually:
45
/ \
39 70
/
50
Could anyone give me tips what's wrong with my rotation code?
Step to do a right rotation on node Q:
Let P = Q's left child.
Q's left child = P's right child
P replaces Q as its parent's child
P's right child = Q
You're missing the bolded step in your supplied code. I think your problem is you're treating rotations involving the root node as a special case. Obviously you can't do this if Q is the root and its parent is null. Try creating a "head" node who's right node is the root. This allows rotations involving the root to work using normal algorithms.
public static void rotateRight(Node node) {
assert(!node.isLeaf() && !node.left.isLeaf());
final Node child = node.left;
node.setLeft(child.right);
if (node.isRightChild())
node.parent.setRight(child);
else node.parent.setLeft(child);
child.setRight(node);
}
Node that setRight and setLeft keep the parent reference updated as well as updating right and left. The node.isRightNode() call can be just (node.parent.right == node).
Based on Gunslinger47's answer, I've tested left rotation version too.
The code works fine. (please do let me know if not..)
Also documented on my website :)
http://masatosan.com/btree.jsp
public static void rotateLeft(Node node) {
assert(!node.isLeaf() && !node.right != null);
final Node child = node.right;
node.setRight(child.left);
if(node.isLeftChild()) {
node.parent.setLeft(child);
}
else {
node.parent.setRight(child);
}
chlid.setLeft(node);
}
Related
I'm trying to recursively populate a tree with integers (as shown in the link below). But I don't understand how to solve the inductive step using recursion.
PS. I have already created the recursive function to calculate the binomial coefficient
Thank you in advance!
The math notation in the picture at the link is a little obscure. But you want to implement that almost exactly. It's saying this:
Node buildTree(n) {
Let tree be a new Node (with no children)
For i from 0 to n - 1
Let b = binomial(n, i)
for b times:
Add buildTree(i) as a child of tree
return tree
}
The obscure part is that multiplication by some integer k in this "tree math" means "repeat the graph k times," and the summation means "add all as children" to an implicit parent node. This parent is the value of the expression.
Here's a development hint. Store a unique integer in each node as a label. Once you get that working, then write a little tree walker that prints out DOT language. When I did that for n=3, I got:
graph {
0 -- 1
2 -- 3
0 -- 2
4 -- 5
0 -- 4
6 -- 7
0 -- 6
8 -- 9
10 -- 11
8 -- 10
12 -- 13
8 -- 12
0 -- 8
14 -- 15
16 -- 17
14 -- 16
18 -- 19
14 -- 18
0 -- 14
20 -- 21
22 -- 23
20 -- 22
24 -- 25
20 -- 24
0 -- 20
}
You can see what that looks like by using online GraphViz here.
Pseudocode to illustrate recursive step
TreeNode getRootOfSomeFancyTree(n)
TreeNode root = new TreeNode()
if(n == 1) return root
else for(i = 0; i < n; i++)
//not sure of correct way to multiply an integer by a tree in your application
int x = binomialCoefficient(n, i) * i
//anyway, recurring is easy and safe provided x < n
TreeNode subTree = getRootOfSomeFancyTree(x)
//build the tree
root.addChild(subTree)
endfor return root
I have a binary tree
as a function input I have tree root and 2 nodes
I need to calculate the sum along the path between the two given nodes.
A tree example:
4
/ \
8 13
/ \
24 45
Code:
List<Node> findPath(root, target):
if (root !=null)
return
if root == node{
return nodes.add(target)
}
path = findPath(root.left, target)
if (path !=null){
return nodes.add(root).addAll(path)
}
path = findPath(root.right, target)
if (path!=null)
return nodes.add(root).addAll(path)
I don't know what is the next step if I have paths to target nodes how should I calculate optimal way?
Input: sumTree(4, 24, 45)
Output: 8 + 24 + 45 = 77
Input: sumTree(4, 24, 13)
Output: 13 + 4 + 8 + 24 = 49
Input: sumTree(4, 4, 13)
Output: 4 + 13 = 17
Input: sumTree(4, 45, 45)
Output: 45
Language is JAVA but language doesn't matter unless I understand the syntax
I just want to have optimal solution.
Is it possible to provide some pseudocode?
Your two paths will have the same prefix (at least the root should be there).
You need to remove the common prefix and add only the last (deepest) common node (once). For the parts that are different you need to add all the values. This should be O(N) complexity, and in-line with the rest of the solution.
Your search algorithm is not efficient because you keep copying the values from one list to the other (O(N^2) if you don't have any constraints on the tree). If you modify it to build the response in place it should become O(N).
I understand recursion when it is only called on itself once, and I sort of understand recursion when there is two, as one recursion has to finish first or something before the second can begin.
I am trying to understand the Towers of Hanoi, But what I really don't understand is the order the lines of code are read in when there is two recursions with a print statement.
Could someone break down the order simply? I have created this simple example (where test(3); )
And why does the print statement run?, isn't it invoked on itself immediately?
public static void test(int n){
if(n>0){
test(n-2);
test(n-1);
System.out.println("print " + n);
}
}
I have tried to elaborate it via diagrams. Have a look!
Lat n = 3;
Your code is not an exact implementation of TOH.
Here's the recursion tree and execution order of your code's statements (see it to believe it):
Let n = 4
4
/ \
2 3
/ \ / \
0 1 1 2
/ \ / \ / \
-1 0 -1 0 0 1
/ \
-1 0
test(4)
test(2)
test(0)
test(1)
test(-1)
test(0)
print(1)
print(2)
test(3)
test(1)
test(-1)
test(0)
print(1)
test(2)
test(0)
test(1)
test(-1)
test(0)
print(1)
print(2)
print(3)
print(4)
The function call sequence can be traced by doing a pre-order traversal of the tree. The print statements will be executed for the nodes where node-value is greater than 0, and after both the children of that node have returned.
I'm trying to do a level order traversal on the following BST.
BST bst = new BST();
int [] arr = {12, 15, 7, 3, 81, 9, 36, 23, 33, 41, 4};
for (int i = 0; i <arr.length; i++) {
bst.add(arr[i]);
}
This is my code.
public static void levelOrderTraversal(Node root){
if(root == null) return;
Queue<Node> queue = new ArrayDeque<Node>();
queue.add(root);
while(!queue.isEmpty()){
Node current = queue.peek();
System.out.print(current.getData() + " ");
if (current.left != null)
queue.add(current.left);
if (current.right != null){
queue.add(current.right);
}
queue.poll();
}
}
The output that I get is
12 7 15 3 9 81 4 36 23 41 33
This clearly is not the correct BFS. Where am I going wrong.
Your traversal function is correct. You may want to check this online tool
https://www.cs.usfca.edu/~galles/visualization/BST.html
It provides visualization of the insert, delete and find process as well. This is the resulting tree:
I don't see why, given the list of elements you provide the tree will look like:
12
|- 7 (L)
|- 3 (L)
|- 4 (R)
|- 9 (R)
|- 15 (R)
|- 81 (R)
|- 36 (L)
|- 23 (L)
|- 33 (R)
|- 41 (R)
Or a better visual:
12
/ \
7 15
/ \ \
3 9 81
\ /
4 36
/ \
23 41
\
33
Note this is not a balanced binary search tree. A BST will simply create first a node 12 (first element you provide). And 12 will remain the root. All elements less than are sorted left (and start growing their own roots etc.)
I'm having trouble with swapping nodes between two binary trees.
I'm trying to swap the current node with the passed node in the tree, but I can't figure out how; I can only seem to swap the parents of the nodes, but not the nodes themselves.
Can anyone give me some direction?
public void swap(Node node) {
if(this.equals(this.parent.leftChild)){
Node tempNodeR = node.parent.rightChild;
System.out.println("Is a left child");
node.parent.rightChild = this.parent.leftChild;
this.parent.leftChild = tempNodeR;
}
else{
Node tempNodeL = node.parent.leftChild;
System.out.println("Is a right child");
node.parent.leftChild = this.parent.rightChild;
this.parent.rightChild = tempNodeL;
}
}
Calling node2.swap(node4):
Given Tree:
1 3
/ \
2 4
Resulting Tree (unchanged):
1 3
/ \
2 4
Expected Tree:
1 3
/ \
4 2
For each node, the node has a reference to its parent and the parent has a reference to that child. So if you're going to swap two nodes, you need to update four references.
Tree
1 3
/ \
2 4
So here...
1 has a reference that points to 2 that you want to point to 4.
2 has a reference to 1 that should point to 3.
4 has a reference to 3 that should point to 1.
3 has a reference to 4 that should point to 2.
Hope that helps.