Display Nodes at the same depth not working - java

void wordsAtDepth() {
int depth = 0;
int numOfNodes;
Queue queue = new Queue(32); // Make a new Queue called queue.
queue.insert(root); // Insert the root into the queue
// While queue is not empty we will continue the while loop
while (!queue.isEmpty()) {
// numOfNodes keeps track of how many times we are going to
// continue the for loop in the current while loop.
numOfNodes = (int) Math.pow(2, depth);
// for loop will continue until i is equal to or is greater
// than numOfNodes.
for (int i = 0; i < numOfNodes; i++) {
// Current will equal to the removed element from the
// queue.
Node Current = queue.remove();
// If Current does not equal null then print current
// and insert its' left and right child.
// If Current does equal null then do nothing go to the
// next iteration of the for loop
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
}
// Makes new line every time we finish the while loop.
// Which means new line for the next iteration of the
// while loop to separate the different depths.
System.out.println(" ");
depth++;
}
}
Nodes contain char values. For the word OPTIMAl it prints correctly, but for words like HAPPY or SUPERMAN they print incorrectly. For example: SUPERMAN: S PU ER AMN SPUERAMNPUERAMN ERAMNAMNNEMNNAMNN AMNNNNAMNNNNNNNN NNNNNNNN
Instead of using numOfNodes = (int) Math.pow(2, depth); the code works when I use the numOfNodes = queue.length(). But I WANT to use numOfNodes = (int) Math.pow(2, depth); since the for loop will should loop for the ammount of Nodes at a depth. Since the number of Nodes in a depth is 2^Depth.

If you expect the number of nodes at a certain depth to be that power of 2, then you must make sure to deal with the case where your tree is not perfect, because then -- even if your tree is complete -- the bottom level will not be fully filled.
The simple fix seems to be that you always add 2 entries to the queue for every entry you pop from it. So change this:
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
to this:
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
} else {
queue.insert(null);
queue.insert(null);
}

Related

Binary Search Tree method prints oddly with some words

Binary Search Tree:
[1]: https://i.stack.imgur.com/lrhxx.png
void wordsAtDepth() {
int depth = 0;
int numOfNodes;
Queue queue = new Queue(32); // Make a new Queue called queue.
queue.insert(root); // Insert the root into the queue
// While queue is not empty we will continue the while loop
while (!queue.isEmpty()) {
// numOfNodes keeps track of how many times we are going to
// continue the for loop in the current while loop.
numOfNodes = (int) Math.pow(2, depth);
// for loop will continue until i is equal to or is greater
// than numOfNodes.
for (int i = 0; i < numOfNodes; i++) {
// Current will equal to the removed element from the
// queue.
Node Current = queue.remove();
// If Current does not equal null then print current
// and insert its' left and right child.
// If Current does equal null then do nothing go to the
// next iteration of the for loop
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
}
// Makes new line every time we finish the while loop.
// Which means new line for the next iteration of the
// while loop to separate the different depths.
System.out.println(" ");
depth++;
}
}
Using OPTIMAL, OUTPUT:
O
IP
AMT
L
This is correct, but if I use a word like SUPERMAN:
S
PU
ER
AMN
SPUERAMNPUERAMN
ERAMNAMNNEMNNAMNN
AMNNNNAMNNNNNNNN
NNNNNNNN
I really want to use the numOfNodes = (int) Math.pow(2, depth);, since the number of nodes at a certain depth is 2^Depth. But it seems to not work.
I have a working version of this code where I use numOfNodes = queue.size(), but that is not what I want to use.

Inserting into an ArrayList<Occurrence> using Binary Search

So this method is passed an arraylist of Occurences, which each contain a string and a frequency. The frequency is the only important part here. But what I need to do is use binary search to insert the last element in the arraylist into the sorted position. Every time I run this code, the insertion position is printed as -1. Am I missing something in my code?
I need to keep track of the indexes in the array I hit during binary search, which shouldn't be too difficult, but explains the return type.
public ArrayList<Integer> insertLastOccurrence(ArrayList<Occurrence> occs) {
ArrayList<Integer> path = new ArrayList<Integer>();
int targetFreq = occs.get(occs.size()-1).frequency; //gets the frequency of the thing we want to insert
//if the array is just 1 value, don't do anything
if(occs.size() == 1){
return null;
}
int start = 0; // The start of the search region
int end = occs.size()-2;// The end of the search region is 1 less than the last position
int position = -1; // Position of the target
// While there is still something list left to search and
// the element has not been found
while (start <= end && position == -1) {
int mid = start + (end - start) / 2; //int mid = (start + end) / 2; // Location of the middle
// Determine whether the target is smaller than, greater than,
// or equal to the middle element
if (targetFreq < occs.get(mid).frequency) {
// Target is smaller; continue the left half
end = mid - 1;
}
else if (targetFreq > occs.get(mid).frequency) {
// Target is larger, continue the right half
start = mid + 1;
}
else {
// Found it!
position = mid;
}
}
System.out.println(position);
return path;
}
So, do I understand this right? You have an ArrayList that is sorted with the exception of the last element (at size()-1) and you want to find the index this element has to be inserted after to regain the sorted property?
I suppose, with the presented code, such an index is only found if the ArrayList contains another element that equals the last (to be inserted) one because position is only set to mid if targetFreq equals the frequency of one of considered elements. Since the last element is never considered (end = size()-2) it is very likely that no equal element is found.

Circular Queue Array Insertion Case

I have the code for the implementation of this pretty close to being done, what is causing my IndexOutofBounds error seems to be happening in one case of inserting into the queue. Any ideas? At the start of my class i set the rear and front to be -1, and the count to be 0. The array has a max size of 100. There is a isfull class that tests to see if the count is the max size.
public boolean insert(int n){
if (isFull()){
//not inserted
return false;
}
else{
//make it the first in queue if queue is empty
if ( front == -1 && rear == -1){
front++;
rear++;
list[front] = n;
list[rear] = n;
count++;
return true;
}
//not at end of queue, add to end
else if ( (count+1) <= 100 ){
rear++;
list[rear] = n;
count++;
return true;
}
//else add to front
else{
//update rear
rear = ((count+1)%100)-1;
list[rear] = n;
return true;
}
}
}
This code so far inserts a number into the array in this order:
0. Check to see if its full. If it is quit.
1. If the queue is empty, make it the first item in there.
2. If the queue is not empty or full, check to see if the back of the array doesnt exceed the max spots. If it doesnt, add it to the end.
3. If the queue is not empty or full, but the back of the queue is full. Loop around and insert it into the beginning of the array.
The problem is in the case where for example:
- The array is filled with numbers 1-100. The array is full at this point.
- Remove the front, so then the array goes from 2-100 with the first slot being empty.
- Insert the number you just removed, this causes the error. At this point the count+1 doesn't exceed the max spots, so it tries to add it to the rear. But since the last spot is full, it doesn't loop around, throwing a array out of bounds exception. What can i add for it to check if the last spot is filled and to add to the beginning of the array in that case?
My remove method:
public int remove(){
//if empty return -1
if (isEmpty()){
return -1;
}
else{//else remove
front++;
int x = list[front-1];
count--;
return x;
}
}
public boolean insert(int n){
if (isFull()){
//not inserted
return false;
}
else{
//make it the first in queue if queue is empty
if (isEmpty()){ //use empty
front=0;//just set it
rear=0;//just set it
}
list[rear] = n;
rear = (rear+1)%100; //just rewind it when it reaches 100 index 0 must be free at this point
count++;
return true;
}
}
I suppose count is the number of elements, so remove should do count--. in this case count is always <100 because the array is not full after u checked for that... so the only thing you must do is to rewind the rear counter;
additionally remove should do front = (front+1)%100;
public int remove(){
if (isEmpty()){
return -1;
}
else{//else remove
int x = list[front];//reorder
front = (front+1)%100;//rewind
count--;
return x;
}
}
empty() and full() should use count
front points on the the element to remove() next
last always points on the next free spot (or on front which is the next free spot too)

Unexpected Java performance

I have just thrown everything I know about Java optimisation out the window. I have the following task:
Given a 2D array representing a playing field and a position on the field, fill another array with the number of steps a player can make to get to every other position in the field. The player can move up, down, left and right. For example, the first neighbours will be all 1's, with the diagonals being all 2's.
For the first attempt, I tried a simple 4-way floodfill algorithm. It wad dreadfully slow.
Secondly, I decided to get rid of the recursion and use a simple Queue. It worked lovely and gave a huge speed-up (very roughly 20x). Here is the code:
private void fillCounterArray(int[] counters, int position) {
Queue<Integer> queue = new ArrayDeque<Integer>(900);
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue.add(destination[i]);
}
}
// Now fill up the space.
while (!queue.isEmpty()) {
int pos = queue.remove();
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue.add(dest);
}
}
}
}
Now, "common-sense" told me that the queue operations with a static array and an int-pointer would be faster. So I removed the Queue and use a standard int[] array. The code is identical, except for the queue-like operations. It now looks like this (As you can see, I use to live by the C-side :)):
private void fillCounterArray(int[] counters, int position) {
// Array and its pointer.
int[] queue = new int[900]; // max size of field
int head = 0;
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue[head++] = dest[i];
}
}
// Now fill up the space.
while (head > 0) {
int pos = queue[--head];
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue[head++] = dest;
}
}
}
}
When I ran this "optimised code" it was significantly slower than using the Queue and only about twice as fast as the recursive technique. There is also hardly any difference when I declare the array as an instance variable. How is this possible?
Your reversed the order while optimising I think;
The queue is fifo, first in first out
The array is lifo, last in first out, as you walk it downwards
That will usually give you different performance ;-)
Insert two Counters in each Loop one in the for loop and one in the while loop in both versions, compare the numbers you get at the end, how many rounds do you make in each version, if you have another Loop in getPossibleDestination then log the pos variable too.
I guess that would be a good starting point to figure it out.
Another way would be to print the time difference on different lines in your program, let say before the 1st loop, between both and at the end, once you compare results and know where it takes a long time in the second Version you can print timestamps in the loop on different lines.

N-Queens in Java using Stacks, Keeps taking the same route after backtracking

Title pretty much says it all. I've been working on this and just can't figure out a way to prevent it from happening. Perhaps some way to store invalid placements? Or how would I implement a way for it to 'resume' from the last time it was at this row so it doesn't just pick the same value again?
Ignore the while i, its just for debugging. Same with the prints.
import java.util.Stack;
public class NQueens {
//***** fill in your code here *****
//feel free to add additional methods as necessary
//finds and prints out all solutions to the n-queens problem
public static int solve(int n) {
//***** fill in your code here *****
//Scaffolding code from Stacks.pdf
//------------------------------------------------------------------------------------------------------------------
// Create empty stack and set current position to 0
Stack<Integer> s = new Stack<Integer>();
int column = 0;
int row = 0;
int solutionsCount = 0;
int i = 0;
//Repeat {
//loop from current position to the last position until a valid position is found //current row
while (i < 5){
for(column = 0; column < n ;column++) {
//if there is a valid position
System.out.println("Top of for loop");
System.out.println("Column/index for = " + column + "; Row is: " + row);
System.out.println("Stack size = " + s.size());
System.out.println();
if (isValid(s, column, row)) {
s.push(column);
//push the position to stack, set current position to 0 // move to next ro
row++;
column = 0;
}//if
}//for
//if there is no valid position
if(!isValid(s, column, row) || column >= n){
//if stack is empty, break // stop search
if(s.size() == 0){
break; //stop search
}//if
//else pop from stack, set current position to next position // backtracking to previous row
else{
s.pop();
column++;
row--;
}//else
}//if
//if stack has size N { // a solution is found
if (s.size() == n){
solutionsCount++;
printSolution(s);
//pop from stack, set current position to next position // backtracking to find next solution
s.pop();
row--;
column++;
}//if
else {
}//else
i++;
// Make sure to change this when not bug testing for 4x4
}//end for loop
//update the following statement to return the number of solutions found
return solutionsCount;
}//solve()
This looks like homework, so here are some pointers:
You are modifying the column variable after the for loop. Obviously, you intend its value to carry over into the next iteration of while. But then the first thing you do when while starts again is you set column to 0 with for (column = 0; ....), which overrides its value. What information is column supposed to carry from one iteration of while to the next?
You are setting column to 0 inside the for loop but it will be incremented to 1 with column++ before the next for iteration.
You are using column in the if statement immediately after the loop. What do you expect the value of that variable to be after the for loop completes?
After the for loop you have two if statements that are trying to check for the same condition -- whether the for loop found a solution. Only the second if is much clearer about it. Do you even need both ifs?
You are putting column values into the stack, but when you pop them off the stack, you just discard them. Don't you have some use for these values?

Categories

Resources