I am struggling with pushing values from a Binary Search Tree into an array, but I also need them to be sorted. Here are the instructions of what is needed.
The toArray method should create and return an array containing every element in the tree in sorted order ("in order"). The capacity of this array should equal the number of elements it contains. This method should make use of the recursive private helper method toArray(BSTNode, List) to generate the array. This array will need be created as an array of Comparable objects and cast to an array of E objects. You can use Collection's toArray(E[]) method to help with the array generation.
Therefore here is my code I have so far:
public E[] toArray()
{
List<E> lista = new ArrayList<E>();
toArray(root, lista);
E[] good = (E[]) lista.toArray();
return good;
}
private void toArray(BSTNode<E> node, List<E> aList)
{
if(node.left != null)
{
aList.add(node.left.data);
}
}
Here is the rest of the code for references, but I am more focused on the toArray methods more than anything. I can't figure out how to sort them into an array. Please help.
public class BinarySearchTree<E extends Comparable<E>>
{
private BSTNode<E> root; // root of overall tree
private int numElements;
// post: constructs an empty search tree
public BinarySearchTree()
{
root = null;
}
// post: value added to tree so as to preserve binary search tree
public void add(E value)
{
root = add(root, value);
}
// post: value added to tree so as to preserve binary search tree
private BSTNode<E> add(BSTNode<E> node, E value)
{
if (node == null)
{
node = new BSTNode<E>(value);
numElements++;
}
else if (node.data.compareTo(value) > 0)
{
node.left = add(node.left, value);
}
else if (node.data.compareTo(value) < 0)
{
node.right = add(node.right, value);
}
return node;
}
// post: returns true if tree contains value, returns false otherwise
public boolean contains(E value)
{
return contains(root, value);
}
// post: returns true if given tree contains value, returns false otherwise
private boolean contains(BSTNode<E> node, E value)
{
if (node == null)
{
return false;
}
else
{
int compare = value.compareTo(node.data);
if (compare == 0)
{
return true;
}
else if (compare < 0)
{
return contains(node.left, value);
}
else
{ // compare > 0
return contains(node.right, value);
}
}
}
public void remove(E value)
{
root = remove(root, value);
}
private BSTNode<E> remove(BSTNode<E> node, E value)
{
if(node == null)
{
return null;
}
else if(node.data.compareTo(value) < 0)
{
node.right = remove(node.right, value);
}
else if(node.data.compareTo(value) > 0)
{
node.left = remove(node.left, value);
}
else
{
if(node.right == null)
{
numElements--;
return node.left;// no R child; replace w/ L
}
else if(node.left == null)
{
numElements--;
return node.right; // no L child; replace w/ R
}
else
{
// both children; replace w/ max from L
node.data = getMax(node.left);
node.left = remove(node.left, node.data);
}
}
return node;
}
private E getMax(BSTNode<E> node)
{
if(node.right == null)
{
return node.data;
}
else
{
return getMax(node.right);
}
}
public void clear()
{
root = null;
numElements--;
}
public boolean isEmpty()
{
if(numElements == 0)
{
return true;
}
else
{
return false;
}
}
public int size()
{
return numElements;
}
//My toArray Methods will go here.
public Iterator<E> iterator()
{
return new Iterator<>(root);
}
public static class Iterator<E>
{
private Stack<BSTNode<E>> stack;
public Iterator(BSTNode<E> node)
{
this.stack = new Stack<>();
while (node != null)
{
stack.push(node);
node = node.left;
}
}
public boolean hasNext()
{
return !stack.isEmpty();
}
public E next()
{
BSTNode<E> goodDays = stack.pop();
E result = goodDays.data;
if (goodDays.right != null)
{
goodDays = goodDays.right;
while (goodDays != null)
{
stack.push(goodDays);
goodDays = goodDays.left;
}
}
return result;
}
}
private static class BSTNode<E>
{
public E data;
public BSTNode<E> left;
public BSTNode<E> right;
public BSTNode(E data)
{
this(data, null, null);
}
public BSTNode(E data, BSTNode<E> left, BSTNode<E> right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
}
Wait, this is a Binary Search Tree so it's already sorted.
Then you need to walk the tree.
Given you have something like:
4
/ \
2 6
\ / \
3 5 9
To insert it you have to:
Given a tree root
A. If the tree is null, there's nothing to insert.
B. If is not null:
B.1 Insert everything on the left
B.2 Insert the tree root
B.3 Insert everything on the right
Which would look like this:
void walkAndInsert(tree, array) {
if (tree == null) {//A
return
} else { //B
walkAndInsert(tree.left) //B.1
array.add(tree.root) //B.2
walkAndInsert(tree.right) //B.3
}
}
So applying these steps on the array:
Is tree null? No, then execute step #B (insert all left, root and all right)
//B
tree =
4
/ \
2 6
\ / \
3 5 9
array =[]
We take the left branch and repeat the process (step #B.1, insert all the left):
Is tree null? No, then execute #B
//B.1
tree =
2
\
3
array =[]
Since the left branch is null, the next execution would like like this:
Is tree null ? yes, then return
//A
tree =
array = []
This will conclude step B.1, we can go now to step B.2, insert root
//B.2
tree =
2
\
3
array =[2]
Followed by step B.3 insert all from right
Is tree null? No (there's a 3 there),
//B.3
tree =
3
array =[2]
Then execute #B.1 on this tree
Is the tree empty? Yes, this concludes this B.1
//A
tree =
array =[2]
Now in B.2 we insert this root
Is tree null? No (there's a 3 there),
//B.2
tree =
3
array =[2,3]
And finally we go to B.3 insert all from right
But there's nothing there, so we just return
//A
tree =
array =[2,3]
This finishes the left branch from our very initial tree.
So after B.1 is finished on our initial tree, we execute B.2 and our data looks like:
// B.2 on the initial tree
tree =
4
/ \
2 6
\ / \
3 5 9
array =[2,3,4]
And we repeat with the right side
Is null? no, then B on the branch with 5, insert 6, and step B on the branch with 9
//B.3
tree =
6
/ \
5 9
array =[2,3,4]
// B.1
tree =
5
array =[2,3,4]
// A
tree =
array =[2,3,4]
// B.2
tree =
5
array =[2,3,4,5]
// B.2
tree =
6
/ \
5 9
array =[2,3,4,5,6]
// B.3
tree =
9
array =[2,3,4,5,6]
// A
tree =
array =[2,3,4,5,6]
// B.2
tree =
9
array =[2,3,4,5,6,9]
Working example of the steps described here
import java.util.*;
import java.lang.reflect.Array;
import static java.lang.System.out;
class Tree<E extends Comparable<E>> {
E root;
Tree<E> left;
Tree<E> right;
void insert(E element) {
if (this.root == null) {
this.root = element;
this.left = new Tree<E>();
this.right = new Tree<E>();
} else if (element.compareTo(this.root) < 0 ) {
left.insert(element);
} else {
right.insert(element);
}
}
E[] toArray() {
List<E> a = new ArrayList<>();
toArray(this, a);
#SuppressWarnings("unchecked")
final E[] r = a.toArray((E[]) Array.newInstance(a.get(0).getClass(), a.size()));
return r;
}
// instance method just to retain the generic type E
private void toArray(Tree<E> t, List<E> list) {
if (t == null || t.root == null) {
return;
} else {
toArray(t.left, list);
list.add(t.root);
toArray(t.right, list);
}
}
public static void main(String ... args) {
Tree<String> t = new Tree<>();
t.insert("hola");
t.insert("adios");
t.insert("fuimonos");
System.out.println(Arrays.toString(t.toArray()));
}
}
I figured it out. I will disclose the code and explain what's going on.
In the public I make a List that will soon be an Array List.
Then I call the toArray helper method (private) to set the values. Root for the top one and lista for the list it will go in.
After make the Array and set the size with numElements. Comparable is in there since at the very top of my code, that's what it extends.
Then put the that array into the lista.
Finally return it.
public E[] toArray()
{
List<E> lista = new ArrayList<E>();
toArray(root, lista);
E[] arr = (E[]) new Comparable[numElements];
lista.toArray(arr);
return arr;
}
In the private I do some recursion.
As long as the node is not empty(null) then the array will search for left nodes continuously until it has no left (left) therefore add that into the array.
Then adds the right ones.
private void toArray(BSTNode<E> node, List<E> aList)
{
if(node != null)
{
toArray(node.left, aList);
aList.add(node.data);
toArray(node.right, aList);
}
}
Sorry if that was hard to understand, I'm not the best at explaining things, however this worked for me.
Related
I am trying to create a class iNode that implements an Iterator to traverse a Binary Search Tree. The Iterator searches in a PreOrder traversal and can pick from any node in a tree, this node has the value of the int value.
I am familiar with using Stacks on BSTs, but am having a bit of trouble with the Iterator's hasNext() and next() methods.
I understand that logically, hasNext must check the current iNode and see if it has children. Then while that is true, the next() function will iterate through the tree starting with the "root" or value, then favoring the left children, and finally the right children. I believe that this is a simple matter of syntax and would greatly appreciate a few tips.
Expected behavior:
should return an Iterable (type Integer) of [8,3,5,6,4,2]
import java.util.Iterator;
import java.util.NoSuchElementException;
public class iNode implements Iterable<Integer> {
public final Integer value;
public final iNode left, right;
public iNode(Integer value) {
this.value = value;
this.right = null;
this.left = null;
// a node with no children / root
}
public iNode(Integer value, iNode left, iNode right) {
this.value = value;
this.left = left;
this.right = right;
// with children
}
#Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private iNode next = new iNode(value, left, right);
#Override
public boolean hasNext() {
// should return false when the current node has no children
return next != null;
}
#Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException("limit reached");
}
return next.value;
}
};
}
}
private static void printPreOrder(Node root) {
if(root == null) {
return;
}
System.out.println(root.value + "->");
printPreOrder(root.left);
printPreOrder(root.right);
}
Let recursion handle this . Just write a base case where the node is null.
private static void printPreOrder(Node root, List<Integer> list) {
if(root == null) {
return;
}
list.add(root.value);
printPreOrder(root.left);
printPreOrder(root.right);
}
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()){
int ele = itr.next();
// print element
}
if you want to store them and then use a iterator to iterate the list.
You can still use a Stack when using an iterator. Iterators are supposed to have state so that they know at which point they are at.
// to record how deep in the tree we are at
// this stores the next nodes to visit
// obviously, start with the current node, "this"
private final Deque<iNode> stack = new ArrayDeque<>(List.of(iNode.this));
#Override
public boolean hasNext() {
return !stack.isEmpty(); // has next, iff there are next nodes to visit
}
#Override
public Integer next() {
// pop will throw NSEE if the stack is empty anyway,
// so you don't need to explicitly throw one,
// unless you want a custom message of course
iNode node = stack.pop(); // we are going to return the value of this later
// the next node to visit is the left node, then the right node
// so we should push the right node first, then the left node,
// which causes the left node to be popped *first*
if (node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
return node.value;
}
Example usage:
var tree = new iNode(
8, new iNode(
3, new iNode(5), new iNode(6)
), new iNode(
4, null, new iNode(2)
)
);
for (var i : tree) {
System.out.println(i);
}
/*
8
3
5
6
4
2
*/
Okay, I've already written several methods related to my problem. Right now I have two methods that are written using recursion (addBSTRecursion (int element) and searchBSTRecursion (int element)). And now I need implement (iteratively) the BST search method (Pair<BinaryTreeNode, BinaryTreeNode> searchBST(int element)) returning the node containing the searched value and its predecessor.
if the searched element is not in the tree, the first element of the pair is null.
if the first element of the pair is a root (it has no predecessor), then the second element of the pair is null.
Here is my class Pair:
public class Pair<T1, T2> {
public T1 first;
public T2 second;
public Pair(T1 a, T2 b) {
first = a;
second = b;
}
}
This is how I managed to implement method (Pair<BinaryTreeNode, BinaryTreeNode> searchBST(int element)), but unfortunately it does not work as expected.
#Override
public Pair<BinaryTreeNode, BinaryTreeNode> searchBST(int element) {
int current = 0;
while (element != data) {
if (element < data) {
current = left.data;
} else {
current = right.data;
}
}
Pair pair = new Pair(element, current);
return pair;
}
To be honest, I don’t know yet how to correctly implement this method, I will be glad to any hints. And also at the bottom I add all my previous classes.
public abstract class BinaryTreeNode {
protected int data; // value stored in the node
protected BinaryTreeNode left, right; // left and right sub-trees
// constructor
public BinaryTreeNode(int data) {
this.data = data;
}
// recursively adds an item to the BST
// #param new data to be stored in the new node
public abstract void addBSTRecursion(int element);
// prints the tree
// for example, for a tree:
// 7
// 6 8
// 2 7 4 9
//
// write:
//
// 2
// 6
// 7
// 7
// 4
// 8
// 9
// method pseudocode
// if there is a left subtree then print the left one (recursive call)
// write out gaps (depending on level), write out data, go to new line
// if it is right, print the right one (recursive call)
// #param level the distance of the node from the root. We start from 0.
public abstract void print(int level);
// recursive searches the BST.
// returns true if it finds an element with the given value
// #param searched value searched
// #return true if the given value is in the tree, false otherwise
public abstract boolean searchBSTRecursion(int element);
// iterative lookup of values in the BST
// returns a pair: node containing the searched element and its predecessor.
// if the searched element is not in the tree, the first element of the pair is null.
// if the first element of the pair is a root (it has no predecessor), then the second element of the pair is null.
// #param searched value searched
// #return pair of nodes: the first is the node containing the value searched for, or null if not found;
// the second element of the pair is the parent of the node (or null if the value is at the root of the tree)
public abstract Pair < BinaryTreeNode, BinaryTreeNode > searchBST(int element);
}
public class Node extends BinaryTreeNode {
public Node(int data) {
super(data);
}
#Override
public void addBSTRecursion(int element) {
Node node = new Node(element);
if (element < data) {
if (left != null) {
left.addBSTRecursion(element);
} else {
left = node;
}
} else {
if (right != null) {
right.addBSTRecursion(element);
} else {
right = node;
}
}
}
#Override
public void print(int level) {
if (left != null) {
left.print(level + 4);
}
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
System.out.print(data + "\n");
if (right != null) {
right.print(level + 4);
}
}
#Override
public boolean searchBSTRecursion(int element) {
if (element == data) {
return true;
} else if (element < data) {
if (left != null && left.searchBSTRecursion(element)) {
return true;
} else {
return false;
}
} else {
if (right != null && right.searchBSTRecursion(element)) {
return true;
} else {
return false;
}
}
}
#Override
public Pair<BinaryTreeNode, BinaryTreeNode> searchBST(int element) {
int current = 0;
while (element != data) {
if (element < data) {
current = left.data;
} else {
current = right.data;
}
}
Pair pair = new Pair(element, current);
return pair;
}
}
public class Main {
public static void main(String[] args) {
Node node = new Node(8);
node.addBSTRecursion(3);
node.addBSTRecursion(10);
node.addBSTRecursion(1);
node.addBSTRecursion(6);
node.addBSTRecursion(14);
node.addBSTRecursion(4);
node.addBSTRecursion(7);
node.addBSTRecursion(13);
node.print(0);
System.out.print(node.searchBSTRecursion(15));
}
}
Ok, I have my Node class with some fields defined as an integer for the value (val) and a Node one for a reference. Also I have a second class called listaArmada with a Node head field that indicates the beginning of the list. I created a method class called borrarEle that receives a created list with some random values and an integer. The method must search within the list for nodes with the value of the given element and eliminate all nodes that contain it. It works but only removes the first element found and not the others as well. Should be able to remove any node that has that element regardless of position.
List: 9,1,2,12,14,2,7,7,1,10
value to eliminate: 7
Expected output: 9,1,2,12,14,2,1,10
Real output: 9,1,2,12,14,2,7,1,10
-------NODE CLASS
public class Nodo {
int val;
Nodo siguiente;
public Nodo(int ob, Nodo nxt){
this.val = ob;
this.siguiente = nxt;
}
}
-------------------------------SECOND CLASS
public class listaArmada {
static public Nodo head;
static public int size;
static void borrarEle(int n, listaArmada ls){
Nodo anterior = null;
if(ls.head.val == n){//EL ELEMENTO ESTÁ EN LA CABEZA
ls.head = ls.head.siguiente;
}else{
Nodo temp = ls.head;
while(temp.siguiente.val != n){
temp = temp.siguiente;
}
Nodo sg = temp.siguiente.siguiente;
temp.siguiente = sg;
}
}
The code in your question is not a minimal, reproducible example (MRE) so in the below code I added to your code in order to create a MRE. Basically, class ListaArmada is a singly linked list where each node in the list is an instance of class Nodo.
First I added method append() to class ListaArmada so as to be able to create a list. Second, I overrode method toString() in both ListaArmada and Nodo classes so as to facilitate testing and debugging.
I used the sample data you provided in your question. Also, I used OOP principles and java naming conventions.
public class ListaArmada {
public Nodo head;
public void append(int val) {
Nodo n = new Nodo(val, null);
if (head == null) {
head = n;
}
else {
Nodo next = head.getSiguiente();
Nodo prev = head;
while (next != null) {
prev = next;
next = next.getSiguiente();
}
prev.setSiguiente(n);
}
}
public void borrarEle(int n) {
if (head != null) {
Nodo curr = head;
Nodo prev = head;
while (curr != null) {
if (curr.getVal() == n) {
prev.setSiguiente(curr.getSiguiente());
if (curr == head) {
head = curr.getSiguiente();
}
}
else {
prev = curr;
}
curr = curr.getSiguiente();
}
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
Nodo curr = head;
while (curr != null) {
sb.append(curr);
curr = curr.getSiguiente();
}
sb.append("END");
return sb.toString();
}
public static void main(String[] args) {
ListaArmada la = new ListaArmada();
la.append(9);
la.append(1);
la.append(2);
la.append(12);
la.append(14);
la.append(2);
la.append(7);
la.append(7);
la.append(1);
la.append(10);
System.out.println(la);
la.borrarEle(7);
System.out.println(la);
}
}
class Nodo {
private int val;
private Nodo siguiente;
public Nodo(int ob, Nodo nxt) {
this.val = ob;
this.siguiente = nxt;
}
public int getVal() {
return val;
}
public Nodo getSiguiente() {
return siguiente;
}
public void setSiguiente(Nodo n) {
siguiente = n;
}
#Override
public String toString() {
return String.format("%d -> ", val);
}
}
The append() method simply appends a new node to the end of the list.
The while loop in your borrarEle() method is wrong. You want to iterate through all the nodes in the list. You know that you have reached the last node in the list when its siguiente is null. You also need to handle the situation where you delete the first node in the list. In that case you also have to update head in class ListaArmada.
Running the above code produces the following output.
9 -> 1 -> 2 -> 12 -> 14 -> 2 -> 7 -> 7 -> 1 -> 10 -> END
9 -> 1 -> 2 -> 12 -> 14 -> 2 -> 1 -> 10 -> END
I have got a binary tree
public class Node
{
int value;
Node left;
Node right;
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public String getValue() {
return value;
}
}
And in main I have got a function to traverse it.
For tree
5
/ \
3 7
/ \
1 2
First one creates a queue of nodes with breadth first traversal(5,3,7,1,2).
Second one returns value of a node for eg. 7 for number 2 or 2 for number 4.
private void queueOfTreaversed() {
LinkedList<Node> queue = new LinkedList<Node>();
if (root != null)
queue.add(root);
while (!queue.isEmpty()) {
Node temp = queue.removeFirst();
if (temp.getLeft() != null && temp.getRight() != null) {
traversed.add(temp); //there is a difference
queue.add(temp.getLeft());
queue.add(temp.getRight());
}
}
}
public int getValue(int n) {
LinkedList<Node> queue = new LinkedList<Node>();
if (root != null)
queue.add(root);
while (!queue.isEmpty() && n>0) {
Node temp = queue.removeFirst();
if (temp.getLeft() != null && temp.getRight() != null) {
queue.add(temp.getLeft());
queue.add(temp.getRight());
}
}
return queue.peekFirst().getValue(); //there is a difference
}
And I have got duplication of code that I do not how to get rid off.
I use traversed in meantime and pop elements from this queue so elements will not be in this order and traversed cannot be used. Could anyone give any hint?
Once you have got the traversed nodes in traversed, your getValue(int n) function can actually index into traversed to get the value you want. In your getValue(int n) function, just use code like this:
if (n < traversed.size()) {
return traversed.get(n).getValue();
}
throw new Exception("Element not existed");
To be able to use traversed, just return it in your queueOfTreaversed function.
I want to remove duplicates from sorted linked list {0 1 2 2 3 3 4 5}.
`
public Node removeDuplicates(Node header)
{
Node tempHeader = null;
if(header != null)
tempHeader = header.next;
else return header;
Node prev = header;
if((tempHeader == null)) return header ;
while(tempHeader != null)
{
if(tempHeader.data != prev.data)
{
prev.setNext(tempHeader);
}
tempHeader = tempHeader.next;
}
prev = header;
printList(prev);
return tempHeader;
}
`
prev.setNext(tempHeader) is not working correctly inside the while loop. Ideally when prev = 2 and tempHeader = 3, prev.next should be node with data = 3.
Printlist function just takes header pointer and prints the list.
Node definition is given below.
public class Node
{
int data;
Node next;
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
The loop is sorted, so you know that duplicates are going to sit next to each other. If you want to edit the list in place then, you've got to have two list pointers (which you do). The one you call tempHeader and prev, and you've got to advance them both in the the list as you go (which I don't see in the code). Otherwise, if you don't advance the prev pointer as you go, then you're always comparing the element under tempHeader to the first item in the list, which is not correct.
An easier way to do this, however, is to build a new list as you go. Simply remember the value of the last item that you appended to the list. Then if the one that you're about to insert is the same then simply don't insert it, and when you're done, just return your new list.
I can give you 2 suggestions for the above suggestion
1) Convert the linked List to Set, that will eliminate the duplicates and
Back from Set to the Linked list
Code to get this done would be
linkedList = new LinkedList<anything>(new HashSet<anything>(origList));
2) You can use LinkedHashSet, if you dont want any duplicates
In this case no return value is needed.
public void removeDuplicates(Node list) {
while (list != null) {
// Walk to next unequal node:
Node current = list.next;
while (current != null && current.data.equals(list.data)) {
current = current.next;
}
// Skip the equal nodes:
list.next = current;
// Take the next unequal node:
list = current;
}
}
public ListNode removeDuplicateElements(ListNode head) {
if (head == null || head.next == null) {
return null;
}
if (head.data.equals(head.next.data)) {
ListNode next_next = head.next.next;
head.next = null;
head.next = next_next;
removeDuplicateElements(head);
} else {
removeDuplicateElements(head.next);
}
return head;
}
By DoublyLinked List and using HashSet,
public static void deleteDups(Node n) {
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while (n != null) {
if (set.contains(n.data)) {
previous.next = n.next;
} else {
set.add(n.data);
previous = n;
}
n = n.next;
}
}
doublylinkedList
class Node{
public Node next;
public Node prev;
public Node last;
public int data;
public Node (int d, Node n, Node p) {
data = d;
setNext(n);
setPrevious(p);
}
public Node() { }
public void setNext(Node n) {
next = n;
if (this == last) {
last = n;
}
if (n != null && n.prev != this) {
n.setPrevious(this);
}
}
public void setPrevious(Node p) {
prev = p;
if (p != null && p.next != this) {
p.setNext(this);
}
}}