I am trying to write a binary tree and the add method is continually overwriting the root of the tree. I have two methods a recursive add method that takes in a String and a Node and then a regular add method that simply calls the recursive method. Any help would be greatly appreciated.
public Node recAdd(String event , Node tNode ){
//tNode -> tree node
if (tNode == null){
// Addition place found
root = new Node(event);
System.out.println("added root");
}
else if (tNode.event.compareTo(event) <= 0){
tNode.setLeft(recAdd(event, tNode.getLeft()));
// System.out.println("added left");// Add in left subtree
}
else{
tNode.setRight(recAdd(event, tNode.getRight()));
// System.out.println("added right");
}// Add in right subtree
return tNode;
}
//////////////////////////////////////////////
public void add(String event){
if(root != null){
System.out.println("The root currently is " + root.event );
}
recAdd(event , root);
}
And my node class is as follows
public class Node {
Node left;
Node right;
String event;
Node(String event){
this.event = event;
this.left = null;
this.right = null;
}
public void setEvent(String event){
this.event = event;
}
public void setLeft(Node left){
this.left = left;
}
public void setRight(Node right){
this.right = right;
}
public String getEvent(){
return event;
}
public Node getLeft(){
return left;
}
public Node getRight(){
return right;
}
}
You are replacing the root node whenever you find a spot to insert the current node:
public Node recAdd(String event, Node tNode) {
//tNode -> tree node
if (tNode == null) {
// Addition place found
root = new Node(event); // Problem is RIGHT HERE
System.out.println("added root");
}
//...
}
What's happening is that you recursively search through the tree until you reach a node that hasn't been assigned yet (i.e., it is null). At this point, you are overwriting root rather than creating the new node.
For example:
root
/ \
node null <- You want to assign this node, not overwrite root
/ \
null null
To do this:
public Node recAdd(String event , Node tNode ){
if (tNode == null){
tNode = new Node(event); // <--- Don't overwrite root
}
else if (tNode.event.compareTo(event) <= 0){
tNode.setLeft(recAdd(event, tNode.getLeft()));
}
else{
tNode.setRight(recAdd(event, tNode.getRight()));
}
return tNode;
}
You would also need to modify your add() function:
public void add(String event){
root = recAdd(event , root); // <-----Reassign root
}
Related
I have a simple Node class to construct a tree node in my binary tree:
class Node {
int data;
Node left;
Node right;
public Node(int i) {
this.data = i;
}
}
I've written a simple Tree class which will use the Node structure to build a tree:
class Tree {
Node root;
}
I'm trying to write a recursive function mirror() in my Tree class that will return a mirrored version of the tree (left and right nodes swapped).
So if I call this function on a Tree t, I would expect to start from the root, and swap all of the nodes until we reach a node that has no more children to swap. The part I'm struggling with is after we've swapped the root nodes children, how I can recursively call the mirror function on these nodes and then return the mirrored tree.
As you can see, the code below will swap the root node's children, but after that I am stuck as I can't call the mirror function on nodes, only a tree.
public Tree mirror() {
Node temp = this.root.left;
this.root.left = this.root.right;
this.root.right = temp;
If you could point me in the right direction I'd appreciate it.
You need a separate method that will accept Node object, mirror its children and call itself recursively.
public Tree mirror() {
mirrorInternal(this.root);
return this;
}
private void mirrorInternal(Node node) {
Node tmp = node.left;
node.left = node.right;
node.right = tmp;
if (node.left != null) {
mirrorInternal(node.left);
}
if (node.right != null) {
mirrorInternal(node.right);
}
}
I guess you could also change your Node-class such that it uses a flag for mirrored behavior:
class Node {
int data;
Node[] children;
public Node(int i) {
this.data = i;
this.children = new Node[2];
}
public void setLeft(Node node) {
children[0] = node;
}
public void setRight(Node node) {
children[1] = node;
}
public Node getLeft(boolean mirrored) {
return mirrored ? children[1] : children[0];
}
public Node getRight(boolean mirrored) {
return mirrored ? children[0] : children[1];
}
}
void mirror (Tree tree) {
mirror (tree.root);
}
Node mirror (Node node) {
if (node != null) {
Node temp = node.left;
node.left = mirror (node.right);
node.right = mirror (temp);
}
return node;
}
I've got a class Node
class Node{
int val;
Node parent;
Node left;
Node right;
public Node (int val){
this.val = val;
}
}
And I have a few methods:
public class Tree{
public Node root = null;
void insertNodeSorted(Node x, Node tree) {
if (x.val < tree.val) {
if (tree.left == null) {
tree.left = x;
}
else
insertNodeSorted(x, tree.left);
}
else {
if (tree.right == null) {
tree.right = x;
}
else
insertNodeSorted(x, tree.right);
}
} // end insertNodeSorted
void deleteNodeSorted(Node x) {
if (root == null)
return;
else
root = deleteNodeSorted(x, root);
}
Node deleteNodeSorted(Node x, Node tree) {
if (x.val < tree.val)
tree.left = deleteNodeSorted(x, tree.left);
else if (x.val > tree.val)
tree.right = deleteNodeSorted(x, tree.right);
else
tree = replaceNodeSorted(tree);
return tree;
} // end deleteNodeSorted
// Additional Method
Node replaceNodeSorted(Node tree) {
if (tree.right == null)
tree = tree.left;
else if (tree.left == null)
tree = tree.right;
else
tree.right = findReplacement(tree.right, tree);
return tree;
} // end replaceNodeSorted
Node findReplacement(Node tree, Node replace) {
if (tree.left != null)
tree.left = findReplacement(tree.left, replace);
else {
replace.val = tree.val;
tree = tree.right;
}
return tree;
} // end findReplacement
And I'd like to compile the Tree, but I don't know what I exactly I need to write in the main method.
public static void main(String[] args){
Tree t = new Tree();
t.insertNodeSorted();
What do I have to write in the brackets in order to print the Tree? (I know I still have to add System.out.println(val); in the methods..)
You defined a variable holding the root node, so it is not necessary to pass the parameter tree for the method insertNodeSorted. You can use always the root node.
Add a method taking only one parameter.
public void insertNodeSorted(Node x) {
if (root == null) {
root = x;
return;
}
insertNodeSorted(x, root);
}
Define the other method with two parameters as private
private void insertNodeSorted(Node x, Node tree) {
...
}
Now you can insert elements as follow:
Tree t = new Tree();
t.insertNodeSorted(new Node(1));
t.insertNodeSorted(new Node(134));
t.insertNodeSorted(new Node(13));
t.insertNodeSorted(new Node(4));
...
//
// BinTree class
//
// this class implements a binary tree
//
// the tree is unbounded. fields are
// info: the value stored in the node (generic type)
// left: pointer to the left subtree
// right: pointer to the right subtree
// parent: pointer to the parent
// preOrderQueue: queue of nodes for preorder traversal
// left, right, and parent are public to allow the client // code to manipulate the tree as needed
//
// methods:
// constructor to create empty tree
// constructor to create tree with one node
// constructor to create tree given the root value, and
// pointers to the left and right subtrees
// get and set methods for the info field
// isEmpty
// attachLeft: if there is no left child, attach the given tree as
// the new left child; otherwisethrowTreeViolationException
// attachRight: if there is no right child, attach the given tree as the // new right child; otherwise throw TreeViolationException
// detachLeft: detach and return the left child
// detachRight: detach and return the right child
// root: return the root of the tree
public class BinTree<T> implements BinTreeInterface<T> {
protected T info;
public BinTree<T> left;
public BinTree<T> right;
public BinTree<T> parent;
private LinkedUnbndQueue<T> preOrderQueue;
// create an empty tree
public BinTree() {
info = null;
left = null;
right = null;
parent = null;
}
// create a tree with one node
public BinTree(T item) {
info = item;
right = null; //idk
left = null; //idk
}
// create a tree where the root contains item
// link the left and right subtrees to the root
// don't forget to set the parent pointers
public BinTree(T item, BinTree<T> ltree, BinTree<T> rtree) {
info = item;
right = rtree;
left = ltree;
ltree = null;
rtree = null;
}
// return the info field
public T getInfo() {
return info;
}
// set the info field
public void setInfo(T newitem) {
info = newitem;
}
// attach the parm as the left child of the current node
// throw TreeViolationException if the current node already has a left child
public void attachLeft(BinTree<T> tree) {
if (this.left != null)
throw new TreeViolationException("Current node already has a left child");
else
this.left = tree;
}
// attach the parm as the right child of the current node
// throw TreeViolationException if the current node already has a right child
public void attachRight(BinTree<T> tree) {
if (this.right != null)
throw new TreeViolationException("Current node already has a right child");
else
this.right = tree;
}
// detach the left child and return it
public BinTree<T> detachLeft() {
return this.left;
}
// detach the right child and return it
public BinTree<T> detachRight() {
return this.right;
}
I think my BinTree method is wrong. I dont understand where I am making mistake.
public BinTree<T> root() {
if (this.parent == null)
return this;
else
return this.root();
/// return parent;
}
// Initializes preOrderQueue with tree elements in preOrder order.
public void preOrder(BinTree<T> tree) {
if (tree != null) {
preOrderQueue.enqueue(tree.getInfo());
preOrder(tree.left);
preOrder(tree.right);
}
}
// calls preorder to create queue of nodes in the tree
public void reset() {
preOrderQueue = new LinkedUnbndQueue<T>();
preOrder(this);
}
// removes and returns the next node in the preorder queue
// returns null if the queue is empty
public T getNext() {
if (preOrderQueue.isEmpty())
return null;
else
return preOrderQueue.dequeue();
}
}
Here is my driver code.
// When I compile fr preorder it only prints out 75 and below bcz at tht time the current node is 75. why is it not traversing 25 and 50?
public class useTree {
public static void main(String[] args) {
Integer num;
BinTree<Integer> mytree = new BinTree<Integer>(25);
BinTree<Integer> subtree = new BinTree<Integer>(50);
mytree.attachLeft(subtree);
subtree = new BinTree<Integer>(75);
mytree.attachRight(subtree);
// subtree = new BinTree<Integer>(10);
// mytree.attachRight(subtree);
// 25
// / \
// 50 75
subtree = new BinTree<Integer>(10);
subtree.attachRight(new BinTree<Integer>(100));
subtree.attachLeft(new BinTree<Integer>(200));
mytree = mytree.right;
mytree.attachLeft(subtree);
// 25
// / \
// 50 75
// /
// 10
// / \
// 200 100
mytree = mytree.root();
System.out.println("\npreorder traversal:");
mytree.reset();
num = mytree.getNext();
while (num != null) {
System.out.println(num);
num = mytree.getNext();
}
}
}
public BinTree root() {
if (this.parent == null)
return this;
else
return this.root();
/// return parent;
}
Should be:
public BinTree root() {
if (this.parent == null)
return this;
else
return this.parent.root();
}
This uses recursion, which is less than optimal, but it is at least correct.
Also:
private LinkedUnbndQueue<T> preOrderQueue;
Each node of the tree has its own queue? That's not right. If you really want to generate a queue, pass the queue object to the relevant method. And, why does the preOrder method need a tree argument - it's not a static method; "this" serves as an implicit argument.
public void preOrder(LinkedUnbndQueue<T> preOrderQueue) {
preOrderQueue.enqueue(this.getInfo());
if (left != null) left.preOrder(preOrderQueue);
if (right != null) right.preOrder(preOrderQueue);
}
Also, attachLeft and attachRight methods needs to set the parent field of the attached subtree.
More generally, your BinTree is both a node and a tree. That can work but some operations don't really make sense on a per-node basis (in particular the custom iteration that you have defined should be moved out, since as I noted, it doesn't make much sense to have a queue per node).
Frankly, there are enough problems with this code that you need a better approach to your development practice. Consider learning to use a debugger.
public BinTree root() {
if (parent == null) return null;
BinTree tmp = parent;
while (tmp.parent != null) {
tmp = tmp.parent;
}
return tmp;
}
You should create a separate class naming BinNode or something. Tree and Node are separate things and the class you created is confusing and doesn't make sense.
Also, you are not assigning the parent variable anywhere.
public void attachRight(BinTree<T> tree) {
if (this.right != null)
throw new TreeViolationException("Current node already has a right child");
else {
this.right = tree;
tree.parent = this;
}
}
Assign the parent of the child branches appropriately. Moreover, your detach methods are wrong too. You are simply returning the right/left branches but you are supposed to detach/remove them first.
BinTree branch = this.right; // or left
this.right = null;
return branch;
I am currently implementing a Binary Search Tree and I am wondering, why my delete() method doesn't work...
My findMin() method does work, I have tested it out so far.
I type in a key, which doesn't exist in the three and I get the right exception, but whenever I type in a key, which is existing, it just doesn't remove the node from the three...
So here is my code so far:
import java.util.NoSuchElementException;
public class Bst {
Node root;
Node head;
Node tail;
public Bst(){
root = null;
}
public void insert (Node root, int key){
Node newNode=new Node(key);
if(root==null){
root=newNode;
}
if(key<=root.getKey()){
if (root.getLeft()!=null){
insert(root.getLeft(), key);
}
else{
root.setLeft(newNode);
}
}
if (key>=root.getKey()){
if (root.getRight()!=null){
insert(root.getRight(),key);
}
else{
root.setRight(newNode);
}
}
}
public void printTree(Node root){
if (root==null) return;
printTree(root.getLeft());
System.out.print(root.getKey() + " ");
printTree(root.getRight());
}
public Node treeToCDLL(Node root){
if (root == null){
return null;
}
Node leftTree=treeToCDLL(root.getLeft());
Node rightTree=treeToCDLL(root.getRight());
if (leftTree == null){
head=root;
}
else {
head=leftTree;
leftTree.getLeft().setRight(root);
root.setLeft(leftTree.getLeft());
}
if (rightTree==null){
head.setLeft(root);
root.setRight(head);
tail=root;
}
else{
tail=rightTree.getLeft();
head.setLeft(tail);
tail.setRight(head);
root.setRight(rightTree);
rightTree.setLeft(root);
}
return head;
}
public boolean find(Node root, int key){
Node current=root;
while(current!=null){
if(current.getKey()==key){
return true;
}
else if(current.getKey()>key){
current=current.getLeft();
}
else
current=current.getRight();
}
return false;
}
public void printList(Node head){
Node current = head;
while(current!=null){
System.out.print(current.getKey() + " ");
current=current.getRight();
if(current==head) break;
}
}
public Node findMin(Node root){
Node current=root;
if(root==null) return null;
else{
if(current.getLeft()!=null){
return findMin(current.getLeft());
}
}
return current;
}
public void delete(Node root, int key){
Node current=root;
if(root==null){
throw new NoSuchElementException("baum ist leer");
}
else{
if(current.getKey()>key){
delete(current.getLeft(), key);
}
else if(current.getKey()<key){
delete(current.getRight(),key);
}
else{
if(current.getLeft()==null && root.getRight()==null){
current=null;
}
else if(current.getLeft()==null){
Node tmp=current;
current=current.getRight();
tmp=null;
}
else if(current.getRight()==null){
Node tmp=current;
current=current.getLeft();
tmp=null;
}
else {
Node min=findMin(current.getRight());
Node tmp=current;
current=min;
tmp=null;
}
}
}
}
public static void main (String[]args){
Bst bst=new Bst();
Node root=new Node(4);
bst.insert(root, 2);
bst.insert(root, 10);
bst.insert(root, 3);
bst.insert(root, 5);
bst.insert(root, 6);
bst.insert(root, 0);
bst.delete(root, 2);
System.out.print("in-order traversal: ");
bst.printTree(root);
System.out.println();
System.out.print("Der gesuchte Knoten : " + bst.find(root,7));
System.out.println();
System.out.print("der kleinste Knoten : " + bst.findMin(root));
System.out.println();
System.out.print("circular doubly linked list: ");
Node head= bst.treeToCDLL(root);
bst.printList(head);
}
}
Node class:
public class Node {
private Node left;
private Node right;
private int key;
public Node(int key){
this.key=key;
left = null;
right = null;
}
public void setLeft(Node left){
this.left=left;
}
public Node getLeft(){
return left;
}
public void setRight(Node right){
this.right=right;
}
public Node getRight(){
return right;
}
public int getKey(){
return key;
}
}
I would be glad if someone could help me...
I tried out to find a solution the whole day, but it seems like I won't find it on my own
Here, by doing this current=min you are not changing node in tree, but simply replacing a local pointer (current).
Either rewrite values of this node by setters, of get update getLeft on parent of the node.
else {
Node min=findMin(current.getRight());
Node tmp=current;
current=min;
tmp=null;
}
In the last else part of the delete() method, you are just simply assigning null values that doesn't mean the references would point to the null value.
e.g When the matched node is a leaf node, you are simply assigning null value to the current variable. You should assign nullvalue to the left/right of current's parent. Assuming parent is the parent node of current node.
if(current.getLeft()==null && root.getRight()==null){
if(current == parent.getLeft()) {
parent.left=null;
} else {
parent.right == null;
}
}
These is same problem with other subsequent else blocks.
else if(current.getLeft()==null){
if(current == parent.left) {
parent.left= current.getRight();
} else {
parent.right = current.getRight();
}
}
else if(current.getRight()==null){
if(current == parent.left) {
parent.left= current.getLeft();
} else {
parent.right = current.getLeft();
}
}
You need to keep track of the parent node while traversing the tree.
Suppose I have a node in a tree, how can I get all leaf nodes whose ancestor is this node?
I have defined the TreeNode like this:
public class TreeNode<T>
{
/** all children of the node */
private List<TreeNode<T>> children = new ArrayList<TreeNode<T>>();
/** the parent of the node, if the node is root, parent = null */
private TreeNode<T> parent = null;
/** the stored data of the node */
private T data = null;
/** the method I want to implement */
public Set<TreeNode<T>> getAllLeafNodes()
{
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
return leafNodes;
}
}
Use recursion.
if the node itself is a leaf, return it
otherwise, return all the leaf-nodes of its children
Something like this (not tested):
public Set<TreeNode<T>> getAllLeafNodes() {
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
if (this.children.isEmpty()) {
leafNodes.add(this);
} else {
for (TreeNode<T> child : this.children) {
leafNodes.addAll(child.getAllLeafNodes());
}
}
return leafNodes;
}
Create a stack and push root node.
Stack<Node> st = new Stack<>();
st.push(root);
CL(st.peek());
Call the recursive method.
public void CL(Node root){
if (st.peek().left == null && st.peek().right == null ) {//if leaf node
System.out.println(st.peek().data);//print
st.pop();
return;
}
else{
if(st.peek().left != null){
st.add(st.peek().left);
CL(st.peek());
}
if(st.peek().right != null){
st.add(st.peek().right);
CL(st.peek());
}
}
st.pop();
}