I'm working on code for insertion into a binary search tree. It works for the first node I insert, making it the root, but after that it doesn't seem to insert any nodes. I'm sure it's a problem with setting left/right references, but I can't quite figure it out. Please help!
//params: key of node to be inserted, parent node
public void insert(int newKey, TreeNode parent){
//if the root of the tree is empty, insert at root
if(this.getRoot() == null){
this.root = new TreeNode(newKey, null, null);
}
//if the node is null, insert at this node
else if(parent == null)
parent = new TreeNode(newKey, null, null);
else{
//if the value is less than the value of the current node, call insert on the node's left child
if(newKey < parent.getKey()) {
insert(newKey, parent.getLeft());
}
//greater than value of current node, call insert on node's right child
else if(newKey > parent.getKey()){
insert(newKey, parent.getRight());
}
//same as value of current node, increment iteration field by one
else if(newKey == parent.getKey())
parent.incrementIterations();
}
}
My treenodes have key, left, right, and iteration fields, as well as getter/setter functions.
Thank you in advance!
public Node insertNode(Node head, int data) {
if(head == null){
head = new Node();
head.data = data;
return head;
}
if(head.data < data) {
head.right = insertNode(head.right,data);
} else {
head.left = insertNode(head.left, data);
}
return head;
}
If (parent==null) you are creating a node, but you are not associating it to tree back. Its just created and garbage collected.
You should be using insert (newkey, parent) then u still have handle to tree
private AVLNode insert(AVLNode root, int value){
if (root == null) return new AVLNode(value);
if(root.value > value)
root.leftChild = insert(root.rightChild, value);
else
root.rightChild = insert(root.leftChild, value);
return root;
}
Related
I have a binary search tree which stores objects. Can I use String value is a key, It only stores the first key and also searches only the first value, all other keys find returns a null
The first Value is A
this my code: help!
public void addNode(String key, String name) {
// Create a new Node and initialize it
Node newNode = new Node(key, name);
// If there is no root this becomes root
if (root == null) {
root = newNode;
} else {
// Set root as the Node we will start
// with as we traverse the tree
Node focusNode = root;
// Future parent for our new Node
Node parent;
while (true) {
parent = focusNode;
if (key.compareTo(focusNode.name) <= 0) {
// Switch focus to the left child
focusNode = focusNode.leftChild;
// If the left child has no children
if (focusNode == null) {
// then place the new node on the left of it
parent.leftChild = newNode;
return; // All Done
}
} else if(key.compareTo(focusNode.name) >= 0){ // If we get here put the node on the right
focusNode = focusNode.rightChild;
// If the right child has no children
if (focusNode == null) {
// then place the new node on the right of it
parent.rightChild = newNode;
return; // All Done
}
}
}
}
}
enter image description here
From what I see, your problem is that you are comparing keys with values (name in your case). For example, instead of:
if (key.compareTo(focusNode.name) <= 0) {...
Try:
if (key.compareTo(focusNode.key) <= 0) {...
Also, another problem is that you are never handling the case that the two keys are equal, but instead you proceed to the left child. You probably want to do something else at that point, I'd guess updating the name and returning from the method.
I decided to create a Binary Search Tree using java, and what I want to do is delete the Max element from the tree, so I created this part of code:
public Node<T> removeMax(Node<T> node) {
if (node == null)
return null;
if (node.right == null) {
Node<T> n = node;
node = null;
return n;
}
return removeMax(node.right);
}
The method returns the Max element, but it doesn't remove it from the tree. As you can see, I tried to remove it in this part:
Node<T> n = node;
node = null;
return n;
But, when I print the elements in the tree, it shows the "removed" ones too.
What am I doing wrong?
EDIT: What I'm really trying to do is delete the Max node and return it so I can now which one was deleted.
Now I noticed you wanted to know which node gets deleted. All you can do is to delete the maximum node and print the tree:
public void deleteMax(Node<T> root) {
Node<T> current = root;
while (current.right.right != null) {
current = current.right;
}
if(current.right.left!=null) {//max has 1 child to left
current.right=current.right.left;
}
else {//max has no child
current.right=null;
}
}
public String printInfix(Node<T> root) {//prints all the data in the tree in infix order
if(root==null) {
return "";
}
return printAll(root.left+" "+root.data+" "+printAll(root.right);
}
You want to delete a node in a binary search tree. So, basically what you want to do is to make it inaccessible. To do that, you have to nullify the reference to it, i.e, make its parent's corresponding pointer to it as null.
Change this:
if (node.right == null) {
Node<T> n = node;
node = null;
return n;
}
To this:
if (node.right.right == null) {
Node<T> n = node.right;
node.right = node.right.left;
return n;
}
Also you need to take care of the case when the root is the maximum element of the tree. So, if you have some reference to the root of BST, add this case before the above case:
if (node.right == null) {
Node<T> n = node;
referenceToTheRootOfBST = node.left;
return n;
}
If you don't have a reference to the root of the BST, what you can do is deep copy the left node of the root and then remove the left node. So, the above case changes to:
if (node.right == null) {
Node<T> n = node;
//I'll assume you don't call this function if root is the only element.
//if root is the only element.If that's the case, then just make the
//root null before calling this function.
Node<T> leftNode = node.left;
node.value = leftNode.value;
node.left = leftNode.left;
node.right = leftNode.right;
return n;
}
Another simple way to handle the case that root is the maximum element is to check it before actually calling this function. Simply check if root has a right node, and if it doesn't have it, reallocate the root reference.
I'm working on Binary Search Trees, and currently working on recursive delete method. I have a bug in my code; it deletes nodes with no children and with one-child. Problem arises when trying to delete node with two children. (Point of reference - I am replacing deleted node with smallest node in Right Subtree)
My code is:
//Driver
public void delete (String val){
root = delete(root, val);
}
//Recursive Delete Method
private static StringNode delete(StringNode node, String v){
StringNode temp;
if(node == null){
return null;
}
if(v.compareTo(node.getString()) < 0){
node.setLeft(delete(node.getLeft(), v));
}
else if(v.compareTo(node.getString()) > 0){
node.setRight(delete(node.getRight(), v));
}
else{
if(node.getLeft() == null){
node = node.getRight();
}
else if(node.getRight() == null){
node = node.getLeft();
}
else{
node = node.getRight();
while(node.getLeft() != null){
node = node.getLeft();
}
node.setRight(delete(node, node.getString()));
}
}
return node;
}
I have debugged and see that I lose a child when re-connecting the nodes after deletion. But I don't know how to correct in my code.
I figured out the bug. I separated the delete method into delete and deleteNode methods. Worked out.
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 ordered binary tree:
4
|
|-------|
2 5
|
|-------|
1 3
The leaves point to null. I have to create a doubly link list which should look like
1<->2<->3<->4<->5
(Obviously 5 should point to 1)
The node class is as follows:
class Node {
Node left;
Node right;
int value;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
As you can see the doubly link list is ordered (sorted) as well.
Question: I have to create the linked list form the tree without using any extra pointers. The left pointer of the tree should be the previous pointer of the list and the right pointer of the tree should be the next pointer of the list.
What I thought off: Since the tree is an ordered tree, the inorder traversal would give me a sorted list. But while doing the inorder traversal I am not able to see, where and how to move the pointers to form a doubly linked list.
P.S I checked some variations of this question but none of them gave me any clues.
It sounds like you need a method that accepts a Node reference to the root of the tree and returns a Node reference to the head of a circular list, where no new Node objects are created. I would approach this recursively, starting with the simple tree:
2
|
|-----|
1 3
You don't say whether the tree is guaranteed to be full, so we need to allow for 1 and/or 3 being null. The following method should work for this simple tree:
Node simpleTreeToList(Node root) {
if (root == null) {
return null;
}
Node left = root.left;
Node right = root.right;
Node head;
if (left == null) {
head = root;
} else {
head = left;
left.right = root;
// root.left is already correct
}
if (right == null) {
head.left = root;
root.right = head;
} else {
head.left = right;
right.right = head;
right.left = root;
}
return head;
}
Once it is clear how this works, it isn't too hard to generalize it to a recursive method that works for any tree. It is a very similar method:
Node treeToList(Node root) {
if (root == null) {
return null;
}
Node leftTree = treeToList(root.left);
Node rightTree = treeToList(root.right);
Node head;
if (leftTree == null) {
head = root;
} else {
head = leftTree;
leftTree.left.right = root;
root.left = leftTree.left;
}
if (rightTree == null) {
head.left = root;
root.right = head;
} else {
head.left = rightTree.left;
rightTree.left.right = head;
rightTree.left = root;
root.right = rightTree;
}
return head;
}
If I got all the link assignments covered correctly, this should be all you need.
Do an in-order traversal of the list, adding each list item to the doubly linked list as you encounter it. When done, add an explicit link between the first and last items.
Update 3/6/2012: Since you must reuse the Node objects you already have, after you put the node objects into the the list, you can then iterate over the list and reset the left and right pointers of the Node objects to point to their siblings. Once that is done, you can get rid of the list and simply return the first node object.
This should also work:
NodeLL first = null;
NodeLL last = null;
private void convertToLL(NodeBST root) {
if (root == null) {
return;
}
NodeLL newNode = new NodeLL(root.data);
convertToLL(root.left);
final NodeLL l = last;
last = newNode;
if (l == null)
first = newNode;
else {
l.next = newNode;
last.prev = l;
}
convertToLL(root.right);
}
Let your recursion return the left and right end of formed list. Then you link your current node to the last of the left list, and first of the right list. Basic case it, when there is no left or right element, which is the node it self for both. Once all is done, you can link the first and last of the final result. Below is the java code.
static void convertToSortedList(TreeNode T){
TreeNode[] r = convertToSortedListHelper(T);
r[1].next = r[0];
r[0].prev= r[1];
}
static TreeNode[] convertToSortedListHelper(TreeNode T){
TreeNode[] ret = new TreeNode[2];
if (T == null) return ret;
if (T.left == null && T.right == null){
ret[0] = T;
ret[1] = T;
return ret;
}
TreeNode[] left = TreeNode.convertToSortedListHelper(T.left);
TreeNode[] right = TreeNode.convertToSortedListHelper(T.right);
if (left[1] != null) left[1].next = T;
T.prev = left[1];
T.next = right[0];
if (right[0] != null) right[0].prev = T;
ret[0] = left[0]==null? T:left[0];
ret[1] = right[1]==null? T:right[1];
return ret;
}
Add the following method to your Node class
public Node toLinked() {
Node leftmost = this, rightmost = this;
if (right != null) {
right = right.toLinked();
rightmost = right.left;
right.left = this;
}
if (left != null) {
leftmost = left.toLinked();
left = leftmost.left;
left.right = this;
}
leftmost.left = rightmost;
rightmost.right = leftmost;
return leftmost;
}
EDIT By maintaining the invariant that the list returned by toLinked() has the proper form, you can easily get the left- and rightmost nodes in the sublist returned by the recursive call on the subtrees
/* input: root of BST. Output: first node of a doubly linked sorted circular list. **Constraints**: do it in-place. */
public static Node transform(Node root){
if(root == null){
return null;
}
if(root.isLeaf()){
root.setRight(root);
root.setLeft(root);
return root;
}
Node firstLeft = transform(root.getLeft());
Node firstRight = transform(root.getRight());
Node lastLeft = firstLeft == null ? null : firstLeft.getLeft();
Node lastRight= firstRight == null ? null : firstRight.getLeft();
if(firstLeft != null){
lastLeft.setRight(root);
root.setLeft(lastLeft);
if(lastRight == null){
firstLeft.setLeft(root);
}
else{
firstLeft.setLeft(lastRight);
root.setRight(firstRight);
}
}
if(firstRight != null){
root.setRight(firstRight);
firstRight.setLeft(root);
if(lastLeft == null){
root.setLeft(lastRight);
lastRight.setLeft(root);
firstLeft = root;
}
else{
root.setLeft(lastLeft);
lastRight.setRight(firstLeft);
}
}
return firstLeft;
}