Suppose I have a node in a tree, how can I get all leaf nodes whose ancestor is this node?
I have defined the TreeNode like this:
public class TreeNode<T>
{
/** all children of the node */
private List<TreeNode<T>> children = new ArrayList<TreeNode<T>>();
/** the parent of the node, if the node is root, parent = null */
private TreeNode<T> parent = null;
/** the stored data of the node */
private T data = null;
/** the method I want to implement */
public Set<TreeNode<T>> getAllLeafNodes()
{
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
return leafNodes;
}
}
Use recursion.
if the node itself is a leaf, return it
otherwise, return all the leaf-nodes of its children
Something like this (not tested):
public Set<TreeNode<T>> getAllLeafNodes() {
Set<TreeNode<T>> leafNodes = new HashSet<TreeNode<T>>();
if (this.children.isEmpty()) {
leafNodes.add(this);
} else {
for (TreeNode<T> child : this.children) {
leafNodes.addAll(child.getAllLeafNodes());
}
}
return leafNodes;
}
Create a stack and push root node.
Stack<Node> st = new Stack<>();
st.push(root);
CL(st.peek());
Call the recursive method.
public void CL(Node root){
if (st.peek().left == null && st.peek().right == null ) {//if leaf node
System.out.println(st.peek().data);//print
st.pop();
return;
}
else{
if(st.peek().left != null){
st.add(st.peek().left);
CL(st.peek());
}
if(st.peek().right != null){
st.add(st.peek().right);
CL(st.peek());
}
}
st.pop();
}
Related
im working on java tree and getting stuck on setting toString for LinkedBinaryTree and mapping yes/no to left/right child.
files im using:
AbstractBinaryTree.java
import java.util.ArrayList;
import java.util.List;
/** An abstract base class providing some functionality of the BinaryTree interface. */
public abstract class AbstractBinaryTree<E> extends AbstractTree<E> implements BinaryTree<E> {
/** Returns the Position of p's sibling (or null if no sibling exists). */
public Position<E> sibling(Position<E> p) {
Position<E> parent = parent(p);
if (parent == null) { // p must be the root
return null;
}
if (p == left(parent)) { // p is a left child
return right(parent); // (right child might be null)
} else { // p is a right child
return left(parent); // (left child might be null)
}
}
/** Returns the number of children of Position p. */
public int numChildren(Position<E> p) {
int count = 0;
if (left(p) != null) {
count++;
}
if (right(p) != null) {
count++;
}
return count;
}
/** Returns an iterable collection of the Positions representing p's children. */
public Iterable<Position<E>> children(Position<E> p) {
List<Position<E>> snapshot = new ArrayList<>(2); // max capacity of 2
if (left(p) != null) {
snapshot.add(left(p));
}
if (right(p) != null) {
snapshot.add(right(p));
}
return snapshot;
}
/** Adds positions of the subtree rooted at Position p to the given snapshot. */
private void inorderSubtree(Position<E> p, List<Position<E>> snapshot) {
if (left(p) != null) {
inorderSubtree(left(p), snapshot);
}
snapshot.add(p);
if (right(p) != null) {
inorderSubtree(right(p), snapshot);
}
}
/** Returns an iterable collection of positions of the tree, reported in inorder. */
public Iterable<Position<E>> inorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty()) {
inorderSubtree(root(), snapshot); // fill the snapshot recursively
}
return snapshot;
}
/** Overrides positions to make inorder the default order for binary trees. */
public Iterable<Position<E>> positions() {
return inorder();
}
}
AbstractTree.java
import java.util.Iterator;
import java.util.List; // for use as snapshot iterator
import java.util.ArrayList; // for use as snapshot iterator
/** An abstract base class providing some functionality of the Tree interface. */
public abstract class AbstractTree<E> implements Tree<E> {
/** Returns true if Position p has one or more children. */
public boolean isInternal(Position<E> p) {
return numChildren(p) > 0;
}
/** Returns true if Position p does not have any children. */
public boolean isExternal(Position<E> p) {
return numChildren(p) == 0;
}
/** Returns true if Position p represents the root of the tree. */
public boolean isRoot(Position<E> p) {
return p == root();
}
/** Returns the number of children of Position p. */
public int numChildren(Position<E> p) {
int count = 0;
for (Position child : children(p))
count++;
return count;
}
/** Returns the number of nodes in the tree. */
public int size() {
int count = 0;
for (Position p : positions())
count++;
return count;
}
/** Tests whether the tree is empty. */
public boolean isEmpty() {
return size() == 0;
}
/** Returns the number of levels separating Position p from the root. */
public int depth(Position<E> p) throws IllegalArgumentException {
if (isRoot(p))
return 0;
else
return 1 + depth(parent(p));
}
/** Returns the height of the tree. */
private int heightBad() { // works, but quadratic worst-case time
int h = 0;
for (Position<E> p : positions())
if (isExternal(p)) // only consider leaf positions
h = Math.max(h, depth(p));
return h;
}
/** Returns the height of the subtree rooted at Position p. */
public int height(Position<E> p) throws IllegalArgumentException {
int h = 0; // base case if p is external
for (Position<E> c : children(p))
h = Math.max(h, 1 + height(c));
return h;
}
/** This class adapts the iteration produced by positions() to return elements. */
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> posIterator = positions().iterator();
public boolean hasNext() {
return posIterator.hasNext();
}
public E next() {
return posIterator.next().getElement();
} // return element!
public void remove() {
posIterator.remove();
}
}
/** Returns an iterator of the elements stored in the tree. */
public Iterator<E> iterator() {
return new ElementIterator();
}
/** Returns an iterable collection of the positions of the tree. */
public Iterable<Position<E>> positions() {
return preorder();
}
/** Adds positions of the subtree rooted at Position p to the given snapshot using a preorder traversal. */
private void preorderSubtree(Position<E> p, List<Position<E>> snapshot) {
snapshot.add(p); // for preorder, we add position p before exploring subtrees
for (Position<E> c : children(p))
preorderSubtree(c, snapshot);
}
/** Returns an iterable collection of positions of the tree, reported in preorder. */
public Iterable<Position<E>> preorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
preorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/** Adds positions of the subtree rooted at Position p to the given snapshot using a postorder traversal. */
private void postorderSubtree(Position<E> p, List<Position<E>> snapshot) {
for (Position<E> c : children(p))
postorderSubtree(c, snapshot);
snapshot.add(p); // for postorder, we add position p after exploring subtrees
}
/** Returns an iterable collection of positions of the tree, reported in postorder. */
public Iterable<Position<E>> postorder() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty())
postorderSubtree(root(), snapshot); // fill the snapshot recursively
return snapshot;
}
/** Returns an iterable collection of positions of the tree in breadth-first order. */
public Iterable<Position<E>> breadthfirst() {
List<Position<E>> snapshot = new ArrayList<>();
if (!isEmpty()) {
Queue<Position<E>> fringe = new LinkedQueue<>();
fringe.enqueue(root()); // start with the root
while (!fringe.isEmpty()) {
Position<E> p = fringe.dequeue(); // remove from front of the queue
snapshot.add(p); // report this position
for (Position<E> c : children(p))
fringe.enqueue(c); // add children to back of queue
}
}
return snapshot;
}
}
BinaryTree.java
/** An interface for a binary tree, in which each node has at most two children. */
public interface BinaryTree<E> extends Tree<E> {
/** Returns the Position of p's left child (or null if no child exists). */
Position<E> left(Position<E> p) throws IllegalArgumentException;
/** Returns the Position of p's right child (or null if no child exists). */
Position<E> right(Position<E> p) throws IllegalArgumentException;
/** Returns the Position of p's sibling (or null if no child exists). */
Position<E> sibling(Position<E> p) throws IllegalArgumentException;
}
LinkedBinaryTree.java
/** Concrete implementation of a binary tree using a node-based, linked structure. */
public class LinkedBinaryTree<E> extends AbstractBinaryTree<E> {
// ---------------- nested Node class ----------------
protected static class Node<E> implements Position<E> {
private E element; // an element stored at this node
private Node<E> parent; // a reference to the parent node (if any)
private Node<E> left; // a reference to the left child (if any)
private Node<E> right; // a reference to the right child (if any)
/** Constructs a node with the given element and neighbors. */
public Node(E e, Node<E> above, Node<E> leftChild, Node<E> rightChild) {
element = e;
parent = above;
left = leftChild;
right = rightChild;
}
// accessor methods
public E getElement() {
return element;
}
public Node<E> getParent() {
return parent;
}
public Node<E> getLeft() {
return left;
}
public Node<E> getRight() {
return right;
}
// update methods
public void setElement(E e) {
element = e;
}
public void setParent(Node<E> parentNode) {
parent = parentNode;
}
public void setLeft(Node<E> leftChild) {
left = leftChild;
}
public void setRight(Node<E> rightChild) {
right = rightChild;
}
} // ----------- end of nested Node class -----------
/** Factory function to create a new node storing element e. */
protected Node<E> createNode(E e, Node<E> parent, Node<E> left, Node<E> right) {
return new Node<E>(e, parent, left, right);
}
// LinkedBinaryTree instance variables
protected Node<E> root = null; // root of the tree
private int size = 0; // number of nodes in the tree
// constructor
public LinkedBinaryTree() { } // constructs an empty binary tree
// nonpublic utility
/** Validates the position and returns it as a node. */
protected Node<E> validate(Position<E> p) throws IllegalArgumentException {
if (!(p instanceof Node)) {
throw new IllegalArgumentException("Not valid position type");
}
Node<E> node = (Node<E>) p; // safe cast
if (node.getParent() == node) { // our convention for defunct node
throw new IllegalArgumentException("p is no longer in the tree");
}
return node;
}
// accessor methods (not already implemented in AbstractBinaryTree)
/** Returns the number of nodes in the tree. */
public int size() {
return size;
}
/** Returns the root Position of the tree (or null if tree is empty). */
public Position<E> root() {
return root;
}
/** Returns the Position of p's parent (or null if p is root). */
public Position<E> parent(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getParent();
}
/** Returns the Position of p's left child (or null if no child exists). */
public Position<E> left(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getLeft();
}
/** Returns the Position of p's right child (or null if no child exists). */
public Position<E> right(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return node.getRight();
}
// update methods supported by this class
/** Places element e at the root of an empty tree and returns its new Position. */
public Position<E> addRoot(E e) throws IllegalStateException {
if (!isEmpty()) {
throw new IllegalStateException("Tree is not empty");
}
root = createNode(e, null, null, null);
size = 1;
return root;
}
/** Creates a new left child of Position p storing element e; returns its Position. */
public Position<E> addLeft(Position<E> p, E e) throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getLeft() != null) {
throw new IllegalArgumentException("p already has a left child");
}
Node<E> child = createNode(e, parent, null, null);
parent.setLeft(child);
size++;
return child;
}
/** Creates a new right child of Position p storing element e; returns its Position. */
public Position<E> addRight(Position<E> p, E e) throws IllegalArgumentException {
Node<E> parent = validate(p);
if (parent.getRight() != null) {
throw new IllegalArgumentException("p already has a right child");
}
Node<E> child = createNode(e, parent, null, null);
parent.setRight(child);
size++;
return child;
}
/** Replaces the element at Position p with e and returns the replaced element. */
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E temp = node.getElement();
node.setElement(e);
return temp;
}
/** Attaches trees t1 and t2 as left and right subtrees of external p. */
public void attach(Position<E> p, LinkedBinaryTree<E> t1, LinkedBinaryTree<E> t2) throws IllegalArgumentException {
Node<E> node = validate(p);
if (isInternal(p)) {
throw new IllegalArgumentException("p must be a leaf");
}
size += t1.size() + t2.size();
if (!t1.isEmpty()) { // attach t1 as left subtree of node
t1.root.setParent(node);
node.setLeft(t1.root);
t1.root = null;
t1.size = 0;
}
if (!t2.isEmpty()) { // attach t2 as right subtree of node
t2.root.setParent(node);
node.setRight(t2.root);
t2.root = null;
t2.size = 0;
}
}
/** Removes the node at Position p and replaces it with its child, if any. */
public E remove(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
if (numChildren(p) == 2) {
throw new IllegalArgumentException("p has two children");
}
Node<E> child = (node.getLeft() != null ? node.getLeft() : node.getRight());
if (child != null) {
child.setParent(node.getParent()); // child's grandparent becomes its parent
}
if (node == root) {
root = child; // child becomes root
} else {
Node<E> parent = node.getParent();
if (node == parent.getLeft()) {
parent.setLeft(child);
} else {
parent.setRight(child);
}
}
size--;
E temp = node.getElement();
node.setElement(null); // helps garbage collection
node.setLeft(null);
node.setRight(null);
node.setParent(node); // our convention for defunct node
return temp;
}
public String toString(Node<E> root) {
String result = "";
if (root != null) {
return "";
} else {
int depth = depth(root);
for (int i = 0; i < depth; i++) {
result = result + " ";
}
result = result + "-" + root.getElement().toString() + "\n";
result = result + toString(root.left);
result = result + toString(root.right);
}
return result;
}
} // ----------- end of LinkedBinaryTree class -----------
LinkedQueue.java
/** Realization of a FIFO queue as an adaptation of a SinglyLinkedList. All operations are performed in constant time. */
public class LinkedQueue<E> implements Queue<E> {
/** The primary storage for elements of the queue */
private SinglyLinkedList<E> list = new SinglyLinkedList<>(); // an empty list
/** Constructs an initially empty queue. */
public LinkedQueue() {
} // new queue relies on the initially empty list
/** Returns the number of elements in the queue. */
public int size() {
return list.size();
}
/** Tests whether the queue is empty. */
public boolean isEmpty() {
return list.isEmpty();
}
/** Inserts an element at the rear of the queue. */
public void enqueue(E element) {
list.addLast(element);
}
/** Returns, but does not remove, the first element of the queue. */
public E first() {
return list.first();
}
/** Removes and returns the first element of the queue. */
public E dequeue() {
return list.removeFirst();
}
/** Produces a string representation of the contents of the queue. (from front to back). This exists for debugging purposes only. */
public String toString() {
return list.toString();
}
}
Position.java
public interface Position<E> {
E getElement() throws IllegalStateException;
}
Queue.java
public interface Queue<E> {
/** Returns the number of elements in the queue. */
int size();
/** Tests whether the queue is empty. */
boolean isEmpty();
/** Inserts an element at the rear of the queue. */
void enqueue(E e);
/** Returns, but does not remove, the first element of the queue. */
E first();
/** Removes and returns the first element of the queue. */
E dequeue();
}
SinglyLinkedList.java
public class SinglyLinkedList<E> implements Cloneable {
// ---------------- nested Node class ----------------
/** Node of a singly linked list, which stores a reference to its element and to the subsequent node in the list (or null if this is the last node).
*/
private static class Node<E> {
/** The element stored at this node */
private E element; // reference to the element stored at this node
/** A reference to the subsequent node in the list */
private Node<E> next; // reference to the subsequent node in the list
/** Creates a node with the given element and next node. */
public Node(E e, Node<E> n) {
element = e;
next = n;
}
// Accessor methods
/** Returns the element stored at the node. */
public E getElement() {
return element;
}
/** Returns the node that follows this one (or null if no such node). */
public Node<E> getNext() {
return next;
}
// Modifier methods
/** Sets the node's next reference to point to Node n. */
public void setNext(Node<E> n) {
next = n;
}
} // ----------- end of nested Node class -----------
// instance variables of the SinglyLinkedList
/** The head node of the list */
private Node<E> head = null; // head node of the list (or null if empty)
/** The last node of the list */
private Node<E> tail = null; // last node of the list (or null if empty)
/** Number of nodes in the list */
private int size = 0; // number of nodes in the list
/** Constructs an initially empty list. */
public SinglyLinkedList() {
} // constructs an initially empty list
// access methods
/** Returns the number of elements in the linked list. */
public int size() {
return size;
}
/** Tests whether the linked list is empty. */
public boolean isEmpty() {
return size == 0;
}
/** Returns (but does not remove) the first element of the list. */
public E first() { // returns (but does not remove) the first element
if (isEmpty())
return null;
return head.getElement();
}
/** Returns (but does not remove) the last element of the list. */
public E last() { // returns (but does not remove) the last element
if (isEmpty())
return null;
return tail.getElement();
}
// update methods
/** Adds an element to the front of the list. */
public void addFirst(E e) { // adds element e to the front of the list
head = new Node<>(e, head); // create and link a new node
if (size == 0)
tail = head; // special case: new node becomes tail also
size++;
}
/** Adds an element to the end of the list. */
public void addLast(E e) { // adds element e to the end of the list
Node<E> newest = new Node<>(e, null); // node will eventually be the tail
if (isEmpty())
head = newest; // special case: previously empty list
else
tail.setNext(newest); // new node after existing tail
tail = newest; // new node becomes the tail
size++;
}
/** Removes and returns the first element of the list. */
public E removeFirst() { // removes and returns the first element
if (isEmpty())
return null; // nothing to remove
E answer = head.getElement();
head = head.getNext(); // will become null if list had only one node
size--;
if (size == 0)
tail = null; // special case as list is now empty
return answer;
}
public boolean equals(Object o) {
if (o == null)
return false;
if (getClass() != o.getClass())
return false;
SinglyLinkedList other = (SinglyLinkedList) o; // use nonparameterized type
if (size != other.size)
return false;
Node walkA = head; // traverse the primary list
Node walkB = other.head; // traverse the secondary list
while (walkA != null) {
if (!walkA.getElement().equals(walkB.getElement()))
return false; // mismatch
walkA = walkA.getNext();
walkB = walkB.getNext();
}
return true; // if we reach this, everything matched successfully
}
public SinglyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create the initial copy
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone(); // safe cast
if (size > 0) { // we need independent chain of nodes
other.head = new Node<>(head.getElement(), null);
Node<E> walk = head.getNext(); // walk through remainder of original list
Node<E> otherTail = other.head; // remember most recently created node
while (walk != null) { // make a new node storing same element
Node<E> newest = new Node<>(walk.getElement(), null);
otherTail.setNext(newest); // link previous node to this one
otherTail = newest;
walk = walk.getNext();
}
}
return other;
}
public int hashCode() {
int h = 0;
for (Node walk = head; walk != null; walk = walk.getNext()) {
h ^= walk.getElement().hashCode(); // bitwise exclusive-or with element's code
h = (h << 5) | (h >>> 27); // 5-bit cyclic shift of composite code
}
return h;
}
/** Produces a string representation of the contents of the list. This exists for debugging purposes only. */
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = head;
while (walk != null) {
sb.append(walk.getElement());
if (walk != tail)
sb.append(", ");
walk = walk.getNext();
}
sb.append(")");
return sb.toString();
}
}
Tree.java
import java.util.Iterator;
/** An interface for a tree where nodes can have an arbitrary number of children. */
public interface Tree<E> extends Iterable<E> {
Position<E> root();
Position<E> parent(Position<E> p) throws IllegalArgumentException;
Iterable<Position<E>> children(Position<E> p) throws IllegalArgumentException;
int numChildren(Position<E> p) throws IllegalArgumentException;
boolean isInternal(Position<E> p) throws IllegalArgumentException;
boolean isExternal(Position<E> p) throws IllegalArgumentException;
boolean isRoot(Position<E> p) throws IllegalArgumentException;
int size();
boolean isEmpty();
Iterator<E> iterator();
Iterable<Position<E>> positions();
}
and this is my driver that i have tried and struggled with!!
when i run the output for the tree is not what i am expected~~
Tree
-----
LinkedBinaryTree#5caf905d
PartA_Driver.java
import java.util.Scanner;
public class PartA_Driver {
public static void main(String[] args) {
// Output should look like
// - A |A|
// - B / \
// - C |B| |C|
// - D / \
// - E |D| |E|
// - F / \
// - G |F| |G|
LinkedBinaryTree<String> tree = new LinkedBinaryTree<>();
Position<String> A = tree.addRoot("Are you nervous?");
Position<String> B = tree.addLeft(A, "Saving Account.");
Position<String> C = tree.addRight(A, "Will you need to access most of the money within the next 5 years?");
Position<String> D = tree.addLeft(C, "Money market fund.");
Position<String> E = tree.addRight(C, "Are you willing to accept risks in exchange for higher expected returns?");
Position<String> F = tree.addLeft(E, "Stock portfolio.");
Position<String> G = tree.addRight(E, "Diversified portfolio with stocks, bonds, and short-term instruments.");
System.out.println("Tree\n-----");
System.out.println(tree.toString() + "\n");
// Are you nervous?
// Yes/ \No
// Saving Account. Will you need to access most of the
// money within the next 5 years?
// Yes/ \No
// Money market fund. Are you willing to accept risks in
// exchange for higher expected returns?
// Yes/ \No
// Stock portfolio. Diversified portfolio with stocks,
// bonds, and short-term instruments.
Scanner scanner = new Scanner(System.in);
System.out.println("Are you nervous? (yes/no)");
String decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Saving Account.");
} else {
System.out.println("Will you need to access most of the money within the next 5 years? (yes/no)");
decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Money market fund.");
} else {
System.out.println("Are you willing to accept risks in exchange for higher expected returns? (yes/no)");
decision = scanner.nextLine();
if (decision.equalsIgnoreCase("yes")) {
System.out.println("Stock portfolio.");
} else {
System.out.println("Diversified portfolio with stocks, bonds, and short-term instruments.");
}
}
}
}
}
I've got this BST I've built and trying to follow java code conventions I decided to fix around some of the access modifiers and add some getters and setters but now my entire code is giving me lots of problems in the execution and I cannot figure out why.
This is my Node class.
/**
* A class that implements a binary tree's node. It contains the data inside each node of the tree.
*/
public class Node {
private int data;
private Node left;
private Node right;
/**
* Constructor initializing the data of the node.
*
* #param data The numeric value of each node as an Integer.
*/
public Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
This is the tree class.
import java.util.ArrayList;
import java.util.List;
/** Class implementation of a binary tree , containing helper classes and methods. */
public class BinaryTree {
private Node root;
private List<Integer> nodes = new ArrayList<>();
/** Constructor initializing the root node of the tree. */
public BinaryTree() {
root = null;
}
public Node getRoot() {
return root;
}
private Node insertNode(Node node, int dataBeingInserted) {
if (node == null) {
node = new Node(dataBeingInserted);
return node;
}
if (node.getData() > dataBeingInserted) {
insertNode(node.getLeft(), dataBeingInserted);
} else if (node.getData() < dataBeingInserted) {
insertNode(node.getRight(), dataBeingInserted);
}
return node;
}
/**
* Method that inserts nodes into the binary tree. If the tree is empty , a new root node is
* initialized.
*
* #param dataBeingInserted The number to be inserted as an integer.
*/
public void insertNode(int dataBeingInserted) {
root = insertNode(root, dataBeingInserted);
}
private Node searchTree(Node node, int dataBeingSearched) {
if (node == null || node.getData() == dataBeingSearched) {
return node;
}
if (node.getData() > dataBeingSearched) {
return searchTree(node.getLeft(), dataBeingSearched);
}
return searchTree(node.getRight(), dataBeingSearched);
}
/**
* Method that recursively searches for our element through the tree. If the value is present in
* the root node , or there aren't any nodes in the tree , the method returns the root node. If
* the value we're looking for is smaller than the root node's value , we search for our value in
* the left subtree , otherwise we search for it in the right subtree.
*
* #param dataBeingSearched User's value.
* #return Recursive call of the method.
*/
public Node searchTree(int dataBeingSearched) {
return searchTree(root, dataBeingSearched);
}
private String inorderTraversal(Node node) {
if (node == null) {
return "";
}
inorderTraversal(node.getLeft());
nodes.add(node.getData());
inorderTraversal(node.getRight());
return nodes.toString();
}
/**
* An implementation of the In-order traversal. First the left subtree is visited and printed
* accordingly, then we visit and print the root and after that we visit and print the right
* subtree.
*/
public String inorderTraversal() {
return inorderTraversal(root);
}
}
And those are some tests I wrote just to try some stuff.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/** Binary tree operations tests. */
class BinaryTreeTests {
/** Testing whether the answer is correct if we search for the root value of the tree. */
#Test
void isSearchWorking() {
BinaryTree tree = new BinaryTree();
tree.insertNode(10);
tree.insertNode(30);
tree.insertNode(35);
tree.insertNode(29);
assertEquals(tree.getRoot(), tree.searchTree(20));
}
/** Testing whether the root changes it's value from null after a single insertion. */
#Test
void isInsertWorking() {
BinaryTree tree = new BinaryTree();
assertNotNull(tree.getRoot());
}
#Test
void inOrderTraversalPrint() {
BinaryTree tree = new BinaryTree();
tree.insertNode(10);
tree.insertNode(30);
tree.insertNode(35);
tree.insertNode(29);
assertEquals("[10, 20, 29, 30, 35]", tree.inorderTraversal());
}
#Test
void inOrderTraversalSameElement() {
BinaryTree tree = new BinaryTree();
tree.insertNode(1);
tree.insertNode(1);
tree.insertNode(1);
tree.insertNode(1);
tree.insertNode(1);
tree.insertNode(1);
assertEquals("[1]", tree.inorderTraversal());
}
}
So before I set the data , left and right variables in the Node class to public , everything was working just fine , now that they are private , only the last test passes for some reason.
isInsertWorking() is giving me expected not
inOrderTraversalPrint() is giving me just [10] instead of [10, 20, 29, 30, 35]
isSearchWorking() says expected node got null.
I currently do not know how to handle these things , I think my recursions might be incorrect but I cannot think of a way to fix them.
The main problem was in insertNode() function which I have fixed. There was a bug in searchTree() function and also I cleared the list nodes whenever inorderTraversal() is called since the tree can be modified between two inorderTraversal() calls.
import java.util.ArrayList;
import java.util.List;
/**
* A class that implements a binary tree's node. It contains the data inside each node of the tree.
*/
class Node {
private int data;
private Node left;
private Node right;
/**
* Constructor initializing the data of the node.
*
* #param data The numeric value of each node as an Integer.
*/
public Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
/** Class implementation of a binary tree , containing helper classes and methods. */
class BinaryTree {
private Node root;
private List<Integer> nodes = new ArrayList<>();
/** Constructor initializing the root node of the tree. */
public BinaryTree() {
root = null;
}
public Node getRoot() {
return root;
}
private Node insertNode(Node node, int dataBeingInserted) {
if (node == null)
return new Node(dataBeingInserted);
if (node.getData() == dataBeingInserted)
return root;
if (node.getData() < dataBeingInserted) {
if (node.getRight() != null)
return insertNode(node.getRight(), dataBeingInserted);
else
node.setRight(new Node(dataBeingInserted));
} else if (node.getData() > dataBeingInserted) {
if (node.getLeft() != null)
return insertNode(node.getLeft(), dataBeingInserted);
else
node.setLeft(new Node(dataBeingInserted));
}
return root;
}
/**
* Method that inserts nodes into the binary tree. If the tree is empty , a new root node is
* initialized.
*
* #param dataBeingInserted The number to be inserted as an integer.
*/
public void insertNode(int dataBeingInserted) {
root = insertNode(root, dataBeingInserted);
}
private Node searchTree(Node node, int dataBeingSearched) {
if (node == null || node.getData() == dataBeingSearched) {
return node;
}
if (node.getData() > dataBeingSearched) {
return searchTree(node.getLeft(), dataBeingSearched);
} else {
return searchTree(node.getRight(), dataBeingSearched);
}
}
/**
* Method that recursively searches for our element through the tree. If the value is present in
* the root node , or there aren't any nodes in the tree , the method returns the root node. If
* the value we're looking for is smaller than the root node's value , we search for our value in
* the left subtree , otherwise we search for it in the right subtree.
*
* #param dataBeingSearched User's value.
* #return Recursive call of the method.
*/
public Node searchTree(int dataBeingSearched) {
return searchTree(root, dataBeingSearched);
}
private String inorderTraversal(Node node) {
if (node == null) {
return "";
}
inorderTraversal(node.getLeft());
nodes.add(node.getData());
inorderTraversal(node.getRight());
return nodes.toString();
}
/**
* An implementation of the In-order traversal. First the left subtree is visited and printed
* accordingly, then we visit and print the root and after that we visit and print the right
* subtree.
*/
public String inorderTraversal() {
nodes.clear(); // clear the previous state
return inorderTraversal(root);
}
}
I've got a class Node
class Node{
int val;
Node parent;
Node left;
Node right;
public Node (int val){
this.val = val;
}
}
And I have a few methods:
public class Tree{
public Node root = null;
void insertNodeSorted(Node x, Node tree) {
if (x.val < tree.val) {
if (tree.left == null) {
tree.left = x;
}
else
insertNodeSorted(x, tree.left);
}
else {
if (tree.right == null) {
tree.right = x;
}
else
insertNodeSorted(x, tree.right);
}
} // end insertNodeSorted
void deleteNodeSorted(Node x) {
if (root == null)
return;
else
root = deleteNodeSorted(x, root);
}
Node deleteNodeSorted(Node x, Node tree) {
if (x.val < tree.val)
tree.left = deleteNodeSorted(x, tree.left);
else if (x.val > tree.val)
tree.right = deleteNodeSorted(x, tree.right);
else
tree = replaceNodeSorted(tree);
return tree;
} // end deleteNodeSorted
// Additional Method
Node replaceNodeSorted(Node tree) {
if (tree.right == null)
tree = tree.left;
else if (tree.left == null)
tree = tree.right;
else
tree.right = findReplacement(tree.right, tree);
return tree;
} // end replaceNodeSorted
Node findReplacement(Node tree, Node replace) {
if (tree.left != null)
tree.left = findReplacement(tree.left, replace);
else {
replace.val = tree.val;
tree = tree.right;
}
return tree;
} // end findReplacement
And I'd like to compile the Tree, but I don't know what I exactly I need to write in the main method.
public static void main(String[] args){
Tree t = new Tree();
t.insertNodeSorted();
What do I have to write in the brackets in order to print the Tree? (I know I still have to add System.out.println(val); in the methods..)
You defined a variable holding the root node, so it is not necessary to pass the parameter tree for the method insertNodeSorted. You can use always the root node.
Add a method taking only one parameter.
public void insertNodeSorted(Node x) {
if (root == null) {
root = x;
return;
}
insertNodeSorted(x, root);
}
Define the other method with two parameters as private
private void insertNodeSorted(Node x, Node tree) {
...
}
Now you can insert elements as follow:
Tree t = new Tree();
t.insertNodeSorted(new Node(1));
t.insertNodeSorted(new Node(134));
t.insertNodeSorted(new Node(13));
t.insertNodeSorted(new Node(4));
...
I have TreeNode class - implementation of the node of the non-binary tree (List<TreeNode> children).
I need find the first node with the given data among the children of this. I wrote some method, but there is some problem obviously (java.lang.AssertionError: Failed to find a child with not-null data: expected:<2> but was:<null>). (if data is null I need to return first child with null data).
public TreeNode findChild(Object data) {
if (data == null) {
Iterator<TreeNode> a = getChildrenIterator();
TreeNode tmp;
while (a.hasNext()) {
tmp = a.next();
if (tmp.getData()==null) return tmp;
tmp.findChild(data);
}
}else
{
Iterator<TreeNode> a = getChildrenIterator();
TreeNode tmp;
while (a.hasNext()) {
tmp = a.next();
if (data.equals(tmp.getData())) return tmp;
tmp.findChild(data);
}
}
return null;
}
Your recursion isn't correct. You should be returning the result of tmp.findChild() if it returns a non-null value.
You also need to consider whether you're supposed to be implementing a depth-first or breadth-first search.
The problem is within the fact you don't return the result of the recursive call.
Maybe the following code will help:
import java.util.*;
public class TreeNode
{
// Constructor
public TreeNode()
{
children = new ArrayList<TreeNode>();
node_data = null;
}
// Get node's data
public Object getData()
{
return (node_data);
}
// Set node's data
public void setData(Object data)
{
node_data = data;
}
// Find the node with specified data
// Return null if not found
public TreeNode findChild(Object data)
{
// Maybe we're the one we're looking for
if (equalData(data))
return (this);
// Search within child nodes
Iterator<TreeNode> it;
TreeNode node;
it = getChildrenIterator();
while (it.hasNext())
{
node = findChild(it.next());
if (node != null)
return (node);
}
// If we get here, we didn't find it
return (null);
} // findChild
// Return whether specified data equals ours
private boolean equalData(Object data)
{
if (node_data == null)
return (data == null);
else
return (node_data.equals(data));
}
// Return iterator over node's children
private Iterator<TreeNode> getChildrenIterator()
{
return (children.iterator());
}
// The node's children
private List<TreeNode> children;
// The node's data
private Object node_data;
} // class TreeNode
I have a java bean class :
class Node{
int id, parentId;
String value;
List<Node> childs;
}
How could i find a parent node in this hierarchy and insert a child node in the child list of parent node.
relationship between to node is defined as :
if node1.id == node2.parentid then node2 will be in child list of node1.
This can be Nth level hierarchy.
In order to find a node in that hierarchy, you'll have to implement a method for traversing. I suggest using a recursive method and employ either a breadth-first or depth-first search pattern. Once you've located the correct Node, insert the child.
For instance:
public Node search(Node root, int searchId) {
if (root.id == searchId) {
return root;
} else {
for (Node child : root.childs) {
Node node = search(child, searchId);
if (node != null) {
return node;
}
}
}
return null;
}
public void insert(Node node) {
Node parent = search(root, node.parentId);
if (node != null) {
parent.childs.add(node);
}
}
Try something like this
insertNode(Node nodeToInsert, Node anyNodeInHirarchy) {
Node parent = getParentNodeById(anyNodeInHirarchy.parentId);
if(parent.Id == nodeToInsert.parentId) {
parent.childs.add(nodeToInsert);
} else {
insertNode(nodeToInsert, parent)
}
}
return getParentNodeById(int nodeId) {
// Find node by id and return
return node;
}
easily :
childNode.setParentId(parentNode.getId());
parentNode.getChilds().add(childNode);
Fast way of doing it is
Guid should point the object easily so that you can point nth node easily.
Generate a Single Random GUID
for eg : say 45892
Root node will point to that id.
child will point in the pattern Parent_ID+"-"+Index_Number
If consider three child will have 45892-0, 45892-1, 45892-2
And child of first node becomes - 45892-0-1, 45892-0-2
So you can travel directly using the id as faster and need not search, search time will be saved.
If you don't understand please comment. I will show in programming.
Note : ID length grows as depends on your level of usage.
If you have data already in the db or some persistent store.then you can prefer jgitter code. if not you can prefer this.
class Node {
public String id;
public String parentId;
public List<Node> childs;
}
class Operation {
public Node getChildNodeByID(Node root,String parentId) {
String[] keys = parentId.split("-");
Node parentNode = root;
int index = 0;
for(String key : keys ) {
if(index == 0) {
if( !root.id.equals(key) ) {
throw new IllegalArgumentException("Root node does not match so parent node will not be found in this node");
}
}else {
int myIndex = Integer.parseInt(key);
if( parentNode.childs.getSize() > myIndex ) {
parentNode = parentNode.childs.get(myIndex);
}else {
throw new IllegalArgumentException("Parent Node does not exist");
}
}
index++;
}
return parentNode;
}
public insert(Node node,Node root) {
Node parentNode = getChildNodeByID(root,node.parentId);
node.id = node.parentId+"-"+parentNode.childs.getSize();
parentNode.childs.add(node);
}
}