I am making a recursive insert method for a binary tree. This method is not able to add nodes to the tree. i cant seem to find whats wrong with this method. the constructor takes a string label for the child and a parent node.
public void insert(String aLabel) {
//if compare is positive add to right else add to left
//basis case:
BSTreeNode aNode = new BSTreeNode(aLabel,null);
if (aNode.parent == null) {
aNode.parent = this;
}
inserts(this,aNode);
}
private void inserts(BSTreeNode aParent, BSTreeNode aNode){
//initially the root node is the parent however a proper parent is found thorough recursion
//left recursion:
if(aParent.getLabel().compareTo(aNode.getLabel()) <= 0) {
if (this.childrenLeft == null) {
this.childrenLeft = aNode;
aNode.parent = this;
return;
} else {
childrenLeft.inserts(childrenLeft, aNode);
}
}
//right recursion
else {
if (this.childrenRight==null) {
this.childrenRight = aNode;
return;
}
else{
childrenRight.inserts(childrenRight,aNode);
}
}
}
EDIT: This answer refers to the original version of the question.
When you call inserts(this.childrenLeft, aNode); you are still at the same node; i.e. this still refers to the old parent.
Instead you should do something like:
childrenLeft.insert(childrenLeft, aNode);
In fact, the first parameter of insert is redundant, you should refactor to remove it.
I think you may need something like this.
The code is commented so you understand what is going on...
// insert method takes The Node as a param and a value to store in BT
public void insert(Node node, int value) {
//Check that the value param is less than the Node (root) value,
// If so insert the data to the left of the root node. Else insert
// the right node as it is a larger number than root
if (value < node.value) {
if (node.left != null) {
insert(node.left, value);
} else {
System.out.println(" Inserted " + value + " to left of "
+ node.value);
node.left = new Node(value);
}
} else if (value > node.value) {
if (node.right != null) {
insert(node.right, value);
} else {
System.out.println(" Inserted " + value + " to right of "
+ node.value);
node.right = new Node(value);
}
}
}
Related
I had an assignment where I was to create a custom Ordered Linked List from scratch. I was happy to receive an near perfect score on the assignment, but I was counted off for not allowing duplicates. Let's say I add "A", and then "A" again. It only prints one "A". Does anyone have any suggestions on how I could implement this? I'll show my add method. If anyone wants more code, feel free to ask and I'll gladly provide.
NOTE: The assignment is already complete, so it's already been graded.
public boolean add(Comparable obj) {
// TODO: Implement this method (8 points)
//FOR REFERENCE - public OrderedListNode(Comparable item, OrderedListNode previous, OrderedListNode next) {
try {
OrderedListNode node; //create new OrderedListNode for comparison
for (node = head; node.next != tail; node = node.next) { //loop one node at a time until next node is tail
int compare = obj.compareTo(node.next.dataItem); //compare current object with next node
if (compare == 0) {
return false; // Nope
}
if (compare < 0) { //obj is less than next node, so insert previous next
break;
}
}
OrderedListNode newNode = new OrderedListNode(obj, node, node.next);
newNode.next.previous = newNode; //swapping nodes
node.next = newNode;
System.out.println("Added: " + obj); //display elements added
modCount++; //another modification
theSize++; //increment size by 1
} catch (ClassCastException e) { //give message to user
System.out.println(RED + "Caught Exception" + RESET_COLOR);
System.out.println("'" + obj +"'" + RED + " not added" + RESET_COLOR);
}
return true; //successful add
}
Change
if (compare == 0) {
return false; // Nope
}
if (compare < 0) { //obj is less than next node, so insert previous next
break;
}
to
if (compare <= 0) { //obj is less than or equal next node, so insert previous next
break;
}
To me it looks like this will allow you to still insert the item if it is equal to another item.
I don't understand why I can't set a leaf-node to null. It still exists in the tree.
Is it beacuse it's a local variable or that it's parent still has a reference to it? I'm deleting the root node, traversing down to the left-most node in the right sub-tree. The left-most node has no right-node. Please check the comment in the code.
public void delete2(Integer value) {
//getNode(value) is a helper-function. Returns the node to be changed
Node node = getNode(value);
if(node != null) {
if(node.hasLeft() && node.hasRight()) {
Node pos = node;
pos = node.right; //Right subtree
while(pos.hasLeft()) //Traverse to the leftmost node
pos = pos.left;
node.value = pos.value; //Change value
if(pos.hasRight())
pos = pos.right;
else {
//I end up here. This doesn't work.
pos = null;
}
}
else if (node.hasLeft() && !node.hasRight()) {
//TODO
}
else if(!node.hasLeft() && node.hasRight()) {
//TODO
}
else {
//TODO
}
}
else
throw new NoSuchElementException();
}
I am trying to implement a remove method for the BST structure that I have been working on. Here is the code with find, insert, and remove methods:
public class BST {
BSTNode root = new BSTNode("root");
public void insert(BSTNode root, String title){
if(root.title!=null){
if(title==root.title){
//return already in the catalog
}
else if(title.compareTo(root.title)<0){
if(root.leftChild==null){
root.leftChild = new BSTNode(title);
}
else{
insert(root.leftChild,title);
}
}
else if(title.compareTo(root.title)>0){
if(root.rightChild==null){
root.rightChild = new BSTNode(title);
}
else{
insert(root.rightChild,title);
}
}
}
}
public void find(BSTNode root, String title){
if(root!= null){
if(title==root.title){
//return(true);
}
else if(title.compareTo(root.title)<0){
find(root.leftChild, title);
}
else{
find(root.rightChild, title);
}
}
else{
//return false;
}
}
public void remove(BSTNode root, String title){
if(root==null){
return false;
}
if(title==root.title){
if(root.leftChild==null){
root = root.rightChild;
}
else if(root.rightChild==null){
root = root.leftChild;
}
else{
//code if 2 chlidren remove
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
}
I was told that I could use the insert method to help me with the remove method, but I am just not seeing how I can grab the smallest/largest element, and then replace the one I am deleting with that value, then recursively delete the node that I took the replacement value, while still maintaining O(logn) complexity. Anyone have any ideas or blatant holes I missed, or anything else helpful as I bang my head about this issue?
EDIT:
I used the answers ideas to come up with this, which I believe will work but I'm getting an error that my methods (not just the remove) must return Strings, here is what the code looks like, I thought that's the return statements??
public String remove(BSTNode root, String title){
if(root==null){
return("empty root");
}
if(title==root.title){
if(root.leftChild==null){
if(root.rightChild==null){
root.title = null;
return(title+ "was removed");
}
else{
root = root.rightChild;
return(title+ "was removed");
}
}
else if(root.rightChild==null){
root = root.leftChild;
return(title+ "was removed");
}
else{
String minTitle = minTitle(root);
root.title = minTitle;
remove(root.leftChild,minTitle);
return(title+ "was removed");
}
}
else if(title.compareTo(root.title)<0){
remove(root.leftChild, title);
}
else{
remove(root.rightChild, title);
}
}
public void remove (String key, BSTNode pos)
{
if (pos == null) return;
if (key.compareTo(pos.key)<0)
remove (key, pos.leftChild);
else if (key.compareTo(pos.key)>0)
remove (key, pos.rightChild);
else {
if (pos.leftChild != null && pos.rightChild != null)
{
/* pos has two children */
BSTNode maxFromLeft = findMax (pos.leftChild); //need to make a findMax helper
//"Replacing " pos.key " with " maxFromLeft.key
pos.key = maxFromLeft.key;
remove (maxFromLeft.key, pos.leftChild);
}
else if(pos.leftChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
//"Promoting " pos.leftChild.key " to replace " pos.key
pos = pos.leftChild;
trash = null;
}
else if(pos.rightChild != null) {
/* node pointed by pos has at most one child */
BSTNode trash = pos;
/* "Promoting " pos.rightChild.key" to replace " pos.key */
pos = pos.rightChild;
trash = null;
}
else {
pos = null;
}
}
}
This is the remove for an unbalanced tree. I had the code in C++ so I have quickly translated. There may be some minor mistakes though. Does the tree you are coding have to be balanced? I also have the balanced remove if need be. I wasn't quite sure based on the wording of your question. Also make sure you add a private helper function for findMax()
void deleteTreeNode(int data){
root = deleteTreeNode(root ,data);
}
private TreeNode deleteTreeNode(TreeNode root, int data) {
TreeNode cur = root;
if(cur == null){
return cur;
}
if(cur.data > data){
cur.left = deleteTreeNode(cur.left, data);
}else if(cur.data < data){
cur.right = deleteTreeNode(cur.right, data);
}else{
if(cur.left == null && cur.right == null){
cur = null;
}else if(cur.right == null){
cur = cur.left;
}else if(cur.left == null){
cur = cur.right;
}else{
TreeNode temp = findMinFromRight(cur.right);
cur.data = temp.data;
cur.right = deleteTreeNode(cur.right, temp.data);
}
}
return cur;
}
private TreeNode findMinFromRight(TreeNode node) {
while(node.left != null){
node = node.left;
}
return node;
}
To compare objects in java use .equals() method instead of "==" operator
if(title==root.title)
^______see here
you need to use like this
if(title.equals(root.title))
or if you are interesed to ignore the case follow below code
if(title.equalsIgnoreCase(root.title))
private void deleteNode(Node temp, int n) {
if (temp == null)
return;
if (temp.number == n) {
if (temp.left == null || temp.right == null) {
Node current = temp.left == null ? temp.right : temp.left;
if (getParent(temp.number, root).left == temp)
getParent(temp.number, root).left = current;
else
getParent(temp.number, root).right = current;
} else {
Node successor = findMax(temp.left);
int data = successor.number;
deleteNode(temp.left, data);
temp.number = data;
}
} else if (temp.number > n) {
deleteNode(temp.left, n);
} else {
deleteNode(temp.right, n);
}
}
I know this is a very old question but anyways... The accepted answer's implementation is taken from c++, so the idea of pointers still exists which should be changed as there are no pointers in Java. So every time when you change the node to null or something else, that instance of the node is changed but not the original one This implementation is taken from one of the coursera course on algorithms.
public TreeNode deleteBSTNode(int value,TreeNode node)
{
if(node==null)
{
System.out.println("the value " + value + " is not found");
return null;
}
//delete
if(node.data>value) node.left = deleteBSTNode(value,node.left);
else if(node.data<value) node.right = deleteBSTNode(value,node.right);
else{
if(node.isLeaf())
return null;
if(node.right==null)
return node.left;
if(node.left==null)
return node.right;
TreeNode successor = findMax(node.left);
int data = successor.data;
deleteBSTNode(data, node.left);
node.data = data;
}
return node;
}
All the links between the nodes are pertained using the return value from the recursion.
For the Depth First Post-Order traversal and removal, use:
/*
*
* Remove uses
* depth-first Post-order traversal.
*
* The Depth First Post-order traversal follows:
* Left_Child -> Right-Child -> Node convention
*
* Partial Logic was implemented from this source:
* https://stackoverflow.com/questions/19870680/remove-method-binary-search-tree
* by: sanjay
*/
#SuppressWarnings("unchecked")
public BinarySearchTreeVertex<E> remove(BinarySearchTreeVertex<E> rootParameter, E eParameter) {
BinarySearchTreeVertex<E> deleteNode = rootParameter;
if ( deleteNode == null ) {
return deleteNode; }
if ( deleteNode.compareTo(eParameter) == 1 ) {
deleteNode.left_child = remove(deleteNode.left_child, eParameter); }
else if ( deleteNode.compareTo(eParameter) == -1 ) {
deleteNode.right_child = remove(deleteNode.right_child, eParameter); }
else {
if ( deleteNode.left_child == null && deleteNode.right_child == null ) {
deleteNode = null;
}
else if ( deleteNode.right_child == null ) {
deleteNode = deleteNode.left_child; }
else if ( deleteNode.left_child == null ) {
deleteNode = deleteNode.right_child; }
else {
BinarySearchTreeVertex<E> interNode = findMaxLeftBranch( deleteNode.left_child );
deleteNode.e = interNode.e;
deleteNode.left_child = remove(deleteNode.left_child, interNode.e);
}
} return deleteNode; } // End of remove(E e)
/*
* Checking right branch for the swap value
*/
#SuppressWarnings("rawtypes")
public BinarySearchTreeVertex findMaxLeftBranch( BinarySearchTreeVertex vertexParameter ) {
while (vertexParameter.right_child != null ) {
vertexParameter = vertexParameter.right_child; }
return vertexParameter; } // End of findMinRightBranch
I've a binary search tree homework in Java where I was given complete Tree and Node classes and a SearchTree class in which I'm to complete the search and insert methods. The search is supposed to return the value of the node corresponding the searched key.
Here is the Tree class and here the Node class. My search and insert methods are below.
It seems I'm getting close, but test insert of key 0 and value 2 into Tree[Node[0,1,null,null]] results in Tree[Node[0,1,null,null] rather than the correct Tree[Node[0,2,null,null]]. What am I not understanding here?
public static Object search(Tree tree, int key) {
Node x = tree.getRoot();
while (x != null) {
if (key == x.getKey()) {
return x.getValue();
}
if (key < x.getKey()) {
x = x.getLeft();
} else {
x = x.getRight();
}
}
return null;
}
public static void insert(Tree tree, int key, Object value) {
if (tree.getRoot() == null) {
tree.setRoot(new Node(key, value));
}
Node juuri = tree.getRoot();
while (juuri != null) {
if (key == juuri.getKey()) {
return;
} else if (key < juuri.getKey()) {
if (juuri.getLeft() == null) {
juuri.setLeft(new Node(key, value));
return;
} else {
juuri = juuri.getLeft();
}
} else {
if (juuri.getRight() == null) {
juuri.setRight(new Node(key, value));
return;
} else {
juuri = juuri.getRight();
}
}
}
}
Well the issue I am seeing is that key values in your tree are unique. In this if statement you leave your insert method without adding a node if you see that the key is already in the tree.
if (key == juuri.getKey()) {
return;
}
In your example (if I understand it right) 0 is already in the tree so nothing changes when inserting 0 again. Based on your example, I am assuming you want to do an update on a node if the key is the same. So this code would do it.
if (key == juuri.getKey()) {
juuri.setValue(value);
return;
}
I need to create a recursive method that takes as a parameter the root node of a binary search tree. This recursive method will then return the int value of the total number of nodes in the entire binary search tree.
This is what I have so far:
public class BinarySearchTree<E> extends AbstractSet<E>
{
protected Entry<E> root;
//called by the main method
public int nodes()
{
return nodes(root);
}
//nodes() will count and return the nodes in the binary search tree
private int nodes(Entry<E> current)
{
if(current.element != null)
{
if(current.left == null && current.right == null)
{
if(current.element == root.element)
return 1;
deleteEntry(current);
return 1 + nodes(current.parent);
}
else if(current.left != null && current.right == null)
return nodes(current.left);
else if(current.left == null && current.right != null)
return nodes(current.right);
else if(current.left != null && current.right != null)
return nodes(current.left) + nodes(current.right);
} else return 1;
return 0;
}
The main method calls nodes like so:
System.out.println ("\nThis section finds the number of nodes "
+ "in the tree");
System.out.println ("The BST has " + bst.nodes() + " nodes");
So I was running the search by traveling in order, once I'd get to a node with no children I would delete the current node and return to the parent node and continue. I ran a debug of the method I have above and the program crashes with a NullPointerException() when it finally counts and removes all the nodes on the left and right side of the root node and tries to return 1.
This is for my lab, the method MUST be recursive.
I'm very lost at this point, does anyone know what I'm doing wrong?
You are making this way too complicated. The basic idea of object oriented programming is that you trust objects to do the jobs they know the answers to. So if I'm a parent, I can count myself, and I let my children count themselves, and so forth.
private int nodes(Entry<E> current) {
// if it's null, it doesn't exist, return 0
if (current == null) return 0;
// count myself + my left child + my right child
return 1 + nodes(current.left) + nodes(current.right);
}
You have several issues:
You're deleting nodes as you count them? Is nodes() supposed to clear the tree?
You're treating root==null, root!=null&left==null&&right==null, root!=null&left!=null&right==null, etc as separate cases. They're not. You have three cases, which are not entirely exclusive:
If the current node is not null, add one to the count. (This should always be the case. The only case where it might be false is if the current node == root, and we can detect and sidestep that beforehand.)
If the current node has a left child, add the left child's count.
If the current node has a right child, add the right child's count.
You're traversing back up the tree for some ungodly reason. Looks like it has something to do with deleting nodes...?
But the biggest thing in my opinion is, you're not giving enough autonomy to the Entrys. :P
A node can count its own children. Trust it to.
class Entry<E> {
...
int count() {
int result = 1;
if (left != null) result += left.count();
if (right != null) result += right.count();
return result;
}
}
public int nodes() {
return (root == null) ? 0 : root.count();
}
If your teacher is incompetent, and insists on some node-counting function outside a node, you can do the same thing you were trying to do:
private int nodes(Entry<E> current) {
int result = 1;
if (current.left) result += nodes(current.left);
if (current.right) result += nodes(current.right);
return result;
}
public int nodes() {
return (root == null) ? 0 : nodes(root);
}
But that teacher should be fired, in my opinion. The Entry class is the real tree; BinarySearchTree is really just a container for a reference to the root.
Also notice, i don't give a damn about the parents. If we start counting from the root, and each node counts its children, which count their children, etc etc... then all nodes will be accounted for.
public int countNodes(Node root){
// empty trees always have zero nodes
if( root == null ){
return 0;
}
// a node with no leafes has exactly one node
// note from editor: this pice of code is a micro optimization
// and not necessary for the function to work correctly!
if( root.left == null && root.right == null ){
return 1;
}
// all other nodes count the nodes from their left and right subtree
// as well as themselves
return countNodes( root.left ) + countNodes( root.right ) + 1;
}
After you delete current in: deleteEntry(current);, you use current.parent in return 1 + nodes(current.parent);
May be this's the reason of throwing NullPointerException..
Hey I have a very clean counting implemented for a binary tree:
public class Binary<T> where T: IComparable<T>
{
private Node _root;
public int Count => _root.Count;
public void Insert(T item)
{
Node newNode = new Node(item);
if (_root == null)
_root = newNode;
else
{
Node prevNode = _root;
Node treeNode = _root;
while (treeNode != null)
{
prevNode = treeNode;
treeNode = newNode.Item.CompareTo(treeNode.Item) < 1 ? treeNode.Left : treeNode.Right;
}
newNode.Parent = prevNode;
if (newNode.Item.CompareTo(prevNode.Item) < 1)
prevNode.Left = newNode;
else
prevNode.Right = newNode;
}
}
public class Node
{
public T Item;
public Node Parent;
public Node Left;
public Node Right;
public Node(T item, Node parent = null, Node left = null, Node right = null)
{
Item = item;
Parent = parent;
Left = left;
Right = right;
}
public int Count
{
get
{
int count = 1;
count += Left?.Count ?? 0;
count += Right?.Count ?? 0;
return count;
}
}
}
}
Maybe this helps you to understand how to implement a class for a simple binary tree with a count.
This implementation accesses the count through a count in the corresponding node in the tree.
Let me now if you are not familiar with the markup of .NET 4.6