I try to print the result of boolean insert(K) in a for loop but after the first insertion the printing stops, that indicates the second insertion is not fully successful.
and inside method insert(K), the method "retrieves(K)" is called, to check if K has been already inserted.
for (int i = 100; i > 0; i--) {
System.out.println(m.insert(i +1, 22));
System.out.println("dd");
System.out.println(m.retrieve(i+1).first + ",,,"+m.retrieve(i+1).second);
System.out.println(i + " insertion done");
System.out.println("---------");
}
and the result is
-------------------
true
dd
true,,,22
100 insertion done
---------
true
dd
After removing the "retrieves(K)" call in the insert() method, the print runs just fine, so i am assuming there is an issues with the method "retrieves(K)", and since there is no error + cpu usage is higher, it might be an infinite loop, the problem is, i don't see it.
here is the method "retrieves(K)"
public Pair<Boolean, T> retrieve(K k) {
Pair<Boolean, T> ff = new Pair<Boolean, T>(false, null);
BSTMapNode<K, T> p = root;
if(root==null) {
return new Pair<Boolean,T>(false,null);
}
else
while (p != null) {
if (k.compareTo(p.key) == 0) {
ff.first=true;
ff.second=p.data;
return new Pair<Boolean,T>(true,p.data);
} else if (k.compareTo(p.key) < 0) {
p = p.left;
} else
p = p.right;
}
return new Pair<Boolean,T>(false,null);
}
EDIT: added insert method
public boolean insert(K k, T e) {
BSTMapNode<K, T> p = current;
BSTMapNode<K, T> q = current;
// ISSUE HERE
if (retrieve(k).first == true) {
current = q;
return false;
//
}
BSTMapNode<K, T> tmp = new BSTMapNode<K, T>(k, e);
if (root == null) {
root = current = tmp;
return true;
} else {
if (k.compareTo(current.key) < 0)
current.left = p;
else
current.right = p;
current = p;
return true;
}
The issue is with the insert() method. When it is called for the second time, root is non-null, so execution gets into the else branch. There, it sets current.left = p with current == p, so p is now its own p.left. When the retrieve() method arrives at that node, it sets p = p.left which changes nothing, causing the infinite loop.
Your approach using a current node does not work. In insert(), you have to search the insertion position of the new node from the root every time, similar to what you do in retrieve(). Just keep going down until you reach a leaf. Then insert the new node there.
The code could look like this:
public boolean insert (K key, T value) {
if (root == null) {
root = new BSTMapNode<>(key, value);
return true;
} else {
BSTMapNode<K, T> p = root;
while (true) {
if (key.compareTo(p.key) == 0) {
return false; // Already in BST
} else if (key.compareTo(p.key) < 0) {
if (p.left == null) {
p.left = new BSTMapNode<>(key, value);
return true;
} else {
p = p.left;
}
} else {
// Analogous for right sub-tree
}
}
}
}
Related
i am trying to delete odd numbers in the queue linked list but I am struggling to make function to
delete the odd here my code for better understanding ;
public class queueLinked {
private Node rear;
private Node front;
private int siz;
public boolean isEmpty() {//function return boolean if is empty or not
boolean response = false;
if (siz == 0) {
response = true;
}
return response;
}
public void enqueue(int element) { // inserting the value type of int
Node node = new Node(element);
if (front == null) {
rear = node;
front = node;
} else {
rear.setNext(node);
rear = node;
siz++;
}
}
public queueLinked() {
front = null;
rear = null;
siz = 0;
}
public Node dequeue() { // to remove the a element in the queue
Node response = null;
if (front != null) ;
if (front.getNext() != null) {
response = new Node(front.getData());
front = front.getNext();
siz--;
} else {
response = new Node(front.getData());
front = null;
rear = null;
}
return response;
}
public Node peak() {
Node response = null;
if (!isEmpty()) {
response = new Node(front.getData());
}
return response;
}
public int getSiz() { // to get the size
return siz;
}
public void display() { // display the queue function
System.out.print("\nQueue = ");
if (siz == 0) {
System.out.print("Empty\n");
return;
}
Node ptr = front;
while (ptr != rear.getNext()) {
System.out.print(ptr.getData() + " ");
ptr = ptr.getNext();
}
System.out.println();
}
public void deleteOdd() { // delete odd number in the queue
System.out.print("\nQueue = ");
if (siz == 0) { //make sure if it is empty or not
System.out.print("Empty\n");
return;
}
Node tempe = front;
if (front.getData() % 2 != 0){
enqueue(front.getData());
front = front.getNext();
rear = rear.getNext();
}
}
}
in function deleteOdd() i tried to make sure if is it empty and then I tried more than way to get the right one if the first one is odd delete it and front = front.next and I do not know if it is right
First, there are some issues in other methods in your code:
Issues
enqueue should also increase the size of the list when adding to an empty list.
dequeue should also decrease the size of the list when removing the last node from it.
dequeue has a wrong semi-colon after if (front != null) ; and so you can get a null pointer exception on the line below it.
Here is a possible correction with minimal changes:
public void enqueue(int element) {
Node node = new Node(element);
if (front == null) {
rear = node;
front = node;
} else {
rear.setNext(node);
rear = node;
}
siz++; // size should be updated in both cases
}
public Node dequeue() {
Node response = null;
if (front != null) { // correction of misplaced semi-colon
response = new Node(front.getData());
front = front.getNext();
if (front == null) {
rear = null;
}
siz--; // size should be updated in both cases
}
return response;
}
deleteOdd
I chose to only use public methods of the class, so that this function can be easily coded outside of the class, if desired.
The current size of the queue is used for a count down, so every node is visited exactly once. The nodes with even data are appended to the queue again, but this count down will prevent us from visiting those again (and again, ...):
public void deleteOdd() {
for (int count = getSiz(); count > 0; count--) {
Node node = dequeue();
if (node.getData() % 2 == 0) {
enqueue(node.getData());
}
}
}
Try the following function to delete odd number in queue.
public void deleteOdd() { // delete odd number in the queue
if (size == 0) { // make sure if it is empty or not
System.out.print("Empty\n");
return;
}
Node ptr = front;
while (ptr != rear.getNext()) {
if (ptr.getData() % 2 != 0) {
Node tmp = ptr.getNext();
ptr.data = tmp.getData();
ptr.next = tmp.next;
size--;
}
else
ptr = ptr.getNext();
}
System.out.println();
}
QueueLinked queue = new QueueLinked();
for (int i=1; i<=20; i++) {
queue.enqueue(i);
}
queue.display();
queue.deleteOdd();
Iterator words = treeSearch.getItems().iterator();
int addCount = 0;
while (words.hasNext())
{
numWords++;
rootNode = add(objectToReference, addCount++, (ITreeSearch) words.next(), 0, rootNode);
}
//Add to the Tree
private TernaryTreeNode add(Object storedObject, int wordNum, ITreeSearch treeSearch, int pos, TernaryTreeNode parentNode) throws NoSearchValueSetException
{
if (parentNode == null)
{
parentNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
if (parentNode.lessThan(treeSearch, pos))
{
parentNode.left = add(storedObject, wordNum, treeSearch, pos, parentNode.left);
}
else if (parentNode.greaterThan(treeSearch, pos))
{
parentNode.right = add(storedObject, wordNum, treeSearch, pos, parentNode.right);
}
else
{
if (pos < treeSearch.getNumberNodeValues())
{
parentNode.mid = add(storedObject, wordNum, treeSearch, pos + 1, parentNode.mid);
}
else
{
numberOfObjectsStored++;
parentNode.addStoredData(storedObject);
}
}
return parentNode;
}
This a snippet of my code in my Ternary Tree which I use for inserting a Name of a person(can hav multiple words in a name, like Michele Adams, Tina Joseph George, etc). I want to convert the above recursion to a for loop / while iterator.
Please guide me on this.
General idea in replacing recursion with iteration is to create a state variable, and update it in the loop by following the same rules that you follow in your recursive program. This means that when you pick a left subtree in the recursive program, you update the state to reference the left subtree; when you go to the right subtree, the state changes to reference the right subtree, and so on.
Here is an example of how to rewrite the classic insertion into binary tree without recursion:
public TreeNode add(TreeNode node, int value) {
// Prepare the node that we will eventually insert
TreeNode insert = new TreeNode();
insert.data = value;
// If the parent is null, insert becomes the new parent
if (node == null) {
return insert;
}
// Use current to traverse the tree to the point of insertion
TreeNode current = node;
// Here, current represents the state
while (true) {
// The conditional below will move the state to the left node
// or to the right node, depending on the current state
if (value < current.data) {
if (current.left == null) {
current.left = insert;
break;
} else {
current = current.left;
}
} else {
if (current.right == null) {
current.right = insert;
break;
} else {
current = current.right;
}
}
}
// This is the original node, not the current state
return node;
}
Demo.
Thanks dasblinkenlight..
This is my logic for replacing the above recursive function for a ternary tree.
Iterator words = treeSearch.getItems().iterator();
while (words.hasNext())
{
for (int i = 0; i < word.getNumberNodeValues(); i++)
{
add_Non_Recursive(objectToReference, word, i);
}
}
//Add to Tree
private void add_Non_Recursive(Object storedObject, ITreeSearch treeSearch, int pos) throws NoSearchValueSetException
{
TernaryTreeNode currentNode = rootNode;
// Start from a node(parentNode). If there is no node, then we create a new node to insert into the tree.
// This could even be the root node.
if (rootNode == null)
{
rootNode = new TernaryTreeNode(treeSearch.getNodeValue(pos));
}
else
{
while (currentNode != null)
{
if (currentNode.lessThan(treeSearch, pos))
{
if (currentNode.left == null)
{
currentNode.left = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.left;
}
}
else if (currentNode.greaterThan(treeSearch, pos))
{
if (currentNode.right == null)
{
currentNode.right = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.right;
}
}
else
{
if (currentNode.mid == null)
{
currentNode.mid = new TernaryTreeNode(treeSearch.getNodeValue(pos));
currentNode = null;
}
else
{
currentNode = currentNode.mid;
}
}
}
}
}
But I dropped this logic as it wasnt great in performing, it took more time than the recursive counterpart.
public int indexOf(X item)
{
Node <X> current = head;
int c = 0;
if (current.getValue().equals(item))
{
return c;
}
while (current != null)
{
current = current.getLink();
c++;
if (current.getValue().equals(item))
{
return c;
}
}
return -1;
}
.
#Test
public void testIndexOf()
{
LList<String> b = new LList<String>();
for (int i = 0; i < 20; i++)
b.add("str" + i);
assertEquals(19, b.indexOf("str0"));
assertEquals(0, b.indexOf("str19"));
assertEquals(-1, b.indexOf("not found"));
}
For some reason the last assertion is bringing up an error as Nullpointer exception. but i made it so when it does reach null to return -1, which is what i was trying to return in the third assertion in the test, what am i missing here?
The problem is this:
while (current != null)
{
current = current.getLink();
You ensure that current is not null . . . but then you immediately change current in a way that makes it possible for it to be null again. And you'll reach that case whenever item is not present in your linked-list.
You can fix this by rearranging the code a bit:
public int indexOf(X item)
{
Node <X> current = head;
int c = 0;
while (current != null)
{
if (current.getValue().equals(item))
{
return c;
}
current = current.getLink();
c++;
}
return -1;
}
while (current != null)
{
current = current.getLink();
c++;
if (current.getValue().equals(item))
{
return c;
}
}
return -1;
You are advancing to the next link after your null check. current.getLink is returning null.
I am implementing a Red Black Tree with insert, search and delete functions in O (log n) time. Insert and search are working fine. However I am stuck on delete. I found this ppt slide on the internet which shows the algorithm of RBT deletion: http://www.slideshare.net/piotrszymanski/red-black-trees#btnNext on page 56 onwards. I know I am asking a bit too much but I have been stuck on this for over 2 weeks and I can't find the problem. The way I'm understanding Top-Down deletion that you have to rotate and recolor nodes accordingly until you find the predecessor of the node to be deleted. When you do find this node - which would be either a leaf or a node with one right child, replace node to be deleted data by the data of this node and delete this node like normal BST deletion, right?
This is the code I did, based on what I learnt from that slide. If anyone would be so kind to go over it, I would be more than grateful! Or at least if you think there's a better algorithm than what I'm using, please tell me!
public void delete(int element){
if (root == null){
System.out.println("Red Black Tree is Empty!");
} else {
Node X = root;
parent = null;
grandParent = null;
sibling = null;
if (isLeaf(X)){
if (X.getElement() == element){
emptyRBT();
}
} else {
if (checkIfBlack(root.getLeftChild()) && checkIfBlack(root.getRightChild())){
root.setIsBlack(false);
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
}
Step2(X, element);
} else {
Step2B(X, element);
}
}
}
root.setIsBlack(true);
}
public void Step2(Node X, int element)
{
int dir = -1;
while (!isLeaf(X)){
if (predecessor == null){ // still didn't find Node to delete
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
dir = 0;
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
dir = 1;
} else if (X.getElement() == element){
toDelete = X;
predecessor = inorderPredecessor(X.getRightChild());
X = moveRight(X);
}
} else { // if node to delete is already found and X is equal to right node of to delete
// move always to the left until you find predecessor
if (X != predecessor){
X = moveLeft(X);
dir = 0;
}
}
if (!isLeaf(X)){
if (!hasOneNullNode(X)){
if (checkIfBlack(X.getLeftChild()) && checkIfBlack(X.getRightChild())){
Step2A(X, element, dir);
} else {
Step2B(X, element);
}
}
}
}
removeNode(X);
if (predecessor != null){
toDelete.setElement(X.getElement());
}
}
public Node Step2A(Node X, int element, int dir) {
if (checkIfBlack(sibling.getLeftChild()) && checkIfBlack(sibling.getRightChild())) {
X = Step2A1(X);
} else if ((checkIfBlack(sibling.getLeftChild()) == false) && checkIfBlack(sibling.getRightChild())) {
X = Step2A2(X);
} else if ((checkIfBlack(sibling.getLeftChild()) && (checkIfBlack(sibling.getRightChild()) == false))) {
X = Step2A3(X);
} else if ((checkIfBlack(sibling.getLeftChild()) == false) && (checkIfBlack(sibling.getRightChild()) == false)) {
X = Step2A3(X);
}
return X;
}
public Node Step2A1(Node X) {
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
return X;
}
public Node Step2A2(Node X) {
if (parent.getLeftChild() == sibling){
LeftRightRotation(sibling.getLeftChild(), sibling, parent);
} else RightLeftRotation(sibling.getRightChild(), sibling, parent);
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
return X;
}
public Node Step2A3(Node X) {
if (parent.getLeftChild() == sibling){
leftRotate(sibling);
} else if (parent.getRightChild() == sibling){
rightRotate(sibling);
}
X.setIsBlack(!X.IsBlack());
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
sibling.getRightChild().setIsBlack(!sibling.getRightChild().IsBlack());
return X;
}
public void Step2B(Node X, int element){
if (predecessor == null){
if (X.getElement() > element && X.getLeftChild() != null){
X = moveLeft(X);
} else if (X.getElement() < element && X.getRightChild() != null){
X = moveRight(X);
} else if (X.getElement() == element){
Step2(X, element);
}
} else {
if (X != predecessor)
X = moveLeft(X);
else Step2(X, element);
}
if (X.IsBlack()){
if (parent.getLeftChild() == sibling){
leftRotate(sibling);
} else if (parent.getRightChild() == sibling){
rightRotate(sibling);
}
parent.setIsBlack(!parent.IsBlack());
sibling.setIsBlack(!sibling.IsBlack());
Step2(X, element);
} else {
Step2B(X, element);
}
}
public void removeNode(Node X) {
if (isLeaf(X)) {
adjustParentPointer(null, X);
count--;
} else if (X.getLeftChild() != null && X.getRightChild() == null) {
adjustParentPointer(X.getLeftChild(), X);
count--;
} else if (X.getRightChild() != null && X.getLeftChild() == null) {
adjustParentPointer(X.getRightChild(), X);
count--;
}
}
public Node inorderPredecessor(Node node){
while (node.getLeftChild() != null){
node = node.getLeftChild();
}
return node;
}
public void adjustParentPointer(Node node, Node current) {
if (parent != null) {
if (parent.getElement() < current.getElement()) {
parent.setRightChild(node);
} else if (parent.getElement() > current.getElement()) {
parent.setLeftChild(node);
}
} else {
root = node;
}
}
public boolean checkIfBlack(Node n){
if (n == null || n.IsBlack() == true){
return true;
} else return false;
}
public Node leftRotate(Node n)
{
parent.setLeftChild(n.getRightChild());
n.setRightChild(parent);
Node gp = grandParent;
if (gp != null){
if (gp.getElement() > n.getElement()){
gp.setLeftChild(n);
} else if (gp.getElement() < n.getElement()){
gp.setRightChild(n);
}
} else root = n;
return n;
}
public Node rightRotate(Node n)
{
parent.setRightChild(n.getLeftChild());
n.setLeftChild(parent);
Node gp = grandParent;
if (gp != null){
if (gp.getElement() > n.getElement()){
gp.setLeftChild(n);
} else if (gp.getElement() < n.getElement()){
gp.setRightChild(n);
}
} else root = n;
return n;
}
The node is being deleted, but the tree after deletion would be black violated, which is very wrong.
The eternally confuzzled blog has top-down implementations of both insert and delete for red-black trees. It also goes through case-by-case why it works. I won't replicate it here (it's rather lengthy).
I've used that blog as a reference for implementing red-black trees in both c++ and java. As I discussed in an earlier answer, I found the implementation to be faster than std::map's bottom-up implementation of red-black trees (whatever STL came with gcc at the time).
Here's an untested, direct translation of the code to Java. I would highly suggest you test it and morph it to match your style.
private final static int LEFT = 0;
private final static int RIGHT = 1;
private static class Node {
private Node left,right;
private boolean red;
...
// any non-zero argument returns right
Node link(int direction) {
return (direction == LEFT) ? this.left : this.right;
}
// any non-zero argument sets right
Node setLink(int direction, Node n) {
if (direction == LEFT) this.left = n;
else this.right = n;
return n;
}
}
boolean remove(int data) {
if ( this.root != null ) {
final Node head = new Node(-1, null, null); /* False tree root */
Node cur, parent, grandpa; /* Helpers */
Node found = null; /* Found item */
int dir = RIGHT;
/* Set up helpers */
cur = head;
grandpa = parent = null;
cur.setLink(RIGHT, this.root);
/* Search and push a red down */
while ( cur.link(dir) != null ) {
int last = dir;
/* Update helpers */
grandpa = parent, parent = cur;
cur = cur.link(dir);
dir = cur.data < data ? RIGHT : LEFT;
/* Save found node */
if ( cur.data == data )
found = cur;
/* Push the red node down */
if ( !is_red(cur) && !is_red(cur.link(dir)) ) {
if ( is_red(cur.link(~dir)) )
parent = parent.setLink(last, singleRotate(cur, dir));
else if ( !is_red(cur.link(~dir)) ) {
Node s = parent.link(~last);
if ( s != null ) {
if (!is_red(s.link(~last)) && !is_red(s.link(last))) {
/* Color flip */
parent.red = false;
s.red = true;
cur.red = true;
}
else {
int dir2 = grandpa.link(RIGHT) == parent ? RIGHT : LEFT;
if ( is_red(s.link(last)) )
grandpa.setLink(dir2, doubleRotate(parent, last));
else if ( is_red(s.link(~last)) )
grandpa.setLink(dir2, singleRotate(parent, last));
/* Ensure correct coloring */
cur.red = grandpa.link(dir2).red = true;
grandpa.link(dir2).link(LEFT).red = false;
grandpa.link(dir2).link(RIGHT).red = false;
}
}
}
}
}
/* Replace and remove if found */
if ( found != null ) {
found.data = cur.data;
parent.setLink(
parent.link(RIGHT) == cur ? RIGHT : LEFT,
cur.link(cur.link(LEFT) == null ? RIGHT : LEFT));
}
/* Update root and make it black */
this.root = head.link(RIGHT);
if ( this.root != null )
this.root.red = false;
}
return true;
}
quick link :
http://algs4.cs.princeton.edu/33balanced/RedBlackBST.java.html
--> Caution : the code on the site is relying on two jars. In the datastructures however the dependency might be minimal. Sometimes it's enough to comment out the main method (that only serves as a test client)
If not : the jars are downloadable on the same site.
If you are looking for two weeks and studying algoritms, chances are you know about
http://algs4.cs.princeton.edu/
the website that is accompanying the famous
Algorithms, by Robert Sedgewick and Kevin Wayne
book.
On this website, there is this implementation of a red black (balances) tree :
http://algs4.cs.princeton.edu/33balanced/RedBlackBST.java.html
I didnot look into it yet (I will later on this year) , but I fully trust it to be a working implementation of a RBTree.
Some sidenote that might be interesting for visitors of this topic:
MIT placed excellent courses concerning algoritms online. The one concerning rbtrees is
http://www.youtube.com/watch?v=iumaOUqoSCk
I'm trying to write code for a binary search tree, the first method I'm working on is the add (insert) method. The root seems to insert properly, but I'm getting null pointer exception when adding the second node. I'll indicate the exact problem spot in my code with comments.
If you can see how to fix the bugs, or let me know if my overall logic is flawed it would be incredibly helpful.-- I will mention that this is for school, so I'm not looking to make a really impressive model...most of my layout choices simply reflect the way we've been working in class. Also, method names were selected by the teacher and should stay the same. Feel free to edit the formatting, had a little trouble.
BINARY TREE CLASS
public class BinarySearchTree
{
private static Node root;
public BinarySearchTree()
{
root = null;
}
public static void Add (Node newNode)
{
Node k = root;
if (root == null)//-----------------IF TREE IS EMPTY -----------------
{
root = newNode;
}
else // -------TREE IS NOT EMPTY --------
{
if (newNode.value > k.value) //-------NEW NODE IS LARGER THAN ROOT---------
{
boolean searching = true;
while(searching) // SEARCH UNTIL K HAS A LARGER VALUE
{ //***CODE FAILS HERE****
if(k.value > newNode.value || k == null)
{
searching = false;
}
else {k = k.rightChild; }
}
if ( k == null) { k = newNode;}
else if (k.leftChild == null){ k.leftChild = newNode;}
else
{
Node temp = k.leftChild;
k.leftChild = newNode;
newNode = k.leftChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
if (newNode.value < k.value) //-----IF NEW NODE IS SMALLER THAN ROOT---
{
boolean searching = true;
while(searching) // ----SEARCH UNTIL K HAS SMALLER VALUE
{// **** CODE WILL PROBABLY FAIL HERE TOO ***
if(k.value < newNode.value || k == null) {searching = false;}
else {k = k.leftChild;}
}
if ( k == null) { k = newNode;}
else if (k.rightChild == null){ k.rightChild = newNode;}
else
{
Node temp = k.rightChild;
k.rightChild = newNode;
newNode = k.rightChild;
if(temp.value > newNode.value )
{
newNode.rightChild = temp;
}
else
{
newNode.leftChild = temp;
}
}
}
}} // sorry having formatting issues
}
NODE CLASS
public class Node
{
int value;
Node leftChild;
Node rightChild;
public Node (int VALUE)
{
value = VALUE;
}
}
TEST APPLICATION
public class TestIT
{
public static void main(String[] args)
{
BinarySearchTree tree1 = new BinarySearchTree();
Node five = new Node(5);
Node six = new Node(6);
tree1.Add(five);
tree1.Add(six);
System.out.println("five value: " + five.value);
System.out.println("five right: " + five.rightChild.value);
}
}
The conditional statement is checked from left to right, so you need to check whether k is null before you check whether k.value > newNode.value because if k is null, then it doesn't have a value.