I have made 4 different traversals for my binary search tree. I am stuck at the last one which is the level order traversal and I can't get seem to find out how to do it correctly.
The main problem is that I don't know how to only search one level at a time, I only can figure out how to search either the whole left or whole right subtree.
private void preOrder(BinaryNode<AnyType> t )
{
if(isEmpty()){
System.out.println("Empty");
}
if(t != null) {
System.out.println(t.element);
preOrder(t.left);
preOrder(t.right);
}
}
private void postOrder(BinaryNode<AnyType> t){
if(isEmpty()){
System.out.println("Empty");
}
if (t != null) {
postOrder(t.left);
postOrder(t.right);
System.out.println(t.element);
}
}
private void inOrder(BinaryNode<AnyType> t)
{
if(isEmpty()){
System.out.println("Empty");
}
if (t != null) {
inOrder(t.left);
System.out.println(t.element);
inOrder(t.right);
}
}
private void levelOrder(BinaryNode<AnyType> t, int level)
{
if(isEmpty()){
System.out.println("Empty");
}
if(height(t) == 2) {
System.out.println(t.element);
}else if(height(t) > 1){
levelOrder(t.left, level );
levelOrder(t.right, level );
}
}
This is how I did it.
private void levelOrder(BinaryNode root) {
if (root == null) {
return;
}
Queue<BinaryNode> q = new LinkedList<>();
// Pushing root node into the queue.
q.add(root);
// Executing loop till queue becomes
// empty
while (!q.isEmpty()) {
BinaryNode curr = q.poll();
System.out.print(curr.element + " ");
// Pushing left child current node
if (curr.left != null) {
q.add(curr.left);
}
// Pushing right child current node
if (curr.right != null) {
q.add(curr.right);
}
}
}
Your approach looks like DFS approach It may not follow that approach.
Try to use Queue here it will help you traverse correctly.
Because it will follow BFS approach so that you can traverse level by level.
Add first left node then right node and according follow.
View the entire search as a sequence of "rounds", one "round" for each level.
In each round :
- initialize a "next round" list of nodes to empty
- process a prepared list of nodes (the ones that are at that level and thus to be searched in that round) whereby for each node :
- do the actual comparison
- add all the node's child nodes to the "next round" list
Start the process with a "next round" list populated with just the root node.
Repeat until the list of "next round" nodes comes up empty or you found what you were looking for.
Related
When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}
Iunderstand the basis of a deletion algorithm in a Binary Search tree and have created the following code to delete the largest value from the tree.
public void DelLargest()
{
Node<T> del = this;
boolean child = this.left.empty();
boolean child2 = this.right.empty();
right.DelLargest();
if(child && child2)
this.head = null;
else if(child == true && child2 == false)
this.head = left;
}
Basically what I have is that the recursion runs until 'this' is the rightmost node and then checks two cases, whether 'this' is a leaf, or whether 'this' has a left child. (The other case normally associated with this kind of algorithm is redundant because in finding the node with the largest value, I have gone as right as I can go.) The trouble I am having is getting the current node to then either point to null or to the value at Node left.
Note : This is what my instructor referred to as a "modern" Binary search Tree wherein a vertex or "filled" node and a nil or "empty" node are two subclasses of Interface Node which define the characteristics of each type.
I've managed to narrow the problem down to the fact that I do not have a method that returns a value of a given Node. Working on that now, input would be appreciated.
As suggested in the other answer you should use iterative approach.
In a BST the largest value is the rightmost node.
So do a scan and keep going right until you hit a null.
In the scan keep track of three nodes. (gpnode, pnode, node).
Once the scan is done you will have (gpnode,pnode,null)
Now there are 2 cases.
case 1:
pnode is a leaf. So change the edge (gpnode,pnode) to (gpnode,null)
case 2: (EDITED)
pnode.lChild is not null. Note that pnode.rChild will be null as the search would have terminated at that point.
Now change the edge (gpnode,pnode) to (gpnode,pnode.lChild)
Here is the pseudo code:
public class Node
{
long key;
Node lChild;
Node rChild;
}
public void DelLargest()
{
Node gpnode = null;
Node pnode = null;
Node node = root;
while(node != null) // keep going right until a null is reached
{
gpnode = pnode;
pnode = node;
node = node.rChild;
}
if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = null;
}
else
{
gpnode.rChild = null;
}
}
else // copy lChild's key to this node and delete lChild
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = pnode.lChild;
}
else
{
gpnode.rChild = pnode.lChild;
}
}
}
You've got the right idea. What you want to do is keep a reference to the right most nodes parent, and the right most nodes left child so then when you delete it you can attach the two.
Here's an iterative solution. This will generally be more efficient than recursion, but if you want recursion you should be able to adapt it:
public void delLargest() {
// get rightmost node's parent
Node<T> current = root;
while(current.right != null && current.right.right != null) {
current = current.right;
}
// get the rightmost nodes left node
Node<T> left = current.right.left;
// attach the parent and left
current.right = left;
// nothing points to the right most node anymore, so it will be garbage collected
}
For instance, if I had
A
/ \
B C
/
D
I would want the next addition to be:
A
/ \
B C
/ \
D E
But I'm having a lot of trouble detecting where the next spot for the item to input will be. I have the following code:
public static BinaryTree<String> addToTree(BinaryTree<String> tree, String name) {
if (tree.getLeft() == null) {
BinaryTree<String> newTree = new BinaryTree<String>();
newTree.makeRoot(name);
tree.attachLeft(newTree);
}
else if (tree.getRight() == null) {
BinaryTree<String> newTree = new BinaryTree<String>();
newTree.makeRoot(name);
tree.attachRight(newTree);
}
// Both are non-null
else {
if (tree.getLeft().getLeft() == null || tree.getLeft().getRight() == null) {
tree.attachLeft(addToTree(tree.getLeft(), name));
}
else if (tree.getRight().getLeft() == null || tree.getRight().getRight() == null) {
tree.attachRight(addToTree(tree.getRight(), name));
}
}
return tree;
}
But it will only work for up to a three level tree. If I try to add the fourth, it no longer adds any.
How do I implement it so it will figure out where the next item is null, and then add it there?
I also thought of having a checkNullity() method, wherein I'd take a tree, and check if its children were null, but I was also having trouble figuring out how to get the children's children. I wanted to find where it was null and then add it there.
Could anyone offer some input?
You can modify breadth first traversal to accomplish this I think. When you pop up the items from the queue, check if any of the children is empty. The first empty child slot is the place you want to add to.
addNode(root, newNode)
q = empty queue
q.enqueue(root)
while not q.empty do
node := q.dequeue()
if node.left == null
//create new node as nodes left child
return
q.enqueue(node.left)
if node.right == null
//create new node as nodes right child
return
q.enqueue(node.right)
Since, you want to insert the element in the order from left to right and starting from the same level. I would suggest you to look in to Breath First Search. I have provided an basic implementation.
public void insert(child, root){
if (root == null){
root = child
}
Node iter = root
Myqueue q = new Myqueue(); //Implementation of the Java Queue Interface
while (iter!=null){
//Check: If the left node exists, enque in the que
if(iter.is_left()){
q.insert(iter.left)
}
else{
iter.left = child
iter = null
}
//Similary for the right
if(iter.is_right()){
q.insert(iter.right)
}
else{
iter.right = child
iter = null
}
if (iter != null){
iter = q.poll() //Retreiving the head of the queue
}
}
}
You could enumerate all nodes while adding them to the tree. If you want to add the n-th node to the tree, it'll be a child of the n/2-th node: left if n%2 == 0 and right if n%2 == 1.
This certainly creates the tree you are asking for although I am still not sure it is what you want:
public class BinaryTree<T> {
T root = null;
BinaryTree<T> left = null;
BinaryTree<T> right = null;
public BinaryTree<T> getLeft() {
return left;
}
public BinaryTree<T> getRight() {
return right;
}
public void makeRoot(T root) {
this.root = root;
}
public void attachLeft(BinaryTree<T> tree) {
left = tree;
}
public void attachRight(BinaryTree<T> tree) {
right = tree;
}
public static BinaryTree<String> addToTree(BinaryTree<String> tree, String name) {
if (tree.getLeft() == null) {
BinaryTree<String> newTree = new BinaryTree<String>();
newTree.makeRoot(name);
tree.attachLeft(newTree);
} else if (tree.getRight() == null) {
BinaryTree<String> newTree = new BinaryTree<String>();
newTree.makeRoot(name);
tree.attachRight(newTree);
} else {
addToTree(tree.getLeft(), name);
}
return tree;
}
public static void main(String[] args) {
try {
BinaryTree<String> tree = new BinaryTree<String>();
String add = "ABCDEFG";
tree.makeRoot(add.substring(0, 1));
for (int i = 1; i < add.length(); i++) {
addToTree(tree, add.substring(i, i + 1));
}
System.out.println("Done");
} catch (Throwable e) {
e.printStackTrace();
}
}
}
Added
I have clearly misunderstood the question. Perhaps an example will help.
If I added one character at a time (as strings) from the following string what would you expect?
"ABCDEFG"
A
/ \
B C
/ \ | \
D E F G?
or something else.
What would you then expect from
"ADEFGBC"
A
/ \
D E
/ \ | \
F G B C
or
A
/ \
B C
/ \ | \
D E F G
or something else?
Either is possible but I cannot see any value in either case.
In order to add an element to a proper place in a binary tree, you have to go from the root at at each node answer the following question: Should I descend to the left or to the right subtree? This is what your problem boils down to - how to make this decision at each node.
You start is OK. If the node has no left subtree, then the newly added leaf should be its left child. And if the node has a left subtree but no right subtree, then the newly added leaf should be its right child.
But how to decide if the node has both subtrees? For this you'll need to keep some sort of information at the nodes that you can use to decide. One possibility is to keep at each node the total size of its subtree. Then if both subtrees have the same size, it means both are perfectly balanced and so you add to the left. Otherwise, if the left subtree has size 2^n-1 it means that it's balanced (and the right one is not) so you add to the right. If not, add to the left.
However, you can do much simpler than that. Since your trees always keep this structure, you can represent a tree as an ArrayList. The root node is at index 0 and for a node at index n its children are at indexes _2*n+1_ and _2*n+2_. This is just how binary heaps are implemented. This way, you'll get O(1) time complexity for adding a new node - simply append it at the end of the list. (However, if you need some classical tree operations like rotations, this implementation won't work.)
Right now I have
private static void iterateall(BinaryTree foo) {
if(foo!= null){
System.out.println(foo.node);
iterateall(foo.left);
iterateall(foo.right);
}
}
Can you change it to Iteration instead of a recursion?
What you're looking for is a successor algorithm.
Here's how it can be defined:
First rule: The first node in the tree is the leftmost node in the tree.
Next rule: The successor of a node is:
Next-R rule: If it has a right subtree, the leftmost node in the right subtree.
Next-U rule: Otherwise, traverse up the tree
If you make a right turn (i.e. this node was a left child), then that parent node is the successor
If you make a left turn (i.e. this node was a right child), continue going up.
If you can't go up anymore, then there's no successor
As you can see, for this to work, you need a parent node pointer.
Example:
First rule: The first node in the tree is the leftmost node in the tree: (1)
Next-U rule: Since (1) has no right subtree, we go up to (3). This is a right turn, so (3) is next.
Next-R rule: Since (3) has a right subtree, the leftmost node in that subtree is next: (4).
Next-U rule: Since (4) has no right subtree, we go up to (6). This is a right turn, so next is (6).
Next-R rule: Since (6) has a right subtree, the leftmost node in that subtree is next: (7).
Next-U rule: Since (7) has no right subtree, we go up to (6). This is a left turn, so we continue going up to (3). This is a left turn, so we continue going up to (8). This is a right turn, so next is (8).
Next-R rule: Since (8) has a right subtree, the leftmost node in that subtree is next: (10).
Next-R rule: Since (10) has a right subtree, the leftmost node in that subtree is next: (13).
Next-U rule: Since (13) has no right subtree, we go up to (14). This is a right turn, so next is (14).
Next-U rule: Since (14) has no right subtree, we go up to (10). This is a left turn, so we continue going up to (8). This is a left turn, so we want to continue going up, but since (8) has no parent, we've reached the end. (14) has no successor.
Pseudocode
Node getLeftMost(Node n)
WHILE (n.leftChild != NULL)
n = n.leftChild
RETURN n
Node getFirst(Tree t)
IF (t.root == NULL) RETURN NULL
ELSE
RETURN getLeftMost(t.root);
Node getNext(Node n)
IF (n.rightChild != NULL)
RETURN getLeftMost(n.rightChild)
ELSE
WHILE (n.parent != NULL AND n == n.parent.rightChild)
n = n.parent;
RETURN n.parent;
PROCEDURE iterateOver(Tree t)
Node n = getFirst(t);
WHILE n != NULL
visit(n)
n = getNext(n)
Java code
Here's a simple implementation of the above algorithm:
public class SuccessorIteration {
static class Node {
final Node left;
final Node right;
final int key;
Node parent;
Node(int key, Node left, Node right) {
this.key = key;
this.left = left;
this.right = right;
if (left != null) left.parent = this;
if (right != null) right.parent = this;
}
Node getLeftMost() {
Node n = this;
while (n.left != null) {
n = n.left;
}
return n;
}
Node getNext() {
if (right != null) {
return right.getLeftMost();
} else {
Node n = this;
while (n.parent != null && n == n.parent.right) {
n = n.parent;
}
return n.parent;
}
}
}
}
Then you can have a test harness like this:
static Node C(int key, Node left, Node right) {
return new Node(key, left, right);
}
static Node X(int key) { return C(key, null, null); }
static Node L(int key, Node left) { return C(key, left, null); }
static Node R(int key, Node right) { return C(key, null, right); }
public static void main(String[] args) {
Node n =
C(8,
C(3,
X(1),
C(6,
X(4),
X(7)
)
),
R(10,
L(14,
X(13)
)
)
);
Node current = n.getLeftMost();
while (current != null) {
System.out.print(current.key + " ");
current = current.getNext();
}
}
This prints:
1 3 4 6 7 8 10 13 14
See also
Complete Java listing and output on ideone.com
Can you change it to Iteration instead of a recursion?
You can, using an explicit stack. Pseudocode:
private static void iterateall(BinaryTree foo) {
Stack<BinaryTree> nodes = new Stack<BinaryTree>();
nodes.push(foo);
while (!nodes.isEmpty()) {
BinaryTree node = nodes.pop();
if (node == null)
continue;
System.out.println(node.node);
nodes.push(node.right);
nodes.push(node.left);
}
}
But this isn’t really superior to the recursive code (except for the missing base condition in your code).
Sure, you have two general algorithms, depth first search and breadth first search.
If order of traversal is not important to you, go for breadth first, it's easier to implement for iteration. You're algorithm should look something like this.
LinkedList queue = new LinkedList();
queue.add(root);
while (!queue.isEmpty()){
Object element = queue.remove();
queue.add(element.left);
queue.add(element.right);
// Do your processing with element;
}
As with every recursion, you can use additional data structure - i.e. the stack.
A sketch of the solution:
private static void visitall(BinaryTree foo) {
Stack<BinaryTree> iterationStack = new Stack<BinaryTree>();
iterationStack.push(foo);
while (!iterationStack.isEmpty()) {
BinaryTree current = iterationStack.pop();
System.out.println(current.node);
current.push(current.right); // NOTE! The right one comes first
current.push(current.left);
}
}
I had a tree (not binary) and eventually solved it with this very simple algorithm. The other solutions used left and right that were not relevant or even implemented in the examples.
My structure was: nodes with each parent containing list of children, and each child containing a pointer back to the parent. Pretty common...
After a bunch of refactoring, I came up with the following example using Kotlin. It should be trivial to convert to your language of choice.
Helper Functions
First, the node must provide 2 simple functions. This will vary depending on your Node class' implementation:
leftMost - This is the first child node. If that node has children, it's first child, etc. If no children, return this.
fun leftMost(): Node {
if (children.isEmpty()) {
return this
}
var n = this
while (n.children.isNotEmpty()) {
n = n.children[0]
}
return n
}
nextSibling - The next sibling of this node, or NULL
fun nextSibling(): Node? {
if (parent == null) return null
val siblingIndex = parent.children.indexOf(this) + 1
return if (siblingIndex < parent.children.size) {
parent.children[siblingIndex]
} else {
null
}
}
The Iteration
The iteration starts with the leftMost of the root.
Then inspect the next sibling.
If NOT NULL the sibling's leftMostChild
If NULL, the parent, and if the parent is NULL, we are done.
That's it.
Here is a Kotlin iterator function.
fun iterator(): Iterator<Node> {
var next: Node? = this.leftMost()
return object : Iterator<Node> {
override fun hasNext(): Boolean {
return next != null
}
override fun next(): Node {
val ret = next ?: throw NoSuchElementException()
next = ret.nextSibling()?.leftMost() ?: ret.parent
return ret
}
}
}
Here is the same next() function, but without the Kotlin shorthand for dealing with NULL values, for those that are not hip to the syntax.
fun next(): Node {
val ret = next
if (ret == null) throw NoSuchElementException()
val nextSibling = ret.nextSibling()
if (nextSibling != null) {
next = nextSibling.leftMost()
}
else {
next = ret.parent
}
return ret
}
Yes, you can change it to iteration instead of a recursion, but then it gets much more complicated, since you need to have some way to remember where to go back from the current node. In the recursive case, the Java call stack handles that, but in an iterative solution you need to build your own stack, or perhaps store back pointers in the nodes.
I am trying to write a remove(node cRoot, Object o) function for a sorted binary tree.
Here is what I have so far:
private boolean remove(Node cRoot, Object o) {
if (cRoot == null) {
return false;
}
else if (cRoot.item.equals(o)) {
//erase node fix tree
return true;
}
else if (((Comparable)item).compareTo(cRoot.item)<=0){
return remove(cRoot.lChild, o);
}
else {
return remove(cRoot.rChild,o);
}
}
It does not work correctly. To delete a node you have to repair the tree to fix the hole. How should this be done?
There are generally two ways of performing a remove on the tree:
First method:
Remove the node, then replace it with either child. Then, resort the tree by doing parent-child swapping until the tree is once again sorted.
The second method:
Traverse the tree to find the next (highest or lowest) value that belongs as the root*, if it is a leaf node, swap that with the root, then trim off the value you want to remove. If it is an internal node, you will have to recursively call remove on that node. Repeat until a leaf node is removed.
*What I mean is, if you convert your BST into a sorted list, then you will want to pick either value to the left or right of the root as the new root. I.e. leftmost child of the right subtree, or right most child of the left subtree.
The basic pseudo-code for erasing a node from a sorted tree is pretty simple:
erase the node value
find child node with maximum value
make it the root node
if it had children - goto 2 recursively
Basically what you are doing is bubbling nodes up the tree, each time the maximum of the children node in each node, so that in the end you stay with a sorted tree, and only one node missing at the end of the full path you went.
Also - see wikipedia on the subject, they have some sample code in C as well.
In the simple case3 you can use next algorithm:
if(removed node had left child)
{
place left child instead of removed node;
most_right = most right leaf in the left subtree;
move right child of removed node as right child of most_right;
}
else
{
place right child instead of removed node
}
In more complicated case you may need to rebalance your tree (see AVL trees, http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html for C++ example)
leaf-delete node
1-child Promote the subtree
2-child case replace the node with either
in order successor or predecessor
left most of the right subtree or
right most of the left subtree
I found this code on Habrahabr. I've just added comments.
public void remove (T1 k){
Node<T1,T2> x = root, y = null;
// from while to if(x == null) - searching for key
while(x != null){
int cmp = k.compareTo(x.key);
if(cmp == 0){
break; // quit cycle if key element is found
} else {
y = x;
if(cmp < 0){
x = x.left;
} else {
x = x.right;
}
}
}
if(x == null) return; // if key is not found or tree is empty
if(x.right == null){ // if element found has not right child
if(y == null){ // if element found is root & has not right child
root = x.left;
} else { // if element found is not root & has not right child
if(x == y.left) y.left = x.left;
else y.right = x.left;
}
} else { // element found has right child, so search for most left of rights
Node<T1,T2> mostLeft = x.right;
y = null;
while(mostLeft.left != null) {
y = mostLeft;
mostLeft = mostLeft.left;
}
if(y == null){ // if right child of element found has not left child
x.right = mostLeft.right;
} else { // if right child of element found has left child
y.left = mostLeft.right;
}
x.key = mostLeft.key;
x.value = mostLeft.value;
}
}