BST smallest n elements show - java

I have this method and it should show on the screen the smallest n Elements in BST,
Example n=3, the smallest 3 elements and so on..
Unfortunately at running, it shows that its reaching an Empty content and gets shut down. Further notes, the method should give and int back and its not void, but I couldn't find another way to show all the Elements, because return type int will give just one Element? right?
public int sorteduptp(int n) {
if (n > 0 && !isEmpty()) {
BinarySearchTree current = this;
while (!current.leftChild.isEmpty() && current.size() != n) {
current = current.leftChild;
}
if (n == 1) {
System.out.println(current.leftChild.getContent());
return 0;
} else {
sorteduptp(n - 1);
while (!current.isLeaf()) {
System.out.println(current.getContent());
System.out.println(current.rightChild);
}
System.out.println(current.getContent());
}
}
}

It seems that the current = current.leftChild; will never get used in the recursive step because current = this will set current to the top of the tree. So you might want add that as parameter and initially pass this.
For the return, you can make it as array of integers like int[] or an ArrayList. Those can hold more than one values.

Related

How does a recursive function inside a while loop works in Java?

I found this code on google but i couldn't find how does the recursive part actually work. The code is about finding the possible path between 2 vertices on a directed graph. Here is the method to print the total possible path :
public void total_path(int source, int destination)
{
result = 0;
boolean[] visit = new boolean[size];
for(int i = 0; i < size; i++)
{
visit[i] = false;
}
count_path(source, destination, visit);
System.out.println(result);
}
Here is the recursive method to count all possible paths :
public void count_path(int start, int end, boolean[] visit)
{
if(start > size || end > size || start < 0 || end < 0 || node == null)
{
return ;
}
if(visit[start]==true)
{
return;
}
if(start == end)
{
result = result + 1;
}
visit[start] = true;
AjlistNode temp = node[start].next;
while(temp!=null)
{
count_path(temp.id, end, visit);
temp = temp.next;
}
visit[start]=false;
}
Here is the graph which i created :
g.addEdge(0, 1);
g.addEdge(1, 2);
g.addEdge(1, 3);
g.addEdge(2, 5);
g.addEdge(3, 4);
g.addEdge(4, 2);
g.addEdge(4, 5);
g.addEdge(5, 6);
I already compiled and run the program which start point is 0 and end point is 6. The result is 3, already looked up on YouTube about the algorithm but i still can't understand on how to visualize and how does the code flow on the recursion part inside a while loop.
A recursive function must contain a base case to return a value rather than the result of the recursive call. In this case:
if(start > size || end > size || start < 0 || end < 0 || node == null)
{
return;
}
if(visit[start]==true)
{
return;
}
are those base cases that will break the recursive call chain. Remember, the method count_path returns void. If the method needed to return some value, you would've seen those if blocks returning some kind of default value. For instance, when you see examples of recursive Fibonacci, the base cases for Fib(0) and Fib(1) return the input value. Otherwise, it returns the result of the (cumulative) recursive call.
What are these base cases?
The method calculate the number of paths to some destination node from the current node. Therefore, if the node was already visited (and thus the paths should've been calculated already) simply return without recalculating. Also, if you have just one node in your graph, or no nodes, then there are no paths (so return without calculation).
Why is the answer 3 paths?
The picture below is based on the calls made to add edges. Each entry is a unidirectional path from a starting node to an ending node. So, starting at Node 0, to get to Node 6, there are three paths and they are outlined in the attached picture.

Implementing an insert function onto array implementation of Binary Search Tree

I am attempting to use the functionality of Binary Search Trees without actually create Node objects and giving them left/right children and instead using the basic idea of a Binary Search Tree within three parallel arrays: left, data, and right. At a particular index in these arrays, left holds the index to data where the current data's left child lives, while right holds the index to data where the current data's right child lives. This table gives a better example of what I am talking about:
The -1 values represent where a node does not have a left or right child. Before any nodes are inserted, all of the arrays hold the value 0, and every time a node is inserted, its left and right children index values are set to -1 (indicating that what we just inserted is a leaf). What I'm struggling to figure out is to how to do this recursively without accidentally accessing an index of -1. My current attempt seen below is running into this issue:
public void insert(int d) {
//PRE: the tree is not full
//if d is not in the tree insert d otherwise the tree does not change
if(root == -1) {
root = d;
}
insert(d, 0);
}
private void insert(int d, int index) {
if(data[index] == d) {
return;
}
if(data[index] == 0) {
data[index] = d;
right[index] = -1;
left[index] = -1;
}
if(data[index] > d) {
if(left[index] == 0) {
data[index] = d;
right[index] = -1;
left[index] = -1;
} else {
insert(d, left[index]);
}
}
if(data[index] < d) {
if(right[index] == 0) {
data[index] = d;
right[index] = -1;
left[index] = -1;
} else {
insert(d, right[index]);
}
}
return;
}
I'm curious for ideas as to how I can prevent from accessing an array with index value -1, while still being able to indicate that a node does not have a child to a particular side.
I understand the concept that every time I'm inserting a node, I'm inserting a leaf, so when a node is placed at a particular index, its left and right can automatically be set to -1, but my current recursive calls end up passing in -1 at one point or another. Even if I change this value to 0, or something else, that doesn't necessarily help me make any progress in my recursion.
Some remarks on your code:
The root variable should not be assigned d, but the index where d will be stored, only then does it make sense that an empty tree is encoded with root equal to -1 (realise that d could be -1).
Your code has no logic to determine at which index to store a new node. This is really your question. A simple solution is to maintain a size variable. This is then the index at which the next node will be stored, after which the size member should be incremented.
There is then never a reason to think of 0 as some special indicator, and your code should only check for -1 references, not 0.
You have some code repetition which you can avoid by creating a method that will "create" a node: it will use size for its index, and will take a value as argument.
Here is the suggested code:
class BinaryTree {
public static final int MAXSIZE = 100;
int left[] = new int[BinaryTree.MAXSIZE];
int right[] = new int[BinaryTree.MAXSIZE];
int data[] = new int[BinaryTree.MAXSIZE];
int root = -1;
int size = 0;
private int createNode(int value) {
data[size] = value;
left[size] = -1;
right[size] = -1;
return size++;
}
public void insert(int value) {
if (root == -1) {
root = createNode(value);
} else {
insert(value, 0);
}
}
private void insert(int value, int index) {
if (data[index] == value) {
return;
}
if (data[index] > value) {
if (left[index] == -1) {
left[index] = createNode(value);
} else {
insert(value, left[index]);
}
} else {
if (right[index] == -1) {
right[index] = createNode(value);
} else {
insert(value, right[index]);
}
}
return;
}
}
This code can be further extended with:
verification that the tree has reached a maximum size,
node deletion
"memory management" for reusing the indexes of deleted nodes (by maintaining a "free list")
self-balancing (like AVL or red-black tree)
Doing the "memory management" (array slot management) yourself is really going to mimic the powerful heap memory management that Java offers out of the box when using class instances. For that reason I would advise to implement a tree the OOP way.

Java - Trying to print all of the coincidences of a binary search

This is my current search method:
public static int search(int[] array, int numero) {
int start = 0;
int end = array.length - 1;
int center;
while (start <= end) {
center = (start + end) / 2;
if (array[center] == numero) {
return center;
} else if (array[center] < numero) {
start = center + 1;
} else {
end = center - 1;
}
}
return -1;
}
It searches from user input numero into a previously bubble sorted Array that's found in the Main method.
What I'm trying to figure out is how to print ALL of the coincidences found in the array, and not just the first one found.
I was thinking about adding results to a List and then returning that to Main, but as I tried that an endless loop happened at the first result found, causing it to add itself to the List repeatedly until the program crashes.
Assuming that you know the basic theory behind binary searches, separate it into 3 steps.
Search using binary search methods.
once a match is found, scan up from that point, until you find a non matching element.
Scan down, adding to a result list, until you find a non
matching element.
If you don't need to care about occurrence order, you could combine steps 2 and 3 and just scan up adding to the list, and scan down adding to the list, since due to the sorting, everything you hit is guaranteed to match until it doesn't.
If you do care about occurrence order, step 2 could be optimised by jumping ahead and checking, and writing a modified binary search that searches for a transition of matching/notmatching instead of a match.
This could be further optimised by keeping statistics or profiling, to find the perfect jump distance, or basing it off of the last up-most check.
actually it's easy because the list is already sorted, the numbers you expect to find are adjacent.
just like Ryan's answer, I'll put some code
public static List<Integer> searchAll (int[] array, int numero){
int firstMatchIndex = search( array, numero);
List<Integer> results = new ArrayList<Integer>():
results.add(firstMatchIndex);
boolean left = true;
while( left){
int i = firstMatchIndex - 1;
if(i<0 || array[i] != numero){
left = false;
}else{
results.add(i);
}
}
boolean right = true;
while( right){
int i = firstMatchIndex + 1;
if(i>array.length || array[i] != numero){
right = false;
}else{
results.add(i);
}
}
}

Java - Recursive solution for subset sum

I am told to write a recursive function that takes a start index, array of integers,and a target sum, your goal is to find whether a subset of of the array of integers adds up to the target sum.
The example I am given is groupSum(0, {2, 4, 8}, 10) should return true because 2 and 8 add up to the target, 10. All I've been able to do so far are the base cases.
public boolean groupSum(int start, int[] nums, int target) {
if (nums.length == 0)
{
return false;
}
else if (start == nums.length - 1)
{
return nums[start] == target;
}
else
{
?????
}
}
I have no idea where I should go with the actual recursive call. Since I can't pass a collective sum between calls, I don't see how I can add a number in each recursive call until I reach the target. Also, like shown in the example, I have no idea how I could have my code realize when a number won't work and just skip it, like the example did with 4. I'm thinking along the lines of that I should subtract numbers one at a time from int target and then recursively call the method with a new starting point and the new value for target, but I have no idea how I could use that to see if there is a valid subset.
I would appreciate any help that can help me understand how to do this problem so that I can finish it. Thanks!
As you point out you can change the target rather than passing a collective sum. Once the target is zero you know that you've got a solution (by selecting no members of the remaining items).
So, in psueduo code:
hasMembersThatSumTo(list, total):
if total == 0
return true
else if total < 0 or list is empty
return false
else
int first = list.pop
return hasMembersThatSumTo(list, total - first)
or hasMembersThatSumTo(list, total)
The two cases in the 'or' statement are looking for this situation in which the current element is either in or not in the sum.
Here is a working version. See comments in the code for explanation.
public static boolean recursiveSumCheck(int target, int[] set) {
//base case 1: if the set is only one element, check if element = target
if (set.length == 1) {
return (set[0] == target);
}
//base case 2: if the last item equals the target return true
int lastItem = set[set.length - 1];
if (lastItem == target) {
return true;
}
//make a new set by removing the last item
int[] newSet = new int[set.length - 1];
for (int newSetIndex = 0; newSetIndex < newSet.length; newSetIndex++) {
newSet[newSetIndex] = set[newSetIndex];
}
//recursive case: return true if the subset adds up to the target
// OR if the subset adds up to (target - removed number)
return (recursiveSumCheck(target, newSet) || recursiveSumCheck(target - lastItem, newSet));
}
dynamic programming. Maybe this will help you.
This should work according to the given conditions.
Initially the value of start = 0
boolean subsetSum(int start, int[] nums, int target) {
// target is the sum you want to find in the nums array
if (target == 0) return true;
if (start > nums.length-1 || nums.length == 0)
return false;
if (nums[start] > target)
return subsetSum(start+1, nums, target);
return subsetSum(start+1, nums, target) || subsetSum(start+1, nums, target - nums[start]);
}

uniformly random access a collection

I wanna implement a uniformly random access to a certain collection with N numbers, like each item in the collection will be accessed at uniformly 1/N chances. I put all the items in a modified double linked-list. then circular shift it with random times, remove the last item then add it as first. finally pick the first item. I used it to test how many number of calls it will take to cover all the item without moving the item out of the list. Mine total number needed is consistently units less than expected. Wondering if the implementation is truly uniformly random? do you think my implementation is truly random?I have been debugging this for quite some time, still no clue.
public Item callout(){
for (int j=0; j<StdRandom.uniform(N); j++)
{
this.addFirst(this.removeLast());
// circular shift the queue by StdRandom.uniform(N)times, always return the first item;
}
return first.item;
}
public void addFirst(Item item){
Node<Item> oldfirst = first;
first = new Node<Item>();
first.item = item;
first.previous = null;
if (last == null)
{last = first; first.next = null;} //if it's the first element added. if last.next = null == last = null;!!!!
else
{
first.next = oldfirst;
oldfirst.previous = first;
}
N++;
}
public Item removeLast(){
if (last == null) throw new RuntimeException();
Item item = last.item;
// if right now only one element exists in the container
if (first == last)
{
first=null;
last=null;
}
else{
last =last.previous;
last.next = null;
// old first becomes first; optional operation, easy way to tell if it's the header.
}
N--;
return item;
}
The following class computes the number of calls needed to reach comprehensive call, it receives a RandomCollection with n items in it. Basically, It's a collection with Integers from 1-N, I use an array int[] of flag to tag if the item has previously been called.
private static int getNumberOfCallsForComprehensiveCallout(RandomCollection<Integer> test, int n){
// create an array of the same number of items in collection, each with a Flag indicating whether it has beeen called
int calltimes =0; // calltimes stands for the numofcalls needed to reach a comprehensive call
int flag = 1; // flag used to indicate if this item has been called
int [] c = new int [n];
Arrays.fill(c, flag);
int NumberOfFlags = n;
while(NumberOfFlags != 0){
int numbercalled = test.callout();
if (c[numbercalled-1]==1) {NumberOfFlags--; c[numbercalled-1]=0;}
else; // indicate this item has been called earlier.
calltimes++;
// System.out.println(calltimes);
}
return calltimes; // return the number of calls for comprehensive callout each time this method is called.
}
The overall logic seems to be correct, but -
Firstly, the number of calls to cover all the items (with replacement) can be greater than size of the collection. Infact it will be greater most of the times.
Secondly, in callout(), call the StdRandom.uniform(N) method outside the loop only once. try the following change -
public Item callout(){
int randomRotate = StdRandom.uniform(N);
for (int j = 0; j < randomRotate; j++)
{
this.addFirst(this.removeLast());
}
return first.item;
}
I ran some simulations and the number of rotations are not uniformly distributed if the call to StdRandom.uniform(N) is made inside the for loop. Histogram results for a collection of size 10 -
0 1 2 3 4 5 6 7 8 9
1001 1813 2074 2043 1528 902 454 144 37 4

Categories

Resources