Java Min-Heap Implementing Priority Queue - Iteration - java

I'm trying to use this code to implement a Priority Queue. There are a number of questions regarding this implementation on the site, but given how many different ways you can write code to do essentially the same thing I am still at a loss after looking through a handful of other examples.
There are some missing lines in this code, but I am limited to editing only the four marked lines and so I find myself stuck on one particular aspect. I can't seem to understand how 'quantity' is incremented.
From my understanding main creates a new object of maxSize = 5. Then calls the insertItem method passing the value of 130. This should be placed into the root (I had put queArray[quantity] = item; into the first blank) at which point the insertItem method exits and is then called again with the next value. So at what point is 'quantity' incremented? Maybe I am missing something incredibly simple, or maybe there is another way of solving this that may not be apparent or known to beginners like me?
I would think you would want to increment quantity under the initial if statement, but that doesn't seem to be an option, so as far as I can tell the else statement can never be executed as quantity doesn't change. I know I am incorrect, but I don't know how, some help would be greatly appreciated.
public class Main {
/**
* #param args the command line arguments
*/
// array in sorted order, from max at 0 to min at size-1
private int maxSize;
private long[] queArray;
private int quantity;
public Main(int s) {
maxSize = s;
queArray = new long[maxSize];
quantity = 0;
}
public void insertItem(long item) {
int i;
if (quantity == 0)
__________; // insert at 0
else
{
for (i = quantity - 1; i >= 0; i--) // start at end,
{
if (item > queArray[i]) // if new item larger,
__________; // shift upward
else
// if smaller,
break; // done shifting
}
__________; // insert it
__________;
} // end else (quantity > 0)
}
public boolean PQEmpty(){
return (quantity == 0);
}
public long removeItemPQ(){
return queArray[--quantity];
}
public long peekMin(){
return queArray[quantity - 1];
}
public static void main(String[] args) {
Main thePQ = new Main(5);
thePQ.insertItem(130);
thePQ.insertItem(450);
thePQ.insertItem(110);
thePQ.insertItem(430);
thePQ.insertItem(280);
while (!thePQ.PQEmpty()) {
long item = thePQ.removeItemPQ();
System.out.print(item + " ");
}
System.out.println("");
}
}

It isn't a style I'd recommend, but you could use queArray[quantity++] = item;.

Related

Check for Palidrome using Recursion and Char Array search

I'm currently trying to use a function that compares the left and right side character to return a true or false Boolean value as to whether the string entered by the user is a palindrome or not, but I get a vague error statement to do with line 44. Not sure how to proceed. I am a beginner-level Java programmer who is open-minded and willing to learn, so don't roast me to hard haha.
import java.util.Scanner;
/**
*
* #author owner
*/
public class Q2_RecursivePalidrome {
public static void main(String[] args) {
int leftSideCharacter = 0;
int rightSideCharacter = 0;
Scanner scan = new Scanner (System.in);
System.out.println("Enter word to check whether palidrome: ");
String userInput = scan.next();
char[] checkPalidrome = userInput.toCharArray(); // creates an array of characters
System.out.println(isPalidrome(checkPalidrome, leftSideCharacter, rightSideCharacter));
}
public static boolean isPalidrome(char[] checkPalidrome, int leftSideCharacter, int rightSideCharacter) {
leftSideCharacter = 0;
rightSideCharacter = checkPalidrome.length - 1; // java arrays start at 0, not 1.
if (rightSideCharacter > leftSideCharacter) { // check both ends of string character by character
// to be palidrome, both sides of string should be same
//
if (checkPalidrome[leftSideCharacter] == checkPalidrome[rightSideCharacter]) {
return (isPalidrome(checkPalidrome, leftSideCharacter + 1, rightSideCharacter - 1));
}
else {
return false;
}
}
return true;
}
}
There are a couple main issues here, but you have the right idea:
Your recursive function uses left and right indices to determine which characters to compare in the test string. However, these two pointers are immediately set to the left and right ends of the string when the function is called, so they never recursively move towards the middle. Since the base case where the indices are equal is unreachable, the stack overflows. Remember, these calls are identical all the way down the stack, but with different parameters, so one-time "set up" tasks like setting initial indices should be moved outside of the recursive function.
Your initial pointer indices are 0, 0. This is an inaccurate "set up" call to the recursive function--it should be 0, string.length - 1.
Here is code that fixes these problems and cleans up comments and variable names:
import java.util.*;
public class Q2_RecursivePalidrome {
public static void main(String[] args) {
String test = "racecar";
System.out.println(isPalidrome(test.toCharArray(), 0, test.length() - 1));
}
static boolean isPalidrome(char[] test, int l, int r) {
if (l < r) {
if (test[l] == test[r]) {
return isPalidrome(test, l + 1, r - 1);
}
else {
return false;
}
}
return true;
}
}
By the way, the important lesson to take from all this is how to debug your program. In this case, printing your indices (the arguments that change from one call to the next) at the top of your recursive function will clearly show that they aren't doing what you expect.

Print Tree with 4 nodes (simple forest) for checking a benchmark

I implemented an experimental OOP language and now benchmark garbage collection using a Storage benchmark. Now I want to check/print the following benchmark for small depths (n=2, 3, 4,..).
The tree (forest with 4 subnode) is generated by the buildTreeDepth method. The code is as follows:
import java.util.Arrays;
public final class StorageSimple {
private int count;
private int seed = 74755;
public int randomNext() {
seed = ((seed * 1309) + 13849) & 65535;
return seed;
}
private Object buildTreeDepth(final int depth) {
count++;
if (depth == 1) {
return new Object[randomNext() % 10 + 1];
} else {
Object[] arr = new Object[4];
Arrays.setAll(arr, v -> buildTreeDepth(depth - 1));
return arr;
}
}
public Object benchmark() {
count = 0;
buildTreeDepth(7);
return count;
}
public boolean verifyResult(final Object result) {
return 5461 == (int) result;
}
public static void main(String[] args) {
StorageSimple store = new StorageSimple();
System.out.println("Result: " + store.verifyResult(store.benchmark()));
}
}
Is there a somewhat simple/straight forward way to print the tree generated by buildTreeDepth? Just the short trees of n=3, 4, 5.
As other has already suggested, you may choose some lib to do so. But if you just want a simple algo to test in command line, you may do the following, which I always use when printing tree in command line (write by handle, may have some bug. Believe you can get what this BFS algo works):
queue.add(root);
queue.add(empty);
int count = 1;
while (queue.size() != 1) {
Node poll = queue.poll();
if (poll == empty) {
count = 1;
queue.add(empty);
}
for (Node n : poll.getChildNodes()) {
n.setNodeName(poll.getNodeName(), count++);
queue.add(n);
}
System.out.println(poll.getNodeName());
}
Sample output:
1
1-1 1-2 1-3 1-4
1-1-1 1-1-2 1-1-3 1-2-1 1-2-2 1-3-1 1-3-2 1-4-1
...
And in your case you use array, which seems even easier to print.
Instead of using object arrays, use a List implementation like ArrayList. For an improved better result subclass ArrayList to also hold a 'level' value and add indentation to the toString() method.

How to start back at beginning of arraylist in a while loop?

I'm trying to solve a puzzle that goes like this: 100 people stand in a circle. The first person kills the person next to him and hands the gun to the next person. Which person is left at the end?
This is what I have so far, but when I run it, it shows an out of bounds exception. I realized that when I write people.remove(i+1), the program runs to the end of the arraylist and has no way to start back at the beginning to continue the pattern. How do I do this?
Thanks for any help!
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
int input = Integer.parseInt(txtInput.getText());
ArrayList <Integer> people = new ArrayList <> ();
for (int i = 0; i < input; i++) {
people.add(i);
}
while (people.size() != 0) {
int i = 1;
people.remove(i+1);
i++;
}
for (int i = 0; i < people.size(); i++) {
lblOutput.setText(" " + people.get(i));
}
The reason you get an out of bound exception is that you check the size to be non-zero, but the call of remove(i+1) with i set to 1 means removing from the third spot in the list, which may not be there. Only the initial element at index zero is guaranteed to be there.
Also note that i++ has no effect, because i is reset back to 1 at the top of the loop's body.
With the condition of people.size() != 0 the only guaranteed thing is that you would be able to remove at index zero. However, this is rather inefficient, because all elements past that index need to be copied. This makes removal an O(n2), which could be slow when the list is really long.
Generally, though, the idiomatic way of managing removals from a list is using ListIterator<T> for removal of zero to a few items, or copying into a separate list and replacing the original list with the new one when you need to remove a significant portion of the list.
As I understand the problem, you need to remove every second person from the list until only one person remains.
The basic problem with your current implementation, is, first, you don't do any range checking (how do you know an element actually exists at i+1) and secondly, you loop until the list is empty, which isn't what you really want.
The basic requirement could use compounding loops, the outer loop checks the size of the list and keeps looping while the size of the List is greater then 1, the second loop processes the list, removing every other person from the list. Note, I don't reset the hasGun flag in the outer loop, this means that on each iteration of the inner loop, the gun continues to pass to the next survivor.
ArrayList<Integer> people = new ArrayList<>();
for (int i = 0; i < 10; i++) {
people.add(i);
}
boolean hasGun = true;
while (people.size() > 1) {
Iterator<Integer> iterator = people.iterator();
while (iterator.hasNext()) {
System.out.print("> " + iterator.next());
if (!hasGun) {
// You get shot...
iterator.remove();
System.out.println(" got shot");
} else {
System.out.println(" shoots");
}
hasGun = !hasGun;
}
}
for (Integer person : people) {
System.out.println(person);
}
This example also makes uses the List's Iterator, this over comes, in part, the issue of the array out of bounds, but you could also use a for-next loop and the hasGun flag as well.
To circulate through your array with indexing, use the remainder operator:
int actual = 0;
while (people.size() != 1) {
people.remove( (actual+1) % people.size() );
actual = (actual+1) % people.size();
}
I just think an ArrayList is not the best data structure for this problem. I find a LinkedList would be more fit. Actually, I found a very easy recursive solution using one. Have a look at this code:
public class Main {
public static int kill(LinkedList<Integer> people) {
assert people.size() > 0;
System.out.println("people: " + people);
if (people.size() < 3)
return people.getFirst();
else {
System.out.println("kill: " + people.remove(1));
people.addLast(people.removeFirst());
return kill(people);
}
}
public static void main(String[] args) {
LinkedList<Integer> people = new LinkedList<>();
for (int i = 0; i <=100; i++) {
people.add(i);
}
int survivor = kill(people);
System.out.println("Last survivor: " + survivor);
}
}
I just remove (kill?) the second member on the list and send the first one back to the end of the list. This process can be repeated until there are 2 people left, in which case you can guess the last survivor will be the first one in the list cause he will kill the second person.
If I had to resolve this problem, I would create my own Person class with a next property pointing to the next person.
Person class:
public class Person {
private int id;
private Person next;
public Person(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public Person getNext() {
return this.next;
}
public void setNext(Person next) {
this.next = next;
}
public void killNext() {
this.next = this.next.next;
}
}
Once that is in place, it's trivial to setup a circular set of linked persons. The algorithm then simply becomes looping each person by following the next property, killing the next person on each iteration. And the loop exits when the next property points to himself, indicating that there is no one left.
Algorithm:
public static void main(String[] args) {
// Setup 100 persons in a linked circle.
Person startingPerson = new Person(1);
Person currentPerson = startingPerson;
for (int i = 2; i <= 100; i++) {
currentPerson.setNext(new Person(i));
currentPerson = currentPerson.getNext();
}
currentPerson.setNext(startingPerson);
// Loop around until a single person is left.
currentPerson = startingPerson;
while (currentPerson != currentPerson.getNext()) {
currentPerson.killNext();
currentPerson = currentPerson.getNext();
}
System.out.println("Surviving person: " + currentPerson.getId());
}
Output:
Surviving person: 73

How can I convert existing procedural code to use classes?

I'm trying to learn Java and basically my approach has been to take the procedural style I learned with python, and apply it to Java. So I never use classes and just put everything in a single class with many methods(which I just use as python functions). I think I've hit a problem, and need to bite the bullet and use classes, but I'm having trouble wrapping my head around how to do it.
To simplify my problem(ignore the poor design- it's just to illustrate the point), I have a program that takes a list and within a for loop does some math on each item(in this case adds 1 to the value of the list). I only want it to do work on 2 items on the list and then stop(in this example it's the first 2 items but in my real program it could be anywhere in the list). Here's the working code that is similar to how I'm already doing it:
No Classes:
public class LearningClasses {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
for (int i =0; i<100; i++){
if (check_size(data_list) == false ) {
break;
}
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
private static boolean check_size(int[] data_list) {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=2) {
break;
}
}
}
if (count>=2) {
return false;
} else {
return true;
}
}
}
The problem with this code is although it works it's inefficient because it calculates the count on every iteration of the second for loop. In my program I cannot put anything above the first for loop but I can put anything below it, so I thought instead of doing the count every time maybe I could use a class to somehow maintain state and just increment the number as oppose to recalculating every time.
With classes:
public class LearningClassesCounter {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
for (int i =0; i<100; i++){
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int count; // current value
private boolean continue_or_not;
private int[] data_list;
// create a new counter with the given parameters
public Counter(int[] data_list) {
data_list = this.data_list;
count = 0;
continue_or_not = true;
}
public boolean check_data() {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=3) {
break;
}
}
}
if (count>=3) {
return false;
} else {
return true;
}
}
// increment the counter by 1
public void increment() {
count++;
}
// return the current count
public int value() {
return count;
}
}
This doesn't work because it thinks the data_list is a null pointer(I know I'm declaring it null, but if I make it private int[] data_list = data_list it doesn't compile either). My ultimate goal is to have some kind of controls, in this case its limiting it to 2 items but I want to also add other limits like total value of al items cannot exceed X or cannot be lower than X and want to save CPU power by not having to do full calculations every time. So I think I need to be able to increment the values and then need to check that those increments haven't exceeded thresholds.
Can anyone help me understand what I'm doing wrong? Am I only wrong with syntax; or am I designing this wrong?
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
When you are calling checker.check_data(), its trying to parse through the data_list, but its empty. So, it throws a NullPointerException. The data_list is empty because inside your constructor, you may need to initialize like this this.data_list = data_list instead of data_list = this.data_list (here this.data_list has no reference so NULL)
If you avoid that call, the output will be 2,3,4,5,6,7,8,9,10,11.

java adding objects to ArrayDeque at random intervals

Trying to add objects to a ArrayDeque at random intervals. This is what I have
for (int i = 0; i <= 100; i ++) {
if (window.isEmpty()) {
Customer customer = new Customer(r.nextInt(10)+1);
q.add(customer);
window.beginService();
}
else {
Customer customer = new Customer(r.nextInt(10)+1);
q.add(customer);
window.beginService();
totalCustomers++;
totalServiceTime += window.serviceTime;
totalWaitTime += customer.getArrivalTime();
}
}
The other methods being used are
public boolean isEmpty() {
if (serviceTime == 0) {
return true;
}
else
return false;
}
public void beginService() {
if (isEmpty()) {
serviceTime = r.nextInt(10)+1;
}
else
serviceTime += r.nextInt(10)+1;
}
public Customer(int arrivalTime) {
this.arrivalTime = arrivalTime;
}
public int getArrivalTime() {
return arrivalTime;
}
When I print out my customer count it is equal to my clock time, which should not be as customers are added at random intervals of 1-10. Any ideas?
Are you defining your "clock time" as the value of i? If so, I'm not sure why you would expect it and totalCustomers to be different.
In your for loop, you add a customer regardless of whether or not the windows is empty. After the first time around, the window will never be empty because you are always beginning service which always increments the serviceTime by at least 1.
So after the first iteration of the loop, the else branch of your if will exclusively be executed and totalCustomers will always increment alongside of i.
I think you have bigger logic gaps in your code but you haven't been very clear with how you've framed your question or shown your code. It is unclear how serviceTime is declared or what the code is supposed to be doing. You never seem to take an item off of the queue. If you need more help than this you need to put some more effort into your question.

Categories

Resources