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.
Related
I am trying to write a non-recursive method that removes a node within a binary search tree if it contains the given input value int x in Java. I figured I need to use a stack but can't seem to figure out how to remove the node without calling the function on itself.
This is my TreeNode class as of now.
class TreeNode {
private int data; // data item (key)
private TreeNode left; // this node's left child
private TreeNode right; // this node's right child
// The "external node" is a special node that acts as a sentinel.
private final static TreeNode externalnode = TreeNode.createExternalNode();
/* Return a TreeNode that represents an "external node"*/
public static TreeNode getExternalNode() {
return externalnode;
}
/* Creates a new TreeNode with no children.
*/
public TreeNode(int id) { // constructor
data = id;
left = externalnode;
right = externalnode;
}
I have tried this but cant get it to work.
public TreeNode removeB(int x){
if (this == externalnode) return externalnode;
TreeNode one = new TreeNode(this.data);
System.out.println(this);
Stack<TreeNode> s = new Stack();
s.push(one);
//System.out.println(s);
boolean check;
boolean check1;
while(check = true){
if(x == one.left.data){
System.out.println(one.left.data);
check = false;
return one.left;
}
if(x == one.right.data){
System.out.println(one.right.data);
check1 = false;
return one.right;
}
}
Your code needs to first perform a binary search to find the node to remove. In pseudo-code, it looks something like:
while (currentNode != null && currentNode.value != target) {
if (currentNode.value > target) {
currentNode = currentNode.left;
} else if (currentNode.value < target) {
currentNode = currentNode.right;
}
}
Once you've targeted that node, you replace it with one of its children, and then graft in the other orphaned child under it, just as you would add any node.
I am trying to search a doubly-linked list in Java for a term, and return it if found. Here is my code so far:
private class Node {
public String content;
public Node up;
public Node left;
public Node right;
}
private Node searchList(String term, Node node) {
while (node != null) {
System.out.print(node.name + " - "); //To see process
if (node.content.equals(term)) {
return node;
} else if (node.right != null) {
return searchList(term, node.right);
}
node = node.left;
}
return null;
}
My algorithm is basically:
While the node is not null
Check if it matches the search term
If there is an element to he right, scan that with recursion
Both points are now null, item is not present
Edit with my question, sorry:
I cannot get it to search down to bottom levels and having trouble understanding where I have gone wrong.
Any help would be appreciated!
I got to agree with the comments that your question is unclear.
However, I assume you are just looking for a way to implement a recursive search on a double linked list (in which null elements are not allowed). As the other answer already mentions, I assume type Page to be a subtype of Node. In fact, I will substitute it in my example below.
Since there seems to be some misconception about implementing a double linked list and about recursion itself, I will give a condensed but running example.
The code you are presenting lacks a termination condition for the recursion. Which, unfortunately, also holds true for ikicha's solution. One way (amongst others) to accomplish this is to use a helper method to pass an invariant (eg. the start element) or counter from one iteration of the recursion to the next one.
The line node = node.left in your example has no effect. If you wanted to achieve a search in both directions (as ikicha sketched) I would be interested in why direction matters for you.
public class DoubleLinked {
private Node first;
private Node last;
private int size;
private class Node {
public String content;
public Node left;
public Node right;
public Node(String content) {
this.content = content;
}
}
private void addElement(Node addedNode) {
if (first == null) {
first = addedNode;
last = addedNode;
} else {
last.right = addedNode;
addedNode.left = last;
addedNode.right = first;
last = addedNode;
}
size++;
}
private Node searchList(String term, Node node) {
int tries = 0;
if (node != null) {
return searchHelper(term, node.right, tries);
}
return null;
}
private Node searchHelper(String term, Node node, int tries) {
if (node == null || tries >= size) {
return null;
}
if (node.content.equals(term)) {
return node;
} else {
return searchHelper(term, node.right, tries);
}
}
public static void main(String[] args) {
DoubleLinked list = new DoubleLinked();
list.addElement(list.new Node("first"));
Node startNode = list.new Node("second");
list.addElement(startNode);
list.addElement(list.new Node("third"));
list.addElement(list.new Node("forth"));
Node r = list.searchList("forth", startNode);
System.out.println(r!=null?r.content:"term not found");
}
}
I think your algorithm computes same node several times because move left and find all right nodes of the left one repeatedly.
You can find node by search two direction each from start node.
private Node internalSearchList(String term, Node node, int direction) {
if (node == null) {
return null;
}
if (term.equals(node.content)) {
return node;
} else {
return internalSearchList(term, direction == 0 ? node.left : node.right, direction);
}
}
private Node searchList(String term, Node node) {
// search to left side
Node result = internalSearchList(term, node, 0);
if (result != null) {
return result;
} else {
return internalSearchList(term, node, 1);
}
}
And also I think the type of Node.left and Node.right must be Node.
private class Node {
public String content;
public Node up;
public Node left;
public Node right;
}
I could not find people to explain me this java code properly so finally I am posting this question.please explain the process how that particular statement is affecting the tree.the problems are stated in the comments.I have problems in the BST class.
import java.util.Scanner;
class BSTNode
{
BSTNode left, right;
int data;
public BSTNode()
{
left = null;
right = null;
data = 0;
}
public BSTNode(int n)
{
left = null;
right = null;
data = n;
}
public void setLeft(BSTNode n)
{
left = n;
}
public void setRight(BSTNode n)
{
right = n;
}
public BSTNode getLeft()
{
return left;
}
public BSTNode getRight()
{
return right;
}
public void setData(int d)
{
data = d;
}
public int getData()
{
return data;
}
}
class BST
{
private BSTNode root;
public BST()
{
root = null;
}
public boolean isEmpty()
{
return root == null;
}
Why is the insert function written like root=insert(...... Is it returning root = actual root element each time?
public void insert(int data)
{
root = insert(root, data);
}
I understand how the inserting process is going on but what is the insert function returning? I know that it returns some node but how the is the process going on during iteration?
private BSTNode insert(BSTNode node, int data)
{
if (node == null)
node = new BSTNode(data);
else
{
if (data <= node.getData())
node.left = insert(node.left, data);
else
node.right = insert(node.right, data);
}
return node;
}
public void delete(int k)
{
if (isEmpty())
System.out.println("Tree Empty");
else if (search(k) == false)
System.out.println("Sorry "+ k +" is not present");
else
{
root = delete(root, k);
Again, why is the delete function written like root=delete(.....? Is it returning root =actual root element each time?
System.out.println(k+ " deleted from the tree");
}
}
private BSTNode delete(BSTNode root, int k)
{
BSTNode p, p2, n;
if (root.getData() == k)
{
BSTNode lt, rt;
lt = root.getLeft();
rt = root.getRight();
if (lt == null && rt == null)
return null;
else if (lt == null)
{
p = rt;
return p;
}
else if (rt == null)
{
p = lt;
return p;
}
else
{
//case when we delete node having both children.
p2 = rt;
p = rt;
//getting the min of the right child subtree in p variable .
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
Please explain what is happening here and why is p2 i.e rt being returned.
return p2;
}
}
if (k < root.getData())
{
n = delete(root.getLeft(), k);
root.setLeft(n);
}
else
{
n = delete(root.getRight(), k);
root.setRight(n);
}
return root;
}
public int countNodes()
{
return countNodes(root);
}
In the delete portion of your code, what you are doing is checking to see if the node (called root) has its data value equal to the value you want to delete (k). If that is true, then you examine both children which you seem to grasp. So then we get down to your question when you have both children of the node not null. In this case you want to delete the current node (root) of the subtree you are on, but you need to choose a node (either the left or right) to promote to the position of this node. So (assuming this tree is not balanced) you simply make a choice (left or right) of the subtree to promote to the know root. Keep in mind here that you are only calling the current node root because it is the root of some subtree within the larger tree (this does not mean the actual root of the tree unless that is the value that was passed in as root). Knowing that all of the values in the right child subtree are going to be greater than those in the left child subtree, you simply take the current node's left subtree then recurse as far down the left children of the right subtree as you can go until you're to the end. You then set this node's left child to the entire left subtree.
//case when we delete node having both children.
p2 = rt;
p = rt;
//getting the min of the right child subtree in p variable .
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
Notice in the statement
p = rt;
You are setting P to be the root of the of the right subtree. Then p is now the right child of the current root passed in.
while (p.getLeft() != null)
p = p.getLeft();
p.setLeft(lt);
This is basically saying that for that right subtree, If the root node has a left child then set p to that and keep doing so until that value is null. This will keep going down the left children of that right subtree. Finally once that value is null
p.setLeft(lt);
Will set the left child of that left most leaf in the right subtree to the entire left subtree that you started with. And return the node that you said was the right subtree of the original (now with the left subtree of the original appended to its leftmost leaf).
So this is my first java program, but I've done c++ for a few years. I wrote what I think should work, but in fact it does not. So I had a stipulation of having to write a method for this call:
tree.insertNode(value);
where value is an int.
I wanted to write it recursively, for obvious reasons, so I had to do a work around:
public void insertNode(int key) {
Node temp = new Node(key);
if(root == null) root = temp;
else insertNode(temp);
}
public void insertNode(Node temp) {
if(root == null)
root = temp;
else if(temp.getKey() <= root.getKey())
insertNode(root.getLeft());
else insertNode(root.getRight());
}
Thanks for any advice.
// In java it is little trickier as objects are passed by copy.
// PF my answer below.
// public calling method
public void insertNode(int key) {
root = insertNode(root, new Node(key));
}
// private recursive call
private Node insertNode(Node currentParent, Node newNode) {
if (currentParent == null) {
return newNode;
} else if (newNode.key > currentParent.key) {
currentParent.right = insertNode(currentParent.right, newNode);
} else if (newNode.key < currentParent.key) {
currentParent.left = insertNode(currentParent.left, newNode);
}
return currentParent;
}
Sameer Sukumaran
The code looks a little confusing with overloaded functions. Assuming member variables 'left' and 'right' to be the left child and right child of the BSTree respectively, you can try implementing it in the following way:
public void insert(Node node, int value) {
if (value < node.value)
{
if (node.left != null)
{
insert(node.left, value);
}
else
{
node.left = new Node(value);
}
}
else if (value > node.value)
{
if (node.right != null)
{
insert(node.right, value);
}
else
{
node.right = new Node(value);
}
}
}
........
public static void main(String [] args)
{
BSTree bt = new BSTree();
Node root = new Node(100);
bt.insert(root, 50);
bt.insert(root, 150);
}
You should have a look to this article. It helps to implement a tree structure and search, insert methods:
http://quiz.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
You can use standard Integer (wrapper for primitive int) object instead of creating a new object type Node. On latest java Integer/int auto-boxing is supported. Hence your method insertNode(int key) can take in Integer argument too (ensure it is not null).
EDIT: Pls ignore above comment. I did not understand your real question. You will have to overload insertNode(). I think you are right.
but where is temp when you insertNode?? With your current implementation temp is lost if root is not null.
I think you want something like
root.getLeft().insertNode(temp);
and
root.getRight().insertNode(temp);
i.e. To insert the new Node (temp) to either the left or the right subtree.
I had to do some methods about BinaryTree (no Search Binary Tree). I'm not able to do 3 methods: reflect (reflect the tree, my code don't work beacuse reflect only a part of the tree), cut and cut2. The code is:
public class BinaryTree {
protected class Node {
Integer element;
Node left;
Node right;
Node(int element) {
this.element = element;
left = right = null;
}
Node(int element, Node left, Node right) {
this.element = element;
this.left = left;
this.right = right;
}
// is leaf?
boolean isLeaf() {
return left == null && right == null;
}
}
protected Node root;
public BinaryTree() {
root = null;
}
/* doesn't work */
public void reflect() {
if (root == null)
return;
reflect(root);
}
protected void reflect(Node node) {
reflect(node.left);
reflect(node.right);
Node temp = new Node(node.left.element);
node.left.element = node.right.element;
node.right.element = temp.element;
}
/* this method had to trim the tree at level h,
if h=0, it cut the whole tree. It change the original tree */
/* doesn't work */
public void cut(int h) {
}
/* i can change parameters */
protected void cut(Node node, int h) {
}
/* this method had to trim the tree at level h,
if h=0, it cut the whole tree. It doesn't change the original tree,
it returns a new tree */
/* doesn't work */
public BinaryTree cut2(int h) {
}
/* i can change parameters */
protected BinaryTree cut2(Node node, int h) {
}
}
}
I'm not able to do the methods reflect cut and cut2. Help me please, thank you!
This smells like homework, and even though the tag was pruned, I don't think us writing complete implementations of binary trees is the right thing.
Having said that, can you explain what isn't clear about implementing both of those methods? They're pretty much equal, except for the tree copying needed for cut2. I'd implement it via a recursive private method cutInternal(Node n, int currLevel, int h) passing in the level number that we're currently at. Then, when currLevel == h we just prune both nodes and return.
You almost had reflect right. Just avoid creating new Node objects:
protected void reflect(Node node) {
if (node != null) {
reflect(node.left);
reflect(node.right);
Node temp = node.left;
node.left = node.right;
node.right = temp;
}
}
As for cut:
public void cut(int h) {
if (h == 0) {
root = null;
} else {
cut(root, h - 1);
}
}
Then you can write cut(Node, int):
protected void cut(Node node, int h) {
if (node != null) {
if (h == 0) {
node.left = node.right = null;
} else {
cut(node.left, h - 1);
cut(node.right, h - 1);
}
}
}
See if you can work out cut2 on your own using the above as a start.