I'm completely new to BST and how they work if this is completely wrong it would be appreciated if I could get a link to a reference site or something. right now I'm writing a program to add values from an ArrayList of Strings to a BST and I come up with errors such as The method compareTo(Node) is undefined for the type ArrayList<String>. I thought by having extends Comparable it would account for comparing ArrayList values but I'm not using E. Also I had to add a cast to s to set it as the root but I feel like there is an easier way. I don't know if I can add ArrayList values the way I'm doing it, this is just how it looks in the book I'm using for reference. This is my code, any help would be appreciated, I already tried looking up things in the Java API and that didn't help:
public class BinarySearchTree<E extends Comparable<? super E>>
{
public void add(ArrayList<String> s, Node n) {
if (n == null)
n = (Node) s;
else if (s.compareTo(n) < 0)
add(s, n.leftChild);
else
add(s, n.rightChild);
}
}
I think this reference would be helpful to you: Binary Search Trees - Stanford Library
First of all, the Node class should extend Comparable and override the compareTo method in it. ArrayList class doesn't extend Comparable and hence the following will not work
s.compareTo(n) < 0
s being an ArrayList reference. Also, you are trying to compare an ArrayList reference with a Node reference which is totally incorrect. You need to compare two Node values.
It looks like you are trying to add the entire ArrayList as a single node of your BST. My guess is that you are supposed to construct a BST from the elements of the ArrayList. For that, I would suggest defining two functions:
public Node add(ArrayList<String> s, Node root) {
for (String elt : s) {
root = add(elt, root);
}
}
public Node add(String elt, Node root) {
if (root == null) {
root = // new Node with data set to elt
} else if (elt.compareTo(n.data()) < 0) {
root.left = add(elt, root.left);
} else if (elt.compareTo(n.data()) > 0) {
root.right = add(elt, root.right);
} else {
// duplicate element being inserted -- error?
}
return root;
}
Related
I have been given a "class" called LinkedList which has only one atributte
"Node first" which refers to the first element of a list. The way to access the other ones is that class "Node" has access to an element 'x' and his following one:
public class LinkedList<T> {
private static class Node<E> {
E elem;
Node<E> next;
Node (E elem) {
this.elem = elem;
this.next = null;
}
}
private Node<T> first;
So that, I have been ordered to do a method called "reverse" from class "LinkedList" which has to reverse the list. However, the difficulty of the exercise is that I can only re-link the attributte "first", I mean I cannot create auxiliar data structures and that type of help.
I have done this in order to achieve the last element of the list, but I dont know how to continue:
public void reverse () {
Node<T> aux = first.next;
while (aux.next != null) {
first.elem = aux.elem;
aux = aux.next;
}
first.elem = aux.elem;
}
It seems quite a theoretical question to me, so you might want to check Geek for Geeks first. Most of these questions that are used in programming courses are well explained there, including coding examples.
In this case, a well-known solution is to use three pointers: a current number, the previous number , and the next number; to keep track of nodes to update reverse links.
Check here: https://www.geeksforgeeks.org/reverse-a-linked-list/
I will receive something like:
public int count (Tree myTree){
}
I already have the Tree definition, getLeft(), getRight() methods.
I have seen some examples, but always they receive a node as parameter, I need to receive the Tree as parameter.
Could anyone please help me? I'm new on this topic.
Thanks
Here Tree is the node class itself, meaning the name is given differently.
So myTree parameter is a node itself of the given Binary Tree, here pointing to the root in the given function.
Now Tree and the node class itself in the picture below, where the right child and left child and the data of the current node are stored.
So to find out the number of nodes of a given tree,
You have to first check if the given myTree is null or not, meaning if the given myTree doesn't have any Root node only.
Then you have to return 0.
int count(Tree myTree)
{
if (myTree == null)
return 0;
int res = 0;
if (myTree.left != null && myTree.right != null)
res++;
res += (count(myTree.left) + count(myTree.right));
return res;
}
Hope it helps :D
A tree in fact is defined by its root node, but let's just say you implemented the Tree in your own way :p and that you have a function to get the root getRoot(), you can use recursion as it follows to count the number of nodes in your tree (we assume that for a node you can access the children with getLeft() and getRight(), you have to implement a function to construct a tree from a node constructTree(Node root)):
public int count (Tree myTree){
Node root = myTree.getRoot();
return root != null ?
1 + count(constructTree(root.getLeft()) +
count(contructTree(root.getRight()))
: 0;
}
Here in count (Tree myTree){ }
Tree is the Node class only and you'll receive root node as a parameter which here is myTree
Because without root node it is impossible to access tree.
And in java Collections there is no such thing as Tree. So rest assured you are on right track.
Assuming Tree == Node as you have described your problem, then one approach is to use recursion:
public static int count(Tree tree) {
Tree left = tree.getLeft();
Tree right = tree.getRight();
return 1 +
(left != null ? count(left) : 0) +
(right != null ? count(right) : 0);
}
After I made my TODOs
I know the solution is as below
public void deleteNode(Node node) {
node.data = (node.next).data;
node.next = (node.next).next;
System.gc();
}
But my question is that
How above solution differ than below another one
Is both are valid solutions and make the same functionality or not
public void deleteNode(Node node) {
node = (node.next);
System.gc();
}
When you do
node = (node.next);
you change parameter, but doesn't change any data.
Java use call by value approach (it slightly difficult to understand what does it mean to pass reference by value).
Here is little example:
void foo(int i) {
i = 2;
System.out.println(i);
}
when we call it
int j = 1;
foo(j);
System.out.println(j);
we get 2 and 1 on console.
It means that when foo is called copy of the value passed to it.
PS:
You don't need to call System.gc();.
Thanks to #talex
And I visualize the cases to be more clear
Lets assume the problem to delete following node c from the Linked List
And we ONLY have access to this node
First solution will actually delete the node
public void deleteNode(Node node) {
node.data = (node.next).data;
node.next = (node.next).next;
System.gc();
}
By copy next cell (value and pointer) to the parameter cell
So the end result
Parameter cell will be considered as deleted and Linked List will be chained correctly
Hints:
No problem that node d not used by any pointer, GC will clean
This solution will NOT work if we need to delete the last cell
Second solution will NOT delete the node
public void deleteNode(Node node) {
node = (node.next);
System.gc();
}
Thats because its ONLY change pointer of the parameter cell
So the end result
Parameter cell will NOT be deleted and Linked List still have the cell
I have made my own Deque class with the following methods:
Deque#pushLeft(E e), pushRight(E e), popLeft() and popRight().
Is it possible to make a method which could change any elements of a Deque? I would like to edit them from left and from right. So editRight(index, E newElement) and the same for editLeft.
How would I start doing this? Would I need to use an Iterator?
You have implemented your Deque as a double linked list. The simplest way to support editLeft and editRight is to just step along the links until you reach the node you wish to change.
Something like:
public void editLeft(int index, Item item) {
Node node = right;
while (node != null && index > 0) {
node = node.prev;
index--;
}
if (node != null) {
node.item = item;
} else {
throw new IllegalRangeException("Attempt to edit value with illegal index");
}
}
Deque is ADT and it could be implemented by linked list or Arrays as data structures. Your answer depends upon the type of data structure being used to store elements.and also I would suggest you to implement a peek operation and it would give you a reference of an element for edit propose .peek operation could be used by other high-level operations like delete/contains etc.
Pretty easy question:
Recursively how can I create an array of a binary search tree (in order) which uses this constructor:
public class OrderedSet<E extends Comparable<E>> {
private class TreeNode {
private E data;
private TreeNode left, right;
public TreeNode(E el) {
data = el;
left = null;
right = null;
}
}
private TreeNode root;
public int size = 0;
public OrderedSet() {
root = null;
}
In-Order means you first have to traverse the left part of the tree, so:
TreeNode tree // this is your tree you want to traverse
E[] array = new E[tree.size]; // the arrays length must be equivalent to the number of Nodes in the tree
int index = 0; // when adding something to the array we need an index
inOrder(tree, array, index); // thats the call for the method you'll create
The method itself could looks something like this:
public void inOrder(TreeNode node, E[] array, int index){
if(node == null){ // recursion anchor: when the node is null an empty leaf was reached (doesn't matter if it is left or right, just end the method call
return;
}
inOrder(node.getLeft(), array, index); // first do every left child tree
array[index++]= node.getData(); // then write the data in the array
inOrder(node.getRight(), array, index); // do the same with the right child
}
Somewhat like that. I am just not sure about the index and where it needs to be incremented. If you don't want to worry about the index or if you don't know how many nodes are in the tree, then use an ArrayList instead and transform it in the end to an array.
Normally a cleaner call method is build around the recursive method like this:
public E[] inOrderSort(TreeNode tree){
E[] array = new E[tree.size];
inOrder(tree, array, 0);
return array;
}
Thanks, that worked great. Java wouldn't allow me to make an array of generics so using your algorithm I made it work with an ArrayList (like you suggested) Here's the method (using the above constructor) just incase someone else asks the same question. (Ref is my reference to the current tree node)
public ArrayList<E> toArray() {
ArrayList<E> result = new ArrayList<E>();
toArrayHelp(root, result);
return result;
}
private void toArrayHelp(TreeNode ref, ArrayList<E> result) {
if (ref == null) {
return;
}
toArrayHelp(ref.left, result);
result.add(ref.data);
toArrayHelp(ref.right, result);
}