Binary search tree method needed: find minimum value node - java

Anyone could help me do this: I need a public method for my binary search tree ADT that returns a reference to the information in the node with the smallest value in the tree. The signature of the method is:
public T min()
A. Design an interative version of the method.
B. Design a reccursive version of the method.
C. Which approach is better? Explain please.
This is not a HW or anything, its a practice for myself.

As i think that if i gave you the solution you will not learn, i'll give a link to you read more about Binary Search Tree: http://en.wikipedia.org/wiki/Binary_search_tree
After that comment, My way:
public T min() {
return recMin(root).getInfo();
}
public BSTnode<T> recMin(BSTnode<T> tree) {
if (tree == null) {
throw new NoSuchElementException();
}
if (tree.left == null) {
return tree;
}
return recMin(tree.left);
}
public T IterationMin(BSTnode<T> tree) {
if (tree == null) {
throw new NoSuchElementException();
}
while (tree.left != null) {
tree = tree.left;
}
return tree.getInfo();
}

On the matter of whether iterative or recursive is better. It really depends. In general recursive solutions tend to be easier to understand, but slower since they consume more and more stack space proportional to the depth of recursion. In this case however, you can come up with a tail-recursive solution which should be easy to understand and just as efficient as the iterative solution.
public BSTNode<T> findMin(BSTNode<T> node) {
if (node.left == null) // if there is no left, we are done
return node;
return findMin(node.left); // recursively search on the left-child
}
Start by calling this method on the head node.

A binary search tree has a lower value to the left always, correct? So, you should always go left when you can. If you can't, then you've reached the lowest value.

Related

Compilation error while implementing the Depth first search Recursively

I am new to using recursion for my methods. I tend to steer away from them for quite a few reasons. However, for a project, it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph.
Since I am not too well versed in recursion, I don't understand why I am getting the following error.
This method must return a result of type LinkedList.Node
The code I have currently is:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
DFSTime(node.nextNode);
}
}
It is unfinished code since I still need to implement some logic, however, I don't understand how to eliminate the error. Is there something very basic that I am missing?
The reason of the compilation error is pretty trivial. The compiler clearly tells that didn't provide the result to return for all possible cases.
The more important is that your current approach is not correct.
it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph
There are crucial things to consider:
Field nextNode is very suspicious. If each Node holds a reference pointing to a single node only, in fact the data structure you've created by definition isn't a Graph, but a Singly linked list. And doesn't make sense to implement DFS for a list. Every node should point to a collection of nodes, no to a single node.
You have to distinguish somehow between unvisited nodes and nodes that are already visited. Or else you might and up with infinite recursion. For that, you can define a boolean field isVisited inside the Node, or place every visited node into a HashSet.
Since you've chosen to create a recursive implementation of DFS, you don't need to create a stack. It's required only for iterative implementation.
Don't overuse global variables. I guess you might want to be able to check whether it is possible to reach different airports of destination without reinstantiating the graph.
Use getters and setters instead of accessing fields directly. It's a preferred practice in Java.
Your method might look like this (it's not necessary that element should be of type String it's just an illustration of the overall idea):
public Node DFSTime(Node node, String destinationAirport){
if(node == null || node.isVisited()) {
return null;
}
if (node.getElement().equals(destinationAirport)) {
System.out.println("The destination airport was found");
return node;
}
node.setVisited(true);
for (Node neighbour: node.getNeighbours()) {
Node result = DFSTime(neighbour, destinationAirport);
if (result != null) return result;
}
return null;
}
And the node might look like this:
public class Node {
private String element;
private List<Node> neighbours;
private boolean isVisited;
public Node(String element, List<Node> neighbours) {
this.element = element;
this.neighbours = neighbours;
}
public void setVisited(boolean visited) {
isVisited = visited;
}
public boolean isVisited() {
return isVisited;
}
public void addNeighbours(Node neighbour) {
neighbours.add(neighbour);
}
public String getElement() {
return element;
}
public List<Node> getNeighbours() {
return neighbours;
}
}
You should have a default return statement at the end of the function after the closing of the else.
In methods conditional blocks (if-else), you need to make sure you are returning appropriate Type from all conditional statements, so that there is no compile-time error. In your case, else block is recursively calling DFSTime(..) without returning anything.
You might want to return reference which gets called via recursive call, something like below:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
Node node = DFSTime(node.nextNode);
return node;
}
}

Why do I need a helper method to recursively search a binary search tree?

Here is the code for the implementation of the Binary Search Tree:
public class BST<T extends Comparable<T>> {
BSTNode<T> root;
public T search(T target)
{
//loop to go through nodes and determine which routes to make
BSTNode<T> tmp = root;
while(tmp != null)
{
//c can have 3 values
//0 = target found
//(negative) = go left, target is smaller
//(positive) = go left, target is greater than current position
int c = target.compareTo(tmp.data);
if(c==0)
{
return tmp.data;
}
else if(c<0)
{
tmp = tmp.left;
}
else
{
tmp = tmp.right;
}
}
return null;
}
/*
* Need a helper method
*/
public T recSearch(T target)
{
return recSearch(target, root);
}
//helper method for recSearch()
private T recSearch(T target, BSTNode<T> root)
{
//Base case
if(root == null)
return null;
int c = target.compareTo(root.data);
if(c == 0)
return root.data;
else if(c<0)
return recSearch(target, root.left);
else
return recSearch(target, root.right);
}
Why do I need the recursive helper method? Why can't I I just use "this.root" to carry out the recursive process that is taking place? Furthermore, if screwing up the root property of the object this method is being called on is a problem, then how is does the helper method prevent this from happening? Does it just create a pointer that is separate from the this.root property, and therefore won't mess up the root property of the object that the method is being called on?
Sorry if the question doesn't seem straight forward, but if anyone can enlighten me on what's exactly going on behind the scenes I would really appreciate it.
The method needs a starting point. It needs to have a non changing Target node and it needs to compare it with some other node to see if they are a match lets call this node current instead of root since it is the current Node the recursive method is evaluating. There really isn't a concise way of doing this when using a recursive method other than using a helper function and passing in both variables (this is the case for many recursive methods). As you said stated if you updated root you would completely alter your tree when going left or right which you wouldn't want to do. The helper function is used because it gives your recursive method a starting point. And it also keeps track of the current node you are working on as you said the method points to the Node object being evaluated but doesn't make any changes. When going left or right it doesn't modify anything it just passes in a reference to the left or right node and continues to do this until the target is found or the base case is hit.

contains(int aData) with Recursion Linked List Java

I am having problems trying to check if a value is in a linked list or not using recursion. The values in the linked list are between 0 and 5. If the value is in the linked list, the method should return true. However, I am getting wild answers across the board if the value is indeed in the linked list. Some numbers will return false, and some will return true. I am not sure why it is doing this. Thanks!
public boolean contains(int aData)
{
Node currentNode = firstNode;
if(currentNode == null) {
return false;
}
if(currentNode.data == aData) {
return true;
}
else {
return false;
}
}
You're only checking one node (the first node). You're going to be needing something like this:
public boolean contains(int aData, Node node)
{
Node currentNode = node;
// base case; if this node is null, return false
if(currentNode == null) {
return false;
}
// if this node contains the data, return true, otherwise, check next nodes.
if(currentNode.data == aData) {
return true;
} else {
return contains(aData, currentNode.next);
}
}
You can call the above function starting with the head node
contains(5, headNode);
and it will run through your entire list until either a) it finds the data, or b) it has exhausted all options and the data was not found.
As has been mentioned, you are not using recursion and are only checking the first Node. If you want to use recursion, you'll need to call the contains method from within the contains method, which you are not currently doing. Even if you were to simply call it at the end of the method as it stands now, it still wouldn't do anything - think about how you might rewrite it if the method started:
public boolean contains(int aData, Node nodeToCheck)
Recursion has a very well defined form that is used in almost all cases. Essentially the form is:
type method(context) {
if (one of the base cases holds)
return appropriate base value
else
for each possible simpler context
return method(simpler context);
}
This works by progressively breaking the problem down into smaller pieces until the problem is so simple it has an obvious answer (i.e. the base case). The key to using recursion is to ask yourself 'in what situations is the answer obvious?' (i.e. the base cases) and 'when the answer isn't obvious how can I simplify the situation to make it more obvious?'. Don't start coding until you can answer those questions!
In your case you have 2 base cases: you've reached the end of your list or you have found the value. If neither of those cases hold then try again in a simpler context. In your case there's only one simpler context: a shorter list.
Putting all that together you have:
public boolean contains(Node node, int data) {
if (node == null)
return false;
else if (node.value == data)
return true;
else
return contains(node.next, data);
}

Recursive inorder Successor of a given element in BST with java

Because the code is too long the link is here ->http://pastebin.com/jXgbE6bB
Because i am not that good at recursions i just can't find the right recursion function for this problem.
(P.S.I am new to this forum and i know i am going to have a lot of hate comments like why not go find tutorials on recursions and other things,but believe me i have done everything but i just can't understand the logic of the recursions)
My question is What's the recursive function for in-order successor of a given element in Binary search tree?I made it this far but it just returns the parent of the node it's supposed to print:
public E getSuccessor(BNode<E> t, E x) {
if(t.left!=null && x.equals(t.info)){
return t.left.info;
}
else if(x.compareTo(t.info)<0){
return (getSuccessor(t.left, x));
}
else {
return (getSuccessor(t.right, x));
}
}
public E getSuccessor(E x) {
return getSuccessor(root, x);
}
The inorder successor of a given node is the lowest node in the right subtree of that node. To understand otherwise, it is the next node that will be printed in a simple in order traversal of the tree.
If the node has a right child, this solution is simplified to finding the smallest node in the right subtree.
If the node doesn't have a right child, and there are no parent pointers, we need to start from the root of the tree and work our way to identify this successor.
Here is the recursive way to solve this. While calling the method, pass root as the root of the tree, the node who's successor is needed as t and null as the successor because the method will calculate it. Something like the following -
BinaryTreeNode successor=tree.inorderSuccessor(root,node,null);
public BinaryTreeNode<Type> inorderSuccessor(BinaryTreeNode<Type> root,BinaryTreeNode<Type> t,BinaryTreeNode<Type> successor)
{
if(root==null)
return null;
if(root.element==t.element)
{
if(root.right!=null)
return findMin(root.right);
else
return successor;
}
int cmp=t.element.compareTo(root.element);
if(cmp < 0)
return inorderSuccessor(root.left,t,root);
else
return inorderSuccessor(root.right,t,successor);
}
public BinaryTreeNode<Type> findMin(BinaryTreeNode<Type> t)
{
if(t==null)
return t;
while(t.left!=null)
t=t.left;
return t;
}

Changing the recursive insertion of the (binary Search tree) to non-recursive?

I am trying to change my recursive insert method of the BST into non-recursive( maybe While loop)
The reason for this changing because I want to see if it is possible.
Here is the code of insertion:
public void insert(String value)
{
//The node is stored in the root
root = insert(value,root);
}
private Character insert(String value,Character current)
{
if(current == null)
{
//Add the root if the tree empty
current = new Character(value);
}
else
//If the value that we want to insert < root value, then keep going to left till
//it's empty then inserted at left end. Done by recursion
if(value.compareTo(current.getElement())<=-1)
{
current.setLeft(insert(value,current.getLeft()));
}
else
//If the value that we want to insert > root value, then keep going to right till
//it's empty then inserted at right end. Done by recursion
if(value.compareTo(current.getElement())>=1)
{
current.setRight(insert(value,current.getRight()));
}
else
{
//Else, the number we want to insert in already in the tree
System.out.println("Duplicate numbers inserted" + current.getElement());
}
//returning the node tree so that we store it in the root
return current;
}
Could I change this code into non recursive ?
Cheers
Yes, but you need to alter the data structure a little bit to make it works.
The node has to know its left child and right child.
The algorithm looks like this:
current = root;
while(current != null){
if(value.compareTo(current.getElement())<=-1)
{
current = current.left_child;
}else if(value.compareTo(current.getElement())>=1){
current = current.right_child;
}else{
// Duplication
}
}
Actually there are some good examples before, you may want to check those out first:
Write a non-recursive traversal of a Binary Search Tree using constant space and O(n) run time
Nonrecursive/Iterative Binary Search Tree in C (Homework)
Yes, you could define your insert function non-recursively.
However, to do this, your insert function will have to define in-order traversal iterator for BST, which is recursively defined.
I believe there is a way to define in-order traversal non-recursively, but depending on implementation this can be very inefficient.
BST itself is basically recursively defined, and it is always efficient to define your insert function recursively. (I could write some pseudo-code if you really need it, but I think it is kind of meaningless and I do not know about the implementation detail of your in-order traversal iterator)
Please don't forget to select this as an answer :-)
Insert using while loop
public Node insert(Node root,int n) {
while (true) {
if (root.data>n) {
if (root.left==null) {
root.left= new Node(n);
return (root.left);
}
root=root.left;
}
else if (root.data<n) {
if (root.right == null) {
root.right= new Node(n);
}
}
}
}

Categories

Resources