Searching through a BST - java

I created a BST that sets each node to a String value, I was wondering if there is a way to search through the tree but just one value at a time. So say the String in a node was "truck" is there a way to search through the tree and return "t"? This is the code I have for building the tree:
public class BinaryTree {
public Node root;
public BinaryTree tree;
public static int pos;
public static Node[] theArray;
private static class Node {
Node left;
Node right;
String data;
Node(String s) {
left = null;
right = null;
data = s;
}
}
public BinaryTree plantTree(ArrayList<String> dict) {
tree = new BinaryTree();
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
tree.add(s);
}
return tree;
}
/**
* Creates an empty binary tree
*/
public BinaryTree() {
root = null;
}
public void add(String data) {
root = add(root, data);
}
private Node add(Node node, String data) {
if (node == null) {
node = new Node(data);
} else {
if (data.compareTo(node.data) > 0) {
node.left = add(node.left, data);
} else {
node.right = add(node.right, data);
}
}
return (node);
}
}

Maybe I misunderstood your question, but it sounds like you want something to iterate through the tree. I would use the visitor pattern. (This sounds like homework anyways, so why not use standard patterns. :))
public class Node<T>{
...
public void visitDepthFirst(Visitor<T> v){
v.visit(this);
if (left != null){
left.visitDepthFirst(v);
}
if (right != null){
right.visitDepthFirst(v);
}
}
}
interface Visitor<T>{
public void visit(T t);
}
...
Node<String> root = ...;
root.visitDepthFirst(new Visitor<String>(){
public visit(String val){
if ("truck".equals(val)){
// do something
}
}
});
I'll let you figure out breadth search. Also, your node class would be more usable using generics. And your class structure is a bit confusing. Might I suggest you just use node AS the tree itself. After all, every node in a tree, is a tree itself. (read about the composite pattern)

So it appears that your trying to search through your tree by the first letter only. This will take just as long as returning the entire word. So you still have to use a BST traversal or search algorithem.

So say the String in a node was "truck" is there a way to search
through the tree and return "t"?
Really, I have no idea what this question is about.
If you have a BST then you search it using binary search. That's that.
A binary search returns true if the element is found. You can implement your own BST and not return a boolean but a Char as in t in your question and null if the value is not part of the tree.

Related

Tree-Structure does not inherit generics

My goal is to create a tree-like object structure.
For this i created a class named Node (I removed the implementation because the problem still persists without it):
public class Node<S> {
public Node<S> addChild(Node<S> node) {
return this;
}
}
Important to know is that i want to define the generic type S only in the root node, all child nodes should automatically inherit from the root node.
Something like this:
new Node<String>().addChild(
new Node<>().addChild(
new Node<>()
)
)
I restricted the addChild method to only accept Nodes with the same generic type S,
so as far as i know my child node should know that it's generic type S has to be (in this example) String. However it seems like the generic type S gets lost after instantiating a new Node, because it gives me the following Exception:
error: incompatible types: Node<Object> cannot be converted to Node<String>
The use of <> requires type inference, and the argument of the first
addChild must be a Node, and just passing new Node<>() would do - infering from the return type.
But chaining to .addChild(new Node<>()) cannot infer anything, can only provide Node<Object>. So: one cannot use <>.
The problem is (of course) that you want addChild to return the head of the list, and keep adding to the tail of the list.
Normal practice is not to create Node instances, but just use the S values.
public class Node<S> {
private S value;
private Node<S> next;
public Node(S value) {
this.value = value;
}
public static <T> void print(Node<T> root) {
if (root == null) {
System.out.println("empty");
return;
}
System.out.print(root.value);
System.out.print(" --> ");
print(root.next);
}
public static <T> Node<T> addAll(T... values) {
Node<T> root = null;
Node<T> previous = null;
for (T value : values) {
Node<T> current = new Node<>(value);
if (root == null) {
root = current;
} else {
previous.next = current;
}
previous = current;
}
return root;
}
public static void main(String[] args) {
Node<String> root = Node.addAll("a", "b", "c", "d");
print(root);
}
}
Comparable to Collections.addAll or List.of. If you keep a Node<S> last field, you could indeed create something like:
public void addLast(S value) {
last.next = new Node<>(value);
}
This also shows a serious problem of the class: an empty list is not a Node.
One could use Optional<Node<S>> or a special constant for an empty list EMPTY - without value.
The normal solution is to have a container:
public class List<S> {
private class Node {
...
}
private Node<S> root;
private Node<S> last;
private int size;
public List<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return this;
}
private int size() {
return size;
}
...
}
Now everything fits.
List<String> nodes = new List<>()
.addLast("a")
.addLast("b")
.addLast("c")
.addLast("d");
After feedback, when wanting Node references.
Then discard chaining, and make Node public again.
public Node<S> addLast() {
addLast(null);
}
public Node<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return last;
}
List<String> nodes = new List<>()
Node<String> a = nodes.addLast();
Node<String> b = nodes.addLast();
var c = nodes.addLast();
var d = nodes.addLast();
One could use var for shortness.
What you are trying to do is something like this
public class Node<T> {
private Node<T> child;
private T data = null;
public Node (T data) {
this.data = data;
}
public T getData() {
return data;
}
public Node<T> getChild() {
return child;
}
public void addChild(Node<T> child) {
this.child = child;
}
#Override
public String toString() {
return "this node's data: " + data + "; has child? " + (child != null);
}
public static void main(String[] args) {
Node<String> root = new Node<> ("parent");
Node<String> child = new Node<>("child");
root.addChild(child);
System.out.println(root);
System.out.println(child);
}
}
If you were to execute this, it will output
this node's data: parent; has child? true
this node's data: child; has child? false
this node's data: 0; has child? false
this node's data: 1; has child? false
Notice how I can create nodes of type String and Integer. However, this class is incomplete if you want to create a tree structure. The implementation of "tree" will depend on what kind of tree you are talking about. For example, a simple binary tree will have two children at most. Other types of trees could have more children. Also, adding nodes to a tree might require balancing the tree.
Now, to your question, this answer suffices. I was able to demonstrate the use of generics to create Node objects of type T.

Recursively adding a new node to the end of a LinkedList?

Having a lot of trouble trying to write a recursive method to add a new Node to the end of a LinkedList. I've been staring at this for a looooong time and still my terminal is printing blanks...if someone can help me out that would be greatly appreciated! Still trying to wrap my head around the concept of recursion. If I try to do the problem iteratively with a while loop, then I'm able to do it no problem but my assignment requires me to write it recursively. Thanks for the help :)
public class LinkedList
{
//
//Instance variable
//
private Node top;
//
//Instance and static methods below
//
//Accessor for the top Node
public Node getTop()
{
return top;
}
public void add(Object data) {
Node newNode = new Node(data,null);
addRec(top,newNode);
}
private Node addRec(Node start, Node newNode) {
if (start == null) {
start = newNode;
return start;
}
start.setLink(addRec(start.getLink(), newNode));
return start;
}
public String toString() {
String value = "";
Node current = top;
while (current != null) {
value += current.getData();
current = current.getLink();
}
return value;
}
Node class:
public class Node
{
//
//Instance variables
//
private Object data;
private Node link;
//
//Constructor
//
public Node (Object initData, Node initLink)
{
data = initData;
link = initLink;
}
//
//Accessors
//
public Object getData()
{
return data;
}
public Node getLink()
{
return link;
}
public void setData(Object data) {
this.data = data;
}
//
//Mutators
//
public void setLink(Node newLink)
{
link = newLink;
}
}
Recursively adding a node to the linked list is a fairly straightforward concept.
Lets look at the algorithm:
1] If the given node does not have a node after it (which we will call the next node), we add the current node.
2] Otherwise, we add the node to the next node. This would involve performing step 1 on the next node.
If you notice, Step 2 has a recursive call to step 1, as it is referencing the same node.
To implement this, first, we create a child class called Node, inside the LinkedList. This will require an int to store the data, and a Node that points to the next Node.
we create the method add() inside Node.
To implement step 1, we check if next is equal to null. If it is, we add the node as the next on on the linked list.
if(this.next== null)this.next= toAdd;
To implement step 2, we say otherwise, we call the method add on the next Node, and pass the value to add.
if(this.next== null)this.next= toAdd;
Now, we have to implement this in the class LinkedList.
We declare a root node, where the list starts.
Now, we declare a method that will do the following:
add a value to root.
That's it.
Recursion takes care of the rest.
Think about it, if root has a node after it, the data will be added to the next node, and so on.
Therefore, problem sorted, you have your list!
public class LinkedList
{
private Node root;
private class Node{
int data;
Node next;
public Node(int data){
this.data = data;
this.next = null;
}
public void add(Node toAdd){
if(this.next== null)this.next= toAdd;
else this.next.add(toAdd);
}
}
public LinkedList(int root){
this.root = new Node(root);
}
public void add(int toAdd){
this.root.add(new Node(toAdd));
}
}

Calling a function with a getter as parameter doesn't retain refrence?

I am having an issue with my code, I am making a Binary Search Tree data structure, and when I call a function with a node's child, then assign a value to that child within the function, it doesn't update the node's child.
//*** Pseudo-ish Code ***
class BSTNode {
private BSTNode lChild;
private BSTNode rChild;
private int key;
public BSTNode(int key) {
this.lChild = null;
this.rChild = null;
this.key = key;
}
//getters and setters for each field ^
}
class BST {
private BSTNode root;
public BST() {
this.root = null;
}
public void insert(BSTNode currentNode, int value) {
BSTNode newNode = new BSTNode(value);
if (currentNode == null) {
currentNode = newNode;
if (this.root == null) {
this.root = currentNode;
}
} else {
//ignore the newNode == currentNode value statement right now
if (newNode.getValue() < currentNode.getValue()) {
insert(currentNode.getlChild(), value);
} else if (newNode.getValue() > curNode.getValue()) {
insert(curNode.getrChild(), value);
}
}
}
//getters and setters
}
I still want to figure out the code myself, but I am curious as to why if I were to run this code with:
BST testBST = new BST();
testBST.insert(testBST.getRoot(), 10);
testBST.insert(testBST.getRoot(), 7);
System.out.print(testBST.getRoot());
System.out.print(" ");
System.out.print(testBST.getRoot().getlChild());
This will output 10 then a NullPointerException. I understand this is because somehow the 7 didn't get allocated as 10's lChild, but I don't know why? Is it a scope issue I am having, or is it because I call recursively with the getlChild() in my insert function that I don't have access to the actual private lChild field?
NOTE: I was using sysout to debug my code, and I noticed the recursion does work, and it does assign the 7 properly to currentNode, but then once the function is done running, it is like currentNode no longer references the lChild of the initial root node.
The problem is here:
BSTNode newNode = new BSTNode(value);
Each time computer is calling the recursive method insert() , it is creating a new BSTNode(). You just want to add one new BSTNode() each time but it is creating nodes again and again. For example, You want to add 3 and for this it has to call insert() 4 times. Instead of creating only 1 node it will be creating 4 nodes.
What I have done, apart of removing some errors, I have created the recursive insertValue() method in BSTNode class. So you dont have to keep track of currentNode every time you call this method. As, every Node will be calling its own insertValue() method.
//*** Pseudo-ish Code ***
class BSTNode
{
public BSTNode lChild;
public BSTNode rChild;
public int key;
public BSTNode(int key)
{
this.lChild = null;
this.rChild = null;
this.key = key;
}
/* Create INSERT function in BSTNode class so that you dont have to give the "CurrentNode" everytime
you call this method, Now you just have to pass the "Key"*/
public void insertValue(int insertValue)
{
if(insertValue < key)
{
if(lChild == null)
lChild = new BSTNode(insertValue);
else
lChild.insertValue(insertValue);
}
else if(insertValue > key)
{
if(rChild == null)
rChild = new BSTNode(insertValue);
else
rChild.insertValue(insertValue);
}
else;
}
}
class BST
{
private BSTNode root;
public BST()
{
this.root = null;
}
// just create the root if not present else it'll call the recursive method of BSTNode class
public void insert(int value)
{
if(root == null)
root = new BSTNode(value);
else
root.insertValue(value);
}
// you didn't provide these methods so i wrote my own just to get your code runing
public BSTNode getRoot()
{
return root;
}
public int getRootValue()
{
return root.key;
}
}
public class BSTMain
{
public static void main(String[] args)
{
BST testBST = new BST();
testBST.insert(10);
testBST.insert(7);
System.out.print(testBST.getRootValue());
System.out.print(" ");
System.out.print(testBST.getRoot().lChild.key);
}
}
NOTE: I have added some methods like getRoot() just to get your code working, as you haven't provided them.

Find child in non-binary tree (recursively)

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

How do I create a Binary Search Tree from a General tree

As the title states. I am trying to create a binary search tree from a general tree that I have created. The code for my general node class is:
Node<E> parent;
E data;
ArrayList<Node<E>> children = new ArrayList<Node<E>>();
public Node(E data){
this.data = data;
}
public ArrayList<Node<E>> getChildren(){
return this.children;
}
public void addChild(Node child){
int counter = 0;
for (int i = 0; i < children.size(); i++){
if (child.toString().equals(children.get(i).toString())){
System.out.println("already exists");
counter++;
}
}
if (counter > 0){}
else{
children.add(child);
}
}
public void removeChild(Node<E> child){
children.remove(child);
}
public Node<E> getChild(Node<E> child){
for (int i = 0; i < children.size(); i++){
if (children.get(i) == child){
return child;
}
}
return null;
}
public void setParent(Node parent){
this.parent = parent;
}
public Node<E> getParent(){
return this.parent;
}
public boolean isDirectory(Node node){
if (data == node.data){
return false;
}
return true;
}
public boolean hasChildren(){
return getChildren() != null;
}
public E getData(){
return this.data;
}
public String toString(){
return data.toString();
}
}//end class
And my tree class is full of methods to the brim, so to save all you guys the eye strain, my tree class consists of a root and the constructor which sets the root as the root of the tree. I know that to convert the general tree to the binary search tree, i must set my general tree root to the root of the binary search tree. My question is then where do i go from there? How do i traverse my general tree to add the nodes to the binary search tree? Any help would be appreciated.
A general tree is not binary because it may have arbitrary number of child nodes and is not search because its nodes do not have any specific order. As a consequence constructing a binary search tree from a general tree is just the same as inserting all the nodes of the general tree in the binary search tree. Please note I would not call this convert it is more constructing a binary search tree from the nodes in a general tree.

Categories

Resources