I am currently writing a method that removes a given value from a binary search tree. However when I call it, it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
There are two methods, one that find the elements, and the other that deletes it.
Here is the one that finds that element...
public static TreeNode delete(TreeNode t, Comparable x, TreeDisplay display)
{
if( x.compareTo(t.getValue()) > 0)
{
display.visit(t);
t.setRight(delete( t.getRight(), x, display));
}
else if ( x.compareTo(t.getValue()) < 0)
{
display.visit(t);
t.setLeft(delete(t.getLeft(), x, display));
}
else
{
t = deleteNode(t, display);
}
return t;
This is the method that deletes the value
private static TreeNode deleteNode(TreeNode t, TreeDisplay display)
{
if (t.getRight()!=null)
{
TreeNode right = t.getRight();
TreeNode max = (TreeNode)TreeUtil.leftmost(right);
TreeNode previous = null;
while ( right.getLeft()!=null&&right.getLeft().getLeft()!=null)
{
right = right.getLeft();
}
t.setValue(max.getValue());
if ( max.getRight()==null)
{
right.setLeft(null);
}
else
{
right.setLeft(max.getRight());
}
}
else if (t.getLeft() !=null)
{
TreeNode left = t.getLeft();
TreeNode max = (TreeNode)TreeUtil.rightmost(left);
while(left.getRight()!=null &&left.getRight().getRight()!=null)
{
left = left.getRight();
}
t.setValue(max.getValue());
if ( max.getLeft()==null)
{
left.setRight(null);
}
else
{
left.setRight(max.getLeft());
}
}
else
{
t = null;
}
return t;
}
Thanks in advance!
...it deletes the said value but then duplicates every other value. I have no idea why. Please tell me what is wrong.
It's because you're returning the deleted node from deleteNode(), and in the first method delete(), your calls to setRight() and setLeft() are setting every traversed element to the deleted element as the recursion unwinds back up the tree.
Related
After adding an elements to the Bst its only saves last 3 elements when i try to search an element it only search in the last 3 elements
I'am trying to add elements to my Bst and it added all the elements i ask to added but when i try to search in elements its always search in the last 3 elements
in my code there is an add function that i call for inserting the elements and for searching iam using contains function that return true or false if the element is found ... after adding some elements , i tried to search for element in the first 3 elements and in the last 3 elements it finds it but when i search in more than 3 elements its only check in the last 3 , i tried to debug then i saw its only check in the last 3 elements that added, even when i try to add element that is already in the tree , if the element in the last 3 elements it return false but if its not it return true like , again checks only in the last 3 elements
my code:
code:
public class BinarySearchTree<T extends Comparable<T>> {
BstNode root;
private int sizeoftree=0;
// Binary Search Tree Node
class BstNode {
T val;
BstNode left, right;
public BstNode(T val) {
this.val = val;
left = null;
right = null;
}
}
public BinarySearchTree() {
this.root=null;
}
public int size(){
return sizeoftree;
}
public boolean add(T val) {
if (this.root == null) {
this.root=new BstNode(val);
sizeoftree++;
return true;
}
while (this.root != null)
{
if (val.compareTo(this.root.val) < 0) {
if(this.root.left==null)
{
this.root.left=new BstNode(val);
sizeoftree++;
return true;
}
this.root = this.root.left;
}
else if(val.compareTo(this.root.val) > 0) {
if(this.root.right==null)
{
this.root.right=new BstNode(val);
sizeoftree++;
return true;
}
this.root = this.root.right;
}
if(val.compareTo(this.root.val)==0)
{
return false;
}
}
return false;
}
public boolean contains(T val)
{
return search(this.root, val);
}
private boolean search(BstNode root, T data) {
if (root == null) {
return false;
} else if (root.val.compareTo(data)==0) {
return true;
} else if (root.val.compareTo(data) > 0) {
return search(root.left, data);
}
return search(root.right, data);
}
public static void main(String[] args)
{
BinarySearchTree<Integer> tree = new BinarySearchTree<Integer>();
tree.add(5);
tree.add(4);
tree.add(2);
tree.add(3);
tree.add(6);
tree.add(1);
tree.contains(5);
}
}
The problem is that you change the root of the tree, and misuse it for navigating down the tree, thereby losing the reference to what should remain the actual root of the tree. The only time the add method should assign to this.root is when the tree is empty:
this.root=new BstNode(val);
All other times you have an assignment to this.root, it is wrong.
So instead of statements like this:
this.root = this.root.left;
...you should use a local variable (let's say current), which you should initialise as
BstNode current = this.root;
...and which you should then use for navigating through the tree with statements like:
current = current.left;
Once you understand this issue, you should be able to update your code consistently.
I'm currently learning about trees using java
and i have some errors going on here
in the insertion of items in a binary tree
I don't why it doesn't work
this is the code:
tree node:
public class TNode {
int data;
TNode left;
TNode right;
public TNode(int data) {
this.data = data;
left = null;
right = null;
}
}
tree class:
public class Tree {
TNode root;
public Tree(){
root = null;
}
public TNode insertNode(TNode item, int d) {
if (item == null) {
return new TNode(d);
}
if (d < item.data) {
item.left = insertNode(item, d);
}
if (d > item.data) {
item.right = insertNode(item, d);
} else {
return item;
}
return item;
}
public void add(int d) {
insertNode(root, d);
}
}
Whenever I add an item the root remains null with no right or left items
if someone can help I'll be really thankful
root is always null because you never assign value to it.
you can add to the beginning of your method check and assign it
public TNode insertNode(TNode item, int d){
if(item == null){
TNode node = new TNode(d);
if (root == null) {
root = node;
}
return node
}
... rest of method isn't changed...
Also when you are recursing you should make a call with a proper child node instead of always calling with item, so for example first case would be:
item.left = insertNode(item.left, d);
For second case you would just use item.right instead.
Fine code, but recursing does not step further
item.left = insertNode(item.left, d);
item.right = insertNode(item.right, d);
And the initial root is not updated:
root = insertNode(root, d);
The else part or final return is superfluous.
Something on the code style
insertNode has a node as input, and returns the updated node value, hence the call "pattern" should look like
X = insertNode(X, d); // X is some expression
This is because java can never assign to the passed argument expression: it has no pass-by-reference, but pass-by-value; f(x) never assigns to x.
I'm attempting to write a pre-order traversal algorithm on a binary tree using the recursive method. Here's what I have:
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
That doesn't compile for some reason. I think the problem is with the rest of my code. Here's the entire code:
class ZOrep extends TreeAndRepresentation {
private int k;
ZOrep left;
ZOrep right;
ZOrep( int m, int[] b ) { // given sequence build tree
super( m, b );
N = (M-1)/2;
k = -1;
t = build();
}
ZOrep( int n, BT t ) { // given tree build sequence
super(n, t);
t = build();
traverse( t );
}
BT build() {
return(a[++k] == 0 ? null : new BT( build(), build() ));
}
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
}
I feel like I'm missing something when I'm building the tree (with my ZOrep method). Also here's the BT class:
class BT {
BT L; BT R;
BT( BT l, BT r ) { L = l; R = r; }
}
Currently my compiler says it can't find the symbol for t.left and t.right.
When the compiler says it can't find the symbol, it means the field you're trying to reference doesn't exist.
Looking at your class BT, this is correct; BT doesn't have left or right, it has L and R. Thus, replacing
traverse(t.left);
traverse(t.right);
with
traverse(t.L);
traverse(t.R);
Will fix this issue.
Currently my compiler says it can't find the symbol for t.left and t.right.
This is because t is a BT and it doesn't have a left and a right.
I suggest you decide what you want to call your tree node class. Is it ZOrep or BT and only use one of these or you will create confusion.
System.out.print(t);
If you want to print out a BT, you will need to add a toString() method to it as the default won't tell you anything useful.
What are you passing into your transverse function? If it's a BT object, then you can't use left and right, you must use L and R. Left and right are parts of your object that extends from BT, but it looks like you're passing in a BT.
// Java
static String tree = "";
private static void preOrder(HuffTree currentObject) {
if (currentObject == null) {
return;
}
if (currentObject.filling == null) tree += 1;
else tree += 0;
preOrder(currentObject.child0);
preOrder(currentObject.child1);
}
}
// class code here
import java.util.Objects;
/**
Huffman tree as class
*/
class HuffTree implements Comparable {
// element filling
Byte filling;
// element repeats
int repeats;
// zero child
HuffTree child0;
// child 1
HuffTree child1;
/**
* constructor for tree fathers and leaves
*/
public HuffTree(Byte filling, int repeats, HuffTree child0, HuffTree child1) {
// father filling
this.filling = filling;
// father repeats
this.repeats = repeats;
// zero child
this.child0 = child0;
// child 1
this.child1 = child1;
}
/**
* finding difference between our tree's items
*/
#Override
public int compareTo(HuffTree currentByte) {
return currentByte.repeats - repeats;
}
/**
* take byte code as a string by recursive three search in depth
*/
public String getCodeForByte(Byte currentByte, String wayToFather) {
// there is 4 cases:
if (!Objects.equals(filling, currentByte)) {
// case 1 - zero child found
if (child0 != null) {
// recursive code add for zero child
String currentWay = child0.getCodeForByte(currentByte, wayToFather + "0");
// return temporary string
if (currentWay != null) return currentWay;
}
// case 2 - child 1 found. recursive code add for child 1. return temporary string
if (child1 != null) return child1.getCodeForByte(currentByte, wayToFather + "1");
}
// case 3 - correct leaf found. return correct code
if (Objects.equals(filling, currentByte)) return wayToFather;
// case 4 - wrong leaf found. return null
return null;
}
}
I know that you can simply solve this question iteratively by using a counter to increment each time you pass a node in linkedlist; also creating an arraylist and setting the data found with each node inside it. Once you hit the tail of the linkedlist, just minus the Nth term from the total number of elements in the arraylist and you will be able to return the answer. However how would someone perform this using recursion? Is it possible and if so please show the code to show your genius :).
Note: I know you cannot return two values in Java (but in C/C++, you can play with pointers :])
Edit: This was a simple question I found online but I added the recursion piece to make it a challenge for myself which I've come to find out that it may be impossible with Java.
The trick is to do the work after the recursion. The array in the private method is basically used as a reference to a mutable integer.
class Node {
Node next;
int data;
public Node findNthFromLast(int n) {
return findNthFromLast(new int[] {n});
}
private Node findNthFromLast(int[] r) {
Node result = next == null ? null : next.findNthFromLast(r);
return r[0]-- == 0 ? this : result;
}
}
As a general rule, anything that can be done with loops can also be done with recursion in any reasonable language. The elegance of the solution may be wildly different. Here is a fairly java idiomatic version. I've omitted the usual accessor functions for brevity.
The idea here is to recur to the end of the list and increment a counter as the recursion unwinds. When the counter reaches the desire value, return that node. Otherwise return null. The non-null value is just returned all the way tot the top. Once down the list, once up. Minimal arguments. No disrespect to Adam intended, but I think this is rather simpler.
NB: OP's statement about Java being able to return only one value is true, but since that value can be any object, you can return an object with fields or array elements as you choose. That wasn't needed here, however.
public class Test {
public void run() {
Node node = null;
// Build a list of 10 nodes. The last is #1
for (int i = 1; i <= 10; i++) {
node = new Node(i, node);
}
// Print from 1st last to 10th last.
for (int i = 1; i <= 10; i++) {
System.out.println(i + "th last node=" + node.nThFromLast(i).data);
}
}
public static void main(String[] args) {
new Test().run();
}
}
class Node {
int data; // Node data
Node next; // Next node or null if this is last
Node(int data, Node next) {
this.data = data;
this.next = next;
}
// A context for finding nth last list element.
private static class NthLastFinder {
int n, fromLast = 1;
NthLastFinder(int n) {
this.n = n;
}
Node find(Node node) {
if (node.next != null) {
Node rtn = find(node.next);
if (rtn != null) {
return rtn;
}
fromLast++;
}
return fromLast == n ? node : null;
}
}
Node nThFromLast(int n) {
return new NthLastFinder(n).find(this);
}
}
Okay, I think think this should do the trick. This is in C++ but it should be easy to translate to Java. I also haven't tested.
Node *NToLastHelper(Node *behind, Node *current, int n) {
// If n is not yet 0, keep advancing the current node
// to get it n "ahead" of behind.
if (n != 0) {
return NToLastHelper(behind, current->next, n - 1);
}
// Since we now know current is n ahead of behind, if it is null
// the behind must be n from the end.
if (current->next == nullptr) {
return behind;
}
// Otherwise we need to keep going.
return NToLastHelper(behind->next, current->next, n);
}
Node *NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n);
}
edit: If you want to return the value of the last node, you can just change it to:
int NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n)->val;
}
This code will fail badly if node is null.
The recursion function:
int n_to_end(Node *no, int n, Node **res)
{
if(no->next == NULL)
{
if(n==0)
*res = no;
return 0;
}
else
{
int tmp = 1 + n_to_end(no->next, n, res);
if(tmp == n)
*res = no;
return tmp;
}
}
The wrapper function:
Node *n_end(Node *no, int n)
{
Node *res;
res = NULL;
int m = n_to_end(no, n, &res);
if(m < n)
{
printf("max possible n should be smaller than or equal to: %d\n", m);
}
return res;
}
The calling function:
int main()
{
List list;
list.append(3);
list.append(5);
list.append(2);
list.append(2);
list.append(1);
list.append(1);
list.append(2);
list.append(2);
Node * nth = n_end(list.head, 6);
if(nth!=NULL)
printf("value is: %d\n", nth->val);
}
This code has been tested with different inputs. Although it's a C++ version, you should be able to figure out the logic :)
I have been trying to learn the ins and outs of some data structures and I am trying to get a binary splay tree to work properly. Every time I run the following code and the node I am looking for is more than one past the root it tells me it is there and then just deletes that whole side from the root down. It works fine if the node is only one level down from the top.
I am not sure what is going wrong but I suppose it has something to do with my rotate functions. I got it to work properly for the insert function which is what I modeled this after.
public class SplayBST {
Node root;
int count;
int level = 0;
boolean found = false;
public SplayBST() {
root = null;
count = 0;
}
public String searchIt(String x) {
//after finishing search method I need to check if splaySearch exists then don't insert just splay it
splaySearch(root, x);
if (this.found == true) {
this.found = false;
return x;
}
else {
return null;
}
}
Node splaySearch(Node h, String x) {
if (h == null) {
return null;
}
if (x.compareTo(h.value) < 0) {
try {
if (x.compareTo(h.left.value) < 0) {
h.left.left = splaySearch(h.left.left, x);
h = rotateRight(h);
} else if (x.compareTo(h.left.value) > 0) {
h.left.right = splaySearch(h.left.right, x);
h.left = rotateLeft(h.left);
}
else {
this.found = true;
return h.left;
}
return rotateRight(h);
}
catch (NullPointerException ex) {
return null;
}
}
else { //basically x.compareTo(h.value)>0
try {
if (x.compareTo(h.right.value) > 0) {
h.right.right = splaySearch(h.right.right, x);
h = rotateLeft(h);
} else if (x.compareTo(h.right.value) < 0) {
h.right.left = splaySearch(h.right.left, x);
h.right = rotateRight(h.right);
}
else {
this.found = true;
return h.right;
}
return rotateLeft(h);
}
catch (NullPointerException ex) {
return null;
}
}
}
Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
return x;
}
Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
return x;
}
class Node {
Node left;
Node right;
String value;
int pos;
public Node(String x) {
left = null;
right = null;
value = x;
}
}
}
I second Tristan Hull's approach to creating a regular BST with a "working" search method. Once you get that working, adding a splay method is rather trivial. I've actually done the same thing when I implemented a Splay Tree in Java. It's a better software design and a simpler implementation.
Your problem is that when you rotate, you update the reference to node H in the function "SplaySearch", but you do not update the parent node in the original "searchIt" function. Thus, the program "thinks" that the original parent node remains the parent, even though the rotated node should be the parent. Thus, when you run whatever method you use to print your tree, you print from a node that is not actually the parent node of the tree, but a child (the level it is on depends on how many times your program called rotateLeft and rotateRight).
To fix this, I suggest implementing search as in a normal binary tree, and then making a "splay" function completely separate from the search function that splays a node to the top of the tree. You would call this splay function at the end of every search, making sure to properly update your reference. This is the traditional way to implement splay trees, and I suggest you take a look at it (maybe look at the wikipedia article on splay trees or do a Google search). Also, you may want to know that your rotate functions are not complete. In terms of splay trees, you also have 2 separate types of double rotations which are very different from single rotations. Again, I suggest looking up splay trees to learn about them more in depth.