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.
Related
I created this binary search tree. I wrote the insert method in 2 forms using loop and recursion. The recursion code although seems correct but does not work and I cannot figure out what the problem is. When I create the tree using insertRecursion method, the leftChild and rightChild always are null.
public class BinarySearchTree {
private class Node{
private int value;
private Node leftChild;
private Node rightChild;
public Node(int value){
this.value=value;
}
public String toString(){
return ""+this.value;
}
}
private Node root;
public BinarySearchTree(int value){
root=new Node(value);
}
public void insertRecursion(int value){
Node current=root;
insertRecursionForm(current,value);
}
private Node insertRecursionForm(Node root, int value){
if(root==null){
root=new Node(value);
return root;
}
if(value<root.value){
return insertRecursionForm(root.leftChild,value);
}else{
return insertRecursionForm(root.rightChild,value);
}
}
public void insert(int value){
Node current=root;
while(true) {
if (value < current.value) {
if (current.leftChild == null) {
current.leftChild= new Node(value);
break;
}else{
current=current.leftChild;
}
}else if(value>current.value) {
if (current.rightChild == null) {
current.rightChild= new Node(value);
break;
}else{
current=current.rightChild;
}
}
}
}
}
Try it like this:
private Node insertRecursionForm(Node root, int value){
if(root==null){
root=new Node(value);
return root;
}
if(value<root.value)
{
root.leftChild = insertRecursionForm(root.leftChild,value);
}else
{
root.rightChild = insertRecursionForm(root.rightChild,value);
}
return root;
}
The problem with your previous code was that you only returned the value of the last inserted node. This is why you always had the left and right node be null.
I am trying this code to populate the BST and then print it in the InOrder traversal format. But the root node is not getting populated compiling wihtout any error and Output is : "root is empty", so how to correct this code so that my BST gets populated in the Node root.
I tried to make Node root as static I thought it might be the case that root node might not be accessible from each method but it is not working, tried to change the name of the Node but it is also not working.
import java.util.*;
import java.io.*;
import java.lang.*;
class Node{
int data; Node left; Node right;
public Node(int data) {
this.data = data;
left = null;
right = null;
}
}
public class insert_tree {
static Node root;
insert_tree() //constructor
{
root = null;
}
public void addNode(int value) { // public method is called by the object and this public method calls the private method in which the root is also passed.
root = add(root, value);
}
private Node add(Node node, int value) {
if(node == null) {
return node;
}
if(value < node.data) {
node.left = add(node.left, value);
}
else if(value > node.data) {
node.right = add(node.right, value);
}
else {
return node;
}
return node;
}
private void inOrder(Node node) {
// node = root;
if(node != null) {
inOrder(node.left);
System.out.print(node.data + " ");
inOrder(node.right);
}
else {
System.out.print("root is empty");
}
//return null;
}
public void inorder() {
inOrder(root);
}
private void printRoot(Node root) {
System.out.println(root.data);
}
public void print() {
printRoot(root);
}
public static void main(String args[]) {
insert_tree obj = new insert_tree();
obj.addNode(20);
obj.addNode(14);
obj.addNode(25);
obj.addNode(10);
obj.addNode(16);
obj.addNode(25);
obj.addNode(21);
obj.addNode(30);
//printing the tree
obj.inorder();
}
}
The output should be the inorder traversal of the tree.
public void addNode(int value) { // public method is called by the object and this public method calls the private method in which the root is also passed.
root = add(root, value);
}
private Node add(Node node, int value) {
if(node == null) {
node = new Node(value);
}
else if(value == node.data) {
node.data = value;
}
else if(value < node.data) {
node.left = add(node.left, value);
}
else {
node.right = add(node.right, value);
}
return node;
}
How can I remove all the evens in a linked list in java? Other similar questions did not help me. I have a possible solution, but it seems too complicated. I'm not sure it even works.
public class Node {
public int value;
public Node next;
public Node (int val) {
value = val;
}
public Node removeNode (Node root) {
if (root == null || (root.next == null && isOdd(root.value))) {
return null;
}
Node deep = root;
while (deep.next != null) {
deep = deep.next;
}
if (isOdd(deep.value)) {
for (Node x = root; x != null; x = x.next) {
if (isOdd(x.next.value)) {
x.next = x.next.next;
}
}
} else {
for (Node x = root; x.next != null; x = x.next) {
if (isOdd(x.next.value)) {
x.next = x.next.next;
}
}
}
if (isOdd(root.value)) {
root = root.next;
}
return root;
}
public boolean isOdd (int val) {
return (val % 2 == 1);
}
How can I improve this solution?
First of all: The remove method should be in your LinkedList class, not in the Node class itself!
After that it's quite easy to just remove the the even ones:
public class LinkedList {
private Node root;
public void removeEvens() {
if (root == null) return;
// removing all even nodes after the root
Node prev = root;
while (prev.next != null) {
if (isEven(prev.next))
prev.next = prev.next.next; // next is even: delete it
else
prev = prev.next; // next is not even: proceed
}
// delete root if it's even
if (isEven(root))
root = root.next;
}
private boolean isEven(Node node) {
return node.value % 2 == 0;
}
}
You can add an element before root node. In that case you don't have to write code for check root node.
public class Node {
public int value;
public Node next;
public Node(){}
public Node (int val) {
value = val;
}
public static Node removeEvens (Node root) {
Node head = new Node();
head.next = root;
for (Node node = head; node.next!=null; node=node.next)
if (isEven(node.next))
node.next = node.next.next;
return head.next;
}
public static boolean isEven(Node node) {
return node.value % 2 == 0;
}
}
I wrote the following code to implement the recursive insert method for the BST. But when I print the tree in walk over order it prints the original tree before insertion. It seems as if the element was not inserted. Please help me out. Thanks in advance. Also please suggest the change in code. By the way, the intial tree in walk over order is 2 5 5 6 7 8.
package DataStructures;
class TreeNode {
private TreeNode parent;
private TreeNode childLeft;
private TreeNode childRight;
private int key;
public TreeNode(){
}
public TreeNode(int key) {
this(key, null);
}
public TreeNode(int key, TreeNode parent) {
this(key, parent, null, null);
}
public TreeNode(int key, TreeNode parent, TreeNode childLeft, TreeNode childRight) {
this.key = key;
this.parent = parent;
this.childLeft = childLeft;
this.childRight = childRight;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public TreeNode getChildLeft() {
return childLeft;
}
public void setChildLeft(TreeNode childLeft) {
this.childLeft = childLeft;
}
public TreeNode getChildRight() {
return childRight;
}
public void setChildRight(TreeNode childRight) {
this.childRight = childRight;
}
}
public class BinarySearchTreeBasicTest {
private static class BinarySearchTree {
private TreeNode root;
private TreeNode maxNode = new TreeNode(0);
public BinarySearchTree(TreeNode root) {
this.root = root;
}
public void printTheTreeInOrderWalk(TreeNode x) {
if (x != null) {
printTheTreeInOrderWalk(x.getChildLeft());
System.out.print(x.getKey() + " ");
printTheTreeInOrderWalk(x.getChildRight());
}
}
public void insertNode(TreeNode node, int key){
if (node == null){
node = new TreeNode(key);
}
else{
if (node.getKey() > key){
insertNode(node.getChildLeft(), key);
} else if (node.getKey() < key){
System.out.println("k");
insertNode(node.getChildRight(), key);
} else{
// dont do anything
}
}
}
}
public static void main(String[] args) {
TreeNode rootNode = new TreeNode(6);
BinarySearchTree tree = new BinarySearchTree(rootNode);
TreeNode node1 = new TreeNode(5);
TreeNode node2 = new TreeNode(7);
rootNode.setChildLeft(node1);
rootNode.setChildRight(node2);
node1.setParent(rootNode);
node2.setParent(rootNode);
TreeNode node3 = new TreeNode(2);
TreeNode node4 = new TreeNode(5);
node1.setChildLeft(node3);
node1.setChildRight(node4);
node3.setParent(node1);
node4.setParent(node1);
TreeNode node5 = new TreeNode(8);
node5.setParent(node2);
node2.setChildRight(node5);
tree.insertNode(rootNode, 3);
tree.printTheTreeInOrderWalk(rootNode);
}
}
In your insertNode() method, you are just creating a new node; you are never adding the newly created node to its parent. You should check whether you are going to insert here or not or you should return the newly returned node and set it accordingly.
If you don't want too much deviation from your current program, you can make the following changes.
public void insertNode(TreeNode node, int key) {
if (node.getKey() > key) {
if (node.left == null) { //check if you want to insert the node here
TreeNode newNode = new TreeNode(key);
node.left = newNode;
} else {
insertNode(node.getChildLeft(), key);
}
} else if (node.getKey() < key) {
if(node.right == null){ //check if you want to insert the node here
TreeNode newNode = new TreeNode(key);
node.right = newNode;
} else {
insertNode(node.getChildRight(), key);
}
} else {
// don't do anything
}
}
In Java, parameters are passed by value. In insertNode, if you don't do anything else with the node, the line node = new TreeNode(key); will not do anything useful.
The typical implementation of an insertion in a tree works by returning the TreeNode that will replace the previous one:
private TreeNode insertNode(TreeNode node, int key){
if (node == null){
node = new TreeNode(key);
}
else{
if (node.getKey() > key){
node.setChildLeft(insertNode(node.getChildLeft(), key));
} else if (node.getKey() < key){
node.setChildRight(insertNode(node.getChildRight(), key));
} else{
// dont do anything
}
}
return node;
}
Going a bit further, the previous method should actually be private. The public method should look like this:
public void insertNode(int key){
root = insertNode(root, key);
}
I'm really struggling to fix my code for this. I've created a Doubly Linked list that I am trying to traverse in reverse.
Any ideas?
Here's my code: Node.java:
public class Node {
String data;
Node next;
public Node(String data) {
super();
this.data = data;
this.next = null;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getNext() {
if (this.next != null)
return this.next;
else
return null;
}
public void setNext(Node a) {
this.next = a;
}
#Override
public String toString() { //CHECK
if(data== null){
return "null";
}
else
return data + "-->";
}
}
Here's the second class "DNode.java":
public class DNode extends Node {
Node prev;
public DNode(String data) {
super(data);
this.prev = null;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
}
Lastly, here is DoublyLinkedList.java: (Overrides "add" and "remove" methods from another class "Linked List")
public class DoublyLinkedList extends LinkedList {
DNode head, tail,current;
public DoublyLinkedList() {
this.head = this.tail = this.current = null;
}
public void add(DNode a) { //CHECK
if (this.head == null) {
this.head = tail = current= a;
this.head.prev = null;
}
else{
//a.setPrev(this.current);
this.current.next= a;
a.setPrev(this.current);
this.current = this.tail = a;
}
}
#Override
public void remove(String removestring) {
this.current = head;
this.current.prev = head;
while (this.current.getData() != removestring) {
if (this.current.next == null) {
System.out.println("not found");
return;
} else {
this.current.prev = this.current;
this.current = (DNode) current.next;
}
}
if (this.current == head) {
head = (DNode) head.next;
} else {
this.current.prev.next = (DNode) this.current.next;
}
}
public void printList() {
DNode temp = this.head;
while (temp != null) {
System.out.println(temp);
temp = (DNode) temp.getNext();
}
}
public void reverseList(){
this.current = this.tail;
this.current.setNext(this.current.getPrev());
this.current.setPrev(null);
this.current = (DNode) this.current.getNext();
while(this.current.getPrev()!= null){
if(this.current.getNext() == null){
this.current.setNext((this.current).getPrev());
this.current.setPrev(null);
this.current = (DNode)this.current.getNext();
}
else{
DNode tempprev = (DNode) this.current.getNext();
this.current.setNext(this.current.getPrev());
this.current.setPrev(tempprev);
this.current = (DNode) this.current.getNext();
}
DNode temp2 = this.tail;
this.head = this.tail;
this.tail = temp2;
}
}
I'm able to print the list going forwards, but going backwards I am running into an infinite loop. Any ideas?
Thanks!
Well, we already have a method to go forwards. Because this is doubly linked, we can just convert this code line by line and instead of moving next (forwards) we move previous (backwards). We also start at the tail instead of the head.
Whereas this was your old method for printing forwards:
public void printList() {
DNode temp = this.head;
while (temp != null) {
System.out.println(temp);
temp = (DNode) temp.getNext();
}
}
This could be your new method for printing backwards:
public void printBackwardsList() {
DNode temp = this.tail;
while(temp != null) {
System.out.println(temp);
temp = (DNode) temp.getPrev();
}
}
Notice how they are almost exactly the same, except we swapped out tail for head and getNext for getPrev.
Your class model seems overly complex. You don't need a DNode class at all to do this. Your method to print the list in reverse should be as simple as the method to print the list normally
public void printListReverse() {
Node temp = this.tail;
while (temp != null) {
System.out.println(temp);
temp = temp.getPrevious();
}
}
assuming you build and maintain the list properly.
while(this.current.getPrev()!= null)
replace with
while(this.current.getPrev()!= head)