I created the following Method to search for a certain ParentReference Id in a Tree that is unsorted and where every node can have any number of children. If the given parentRef matches the Node's parentRef, the Node should be returned.
public static <T>Node<T> search(Node<T> node, int parentRef) {
if(node.getParentRef() == parentRef){
return node;
}
if(node.getChildren()!= null){
for(int i = 0; i < node.getChildren().size(); i++){
if(node.getChildren().get(i).parentRef == parentRef){
return node;
}
else {
search(node.getChildren().get(i), parentRef);
}
}
}
return null;
}
However, it does not work and always returns null but I don't know why. Can anybody explain what I am doing wrong?
In the else branch, you call search recursively, but don't return its value, so it is lost. You should check if it's not null, and if so, return it:
else {
Node<T> result = search(node.getChildren().get(i), parentRef);
if (result != null) {
return result;
}
}
Related
I am creating an implementation of a linked list and am having trouble with the add method. After testing it with several entries, my size() method always returns 1. what am i doing wrong.
public class Node {
public int data;
public Node next;
public Node(int data){
this.data = data;
}
}
public class LinkedList {
public Node first;
public Node last;
public LinkedList(){
first = null;
last = null;
}
public void add(int data){
Node newNode = new Node(data);
if(first == null){
first = newNode;
} else {
add(first, newNode);
}
}
public void add(Node currentNode, Node newNode){
if(currentNode.next != null){
add(currentNode.next, newNode);
}
currentNode.next = newNode;
}
public int size(){
if(first == null){
return 0;
}
else{
return size(first);
}
}
public int size(Node currentNode){
//Count Starts At One Because First = 1.
int count = 1;
if(currentNode == null){
return count;
}
else {
count++;
return size(currentNode.next);
}
}
}
You forgot the else in the 2-arg form of add. As it stands,
if(currentNode.next != null){
add(currentNode.next, newNode);
}
currentNode.next = newNode;
will always add the new node to first and to all the other nodes in the list. If currentNode.next = newNode appears in an else clause, it will be added correctly only to the end.
Additionally, your size method always returns 1 because the final branch always returns 1. To fix this, change
count++;
return size(currentNode.next);
to
return 1 + size(currentNode.next);
Also, replace return count; with return 1;.
Basically, your implementation is almost correct. size(Node) should return the size of the list starting with that node. If the node does not have a next, the size is 1. Otherwise, its the current node (1) + the size of the remaining tail.
You should make the 2-arg versions of add and the 1-arg version of size private since you don't want to expose the internals of your list to the public (in fact, the Node class should be a private class as well).
Additionally, you never use the last field of your class. You can either remove it, or use it to avoid the need for recursion completely in add. In the latter case, you will have to update it correctly with every new addition.
In place of return size(currentNode.next); try this return count + size(currentNode.next);
It will fix the count problem given that, the list is fine. But checking your code at a glance looks like the list addition code is also buggy.
I have a Binary Search Tree that contains nodes. Each node contains a key value and data value, and the nodes are sorted by key. I am trying to write a method to remove an object from my BST provided a key. Here is the code:
public Object remove(Comparable theKey) {
return remove(theKey, rootPtr).data;
}
public Node remove(Comparable theKey, Node node) {
Object o;
if(node == null)
return node;
if(theKey.compareTo(node.key) < 0) {
// go to left subtree
node.leftChild = remove(theKey, node.leftChild);
}else if(theKey.compareTo(node.key) > 0) {
//go to the right subtree
node.rightChild = remove(theKey, node.rightChild);
}else if(theKey.compareTo(node.key) == 0) {
if(node.leftChild != null && node.rightChild != null){
Node foundNode = findMin(node.rightChild);
node.key = foundNode.key;
node.data = foundNode.data;
node.rightChild = remove(node.key, node.rightChild);
}else{
if(node.leftChild != null){
node = node.leftChild;
}else{
node = node.rightChild;
}
}
}
numNodes--;
return node;
}
I would like to return the data value associated with the DELETED node. The issue I have is that: in the public Object remove() method, wouldn't the returned value always be the data value of the root node? I believe this would occur because the final returned call from the second method would be a reference to the rootPtr (root pointer). If this is the case, how can I save the data from the deleted node?
The simplest solution seems to be to add an output parameter than hands back the result:
public Object remove(Comparable theKey) {
Object[] result = new Object[1];
rootPtr = remove(theKey, rootPtr, result); // fix for deletion from a one-node tree
return result[0];
}
public Node remove(Comparable theKey, Node node, Object[] result) {
if(node == null) {
return node;
}
int diff = theKey.compareTo(node.key);
if (diff < 0) {
node.leftChild = remove(theKey, node.leftChild, result);
} else if (diff > 0) {
node.rightChild = remove(theKey, node.rightChild, result);
} else {
result[0] = node.key;
if (node.rightChild == null) {
node = node.leftChild;
} else if (node.leftChild == null) {
node = node.rightChild;
} else {
Node foundNode = findMin(node.rightChild);
node.key = foundNode.key;
node.data = foundNode.data;
node.rightChild = remove(node.key, node.rightChild, new Object[1]);
}
numNodes--;
}
return node;
}
Returning the found node doesn't work without significant changes because the return parameter is used to replace nodes as needed, and in the case where the found node has two children, you'd need to make a copy or insert a new node. Handling the case where the root node gets removed would be an issue, too.
p.s. I am assuming this is not a "trick question" and you can't just return theKey -- which has to equal the found key after all :)
You have to return the value, that you are receiving from the recursive remove-call.
p.ex:
if(theKey.compareTo(node.key) < 0) {
// go to left subtree
return remove(theKey, node.leftChild);
}else if ...
Now you will run throught the tree, until you find the correct node and that node will be given to the node which is the parent of the node to remove, and the parent will than give it to his parent and so on, until the root will return the node to his caller.
I have a slightly working binary search tree delete value function. The only time that it does not work is if you are trying to delete a root that has two children.
public boolean delete(BinaryTreeNode node, int i){
if (node == null){
return false;
} else {
if (node.getKey() == i){
BinaryTreeNode parent = new BinaryTreeNode(0, null, null);
parent.setLeftChild(root);
boolean result = deleteHelper(i, node, parent);
root = parent.getLeftChild();
return result;
} else {
return deleteHelper(i, node, null);
}
}
}
public boolean deleteHelper(int value, BinaryTreeNode curr, BinaryTreeNode parent){
if (value < curr.getKey()){
if (curr.getLeftChild() != null){
return deleteHelper(value, curr.getLeftChild(), curr);
} else {
return false;
}
} else if (value > curr.getKey()){
if (curr.getRightChild() != null){
return deleteHelper(value, curr.getRightChild(), curr);
} else {
return false;
}
} else {
if (curr.getRightChild() != null && curr.getLeftChild() != null){
curr.setKey(findMin(curr.getRightChild()).getKey());
deleteHelper(curr.getKey(), curr.getRightChild(), curr);
} else if (parent.getLeftChild() == curr){
parent.setLeftChild((curr.getLeftChild() != null)?curr.getLeftChild():curr.getRightChild());
} else if (parent.getRightChild() == curr){
parent.setRightChild((curr.getLeftChild() != null)?curr.getLeftChild():curr.getRightChild());
}
return true;
}
}
According to Wikipedia
Deleting a node with two children: Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node or its in-order predecessor node, R. Copy the value of R to N, then recursively call delete on R until reaching one of the first two cases.
http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
You can try by successor node as follows:
get successor of node to delete (current)
connect parent of current to successor
connect successor to the left child for current
For more details check out this link
Java, Binary tree remove method
So I want to go into my tree (which is assumed to have no duplicates and is branched correctly) and find the element that is given in the parameters. I have found that my method gives me a BinaryNode that resembles what I want (the root) in its fields, but is not actually the root. I have not overridden the equals method. Using the equals method, the test returns false when the returned object and the root are compared. I want to know why my variable, elementNode, does not reference (and hence change) the root to be null when it is set null.
Binary nodes are implemented with generics. This method is being called with the root as its starting point. Any help will be appreciated, thank you.
/**
* Returns the node that the sought element resides within
*
* #param element: The element being hunted
* #param start: The start of the search (usually the root)
* #return The node that the element resides in
*/
private BinaryNode<T> findElementNode(T element, BinaryNode<T> start) {
if (start.getElement().equals(element)) {
return start;
}
// the element is not in the collection
if (start.getLeftChild() == null && start.getRightChild() == null) {
return null;
}
int comparison = element.compareTo(start.getElement());
if (comparison < 0) {
return findElementNode(element, start.getLeftChild());
} else {
return findElementNode(element, start.getRightChild());
}
}
EDIT FOR EXAMPLE: (this is for a removal method)
if (!hasLeft && !hasRight) {
System.out.println(elementNode + "," + root);
elementNode = null;
System.out.println(elementNode + "," + root);
return true;
}
This outputs:
BinaryNode#68b0019f,BinaryNode#68b0019f and null,BinaryNode#68b0019f
EDIT FOR ANSWER: The reason that the returned element does not set the node it points to as null is because in Java, we can only point at, not edit, memory locations. So in order to make my node null, I will locate the parent and just set its left/right child to null.
Try with something like this.
private boolean findElementNode(T element, BinaryNode<T> start) {
if (start == null) {
return false;
} else {
if (element.getElement().equals(start.getElement())) {
return true;
} else {
int comparison = element.compareTo(start.getElement());
if (comparison < 0) {
return findElementNode(element, start.getLeftChild());
} else {
return findElementNode(element, start.getRightChild());
}
}
}
EDIT: this is actually what you want. Tell me if this works.
private BinaryNode<T> findElementNode(T element, BinaryNode<T> start) {
if(start != null){
if(start.getElement().equals(element)){
return start;
} else {
BinaryNode<T> start = findElementNode(element, start.getLeftChild());
if(start == null) {
start = findElementNode(element, start.getRightChild());
}
return start;
}
} else {
return null;
}
}
I am having trouble finding the smallest element of a binary search tree. I have some code finished, but it is not working.
public T getMinElement(TreeNode<T> node) {
//TODO: implement this
if (node == null){
return null;
}
if (node.getLeftChild() == null){
return (T) node;
}
else{
return getMinElement(node);
}
}
You were almost there! You just need to recurse on the left child of your binary search tree (always guaranteed to be smaller). Also you had some syntax errors, which I fixed.
public <T> T getMinElement(TreeNode<T> node) {
if (node == null){
return null;
}
if (node.getLeftChild() == null){
return node.getData(); // or whatever your method is
} else{
return getMinElement(node.getLeftChild());
}
}