Stop peeking at empty stack - java

I'm checking that a stack is sorted by popping it and comparing the pop to the peek. If the pop is greater than the peek, we know those two elements are in order. I run this loop as long as the stack isn't empty.
The problem I'm running into is with the final element of the stack. I do my final pop, and but it tries to peek at an empty stack to make sure it's in order. Since there is nothing there, I get a runtime error.
public static boolean isSorted(Stack<Integer> s){
boolean result = true;
while(!s.empty()){
if(s.pop() < s.peek()){
result = false;
}
}
return result;
}
I'm trying to do this exclusively with Stack, so using only push pop and peek. Nothing from an ArrayList. How can I fix this problem, while still checking every element?
I've tried storing pop in a temporary variable, but that fixed nothing. Not sure what I was hoping for

The problem is that you need two items, but empty() checks for just one item. Once you call pop(), you need to do another empty() call prior to executing a peek():
while(!s.empty()){
// We know we have one element available; store it in "top"
Integer top = s.pop();
// If the next element is not available, exit
if (s.empty()) {
break;
}
if(top < s.peek()){
// Once result is set to "false", it never becomes "true"
// so we might as well return now:
return false;
}
}
return true;

It has to, as pop removes the last element and peek throws EmptyStackException if the stack is empty
public static boolean isSorted(Stack<Integer> s){
boolean result = true;
while(!s.empty()){
if(s.size() == 1)
return result;
if(s.pop() < s.peek()){
result = false;
}
}
return result;
}

One way to do it, is to check the size explicitly:
while(s.size() > 1){ // ok, we have enough elements in the stack
if (s.pop() < s.peek()) {
result = false;
break; // no need to proceed, we already know it's not sorted.
}
}

Related

Recursive Statement not Instantly Returning

I am creating a method that takes a list of numbers and an index.
If there is a number after the index that is six times the first number, it returns true. Otherwise, it returns false.
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
firstElementMultiple(Numbers, index+1);
return false;
With a list of {5,6,7,30} and an index of 1, false is returned, even though 30 is in the list.
6
7
30
Yep
Is printed, which shows me that it did recognise that 30 was in the list. However, it is still returning false even though the next statement is true and should stop the method?
This has to be done by recursion.
edit: I have to put the 'return false;' at the end as, without it, it doesn't let me. However, I don't see how it can ever get there because there is always a recursive call in the way.
firstElementMultiple(Numbers, index+1);
return false;
Here's the end of your method. This is what it does. It says "Call firstElementMultiple to keep looking for the value we're looking for. Once you've finished looking, completely ignore whether or not you found it and return false anyway."
Given that, how can you fix it to do what you want it to do, namely return whether or not we found the element?
Because in the end, you are returning false in your recursive function no matter what you get in further calculations. You should change your code to this:
public static boolean firstElementMultiple(int []Numbers, int index) {
System.out.println(Numbers[index]);
if ((Numbers[0]*6)==Numbers[index]){
System.out.println("Yep");
return true;
}
if (index+1 >= Numbers.length){
return false;
}
return firstElementMultiple(Numbers, index+1);
}
Basically you need to change
firstElementMultiple(Numbers, index+1);
return false;
to
return firstElementMultiple(Numbers, index+1);

Using a break to get out of an enhanced for loop

Hi everyone I was asked to write the following method for homework and I need some clarification. Basically I want to know if the Comparable item given as a parameter is part of the comparableList array. Assuming the array is sorted, I was told to stop checking the array if the comparableList has the item in it or if item is smaller than the following item of the array. I used break but I am not sure if break will get me out of the enhanced for loop to avoid checking the whole array if any of the conditions are true. I want to make sure that if there are 50,000 items in the array and I find the item at position 5 to stop checking the rest of the array. I have never used break before so I am not sure if it will get me out of the for loop.
public boolean contains(Comparable item) {
Comparable[] comparableList= getStore();
boolean isThere = false;
for(Comparable p : comparableList)
{
if(item.compareTo(p)==0)
{
isThere = true;
break;
}
if(item.compareTo(p)<0)
{
break;
}
}
return isThere;
}
The break will break out of any loop, including the enhanced one. Your solution will work.
However, since you are returning as soon as you find your item, you could change the loop to return as soon as the item is found, or as soon as you know that you are not going to find it:
Comparable[] comparableList= getStore();
for(Comparable p : comparableList) {
if(item.compareTo(p)==0) {
return true;
}
if(item.compareTo(p)<0) {
return false;
}
}
return false;
Moreover, since the array is sorted, linear search is not your best strategy: implementing Binary Search could make your algorithm significantly faster.
If you want to know the best way of stopping once it's found, just do this:
public boolean contains(Comparable item) {
Comparable[] comparableList= getStore();
for(Comparable p : comparableList)
{
if(item.compareTo(p)==0)
{
return true;
}
if(item.compareTo(p)<0)
{
return false;
}
}
return false;
}

DFS tree traversal function modification

Please find below my implementation for DFS.
protected void DFS(String search) {
for(Tree<T> child : leafs) {
if(child.value.equals(search))
return;
else
child.DFS(search);
System.out.println(child.value);
}
}
The objective is to stop traversal on finding the node whose value is in the variable search. However, the above function goes on traversing the tree even beyond the declared search node. Could someone help me modify the above function?
Thank you.
Edit 1
protected boolean DFS(String anaphorKey) {
boolean found = false;
for(Tree<T> child : leafs) {
if(child.head.equals(anaphorKey))
return true;
found = child.DFS(anaphorKey);
if(found == true)
break;
System.out.println(child.head);
//System.out.println("anaphorKey: "+anaphorKey);
}
return found;
}
Tried implementing the given answer suggestion (#SJuan76). The implementation above isn't working as desired. Could you point me to the place where code is not as per the logic suggested?
rookie, might I suggest an implementation using the classic for-loop (as opposed to the enhanced for-loop being used now) which allows integration of your stop-condition a bit better, something like:
protected boolean DFS(String key) {
boolean found = false;
for(int i = 0; i < leafs.size() && !found; i++) {
Tree<T> child = leafs.get(i);
if(child.head.equals(key))
found = true;
else
found = child.DFS(key);
}
return found;
}
So as soon as your found condition is hit, the 'found' becomes true and your loop stops.
What you may have forgotten is the "found = child.DFS(key)" portion of the recursion, where you need to remember the result of your recursive calls so ALL your for-loops on up the chain all break as soon as you return.
Hope that helps.
Option A (Nice): the function returns a value, when the node is found it returns a different value that if the node was not found. When you call to method, if you get the found value you stop the loop and return the found value too.
Option B (Ugly): When found, thow an Exception (better if it is your own implementation of it). Don't forget to catch it.
Option C (Uglier): The same with global (static) variables.
UPDATE 1:
It looks like your method should run ok now, can you check (System.out.println) if your value is ever found?
In a more personal opinion, I would find
protected boolean DFS(String anaphorKey) {
for(Tree<T> child : leafs) {
if(child.head.equals(anaphorKey))
return true;
if(child.DFS(anaphorKey)) // No need to store value. No need to check == true (it is implicit)
return true; // If we are in this line the value was found, always return true
System.out.println(child.head);
//System.out.println("anaphorKey: "+anaphorKey);
}
return false; // If the method did not exit previously it was because the value was not found, so in this line always return false
}
more readable (but it should work exactly as your implementation)

java stack reading from an array throws ArrayIndexOutOfBoundsException

I need to fill a stack from an array, then print out the elements in order and then again reversing the order. What I'm having problems with is I'm getting an ArrayIndexOutOfBoundsException and cant figure out where it is coming from. I have tried running through the debug and it appears as I'm popping off elements it never reaches the last element. Below is my code:
public class arrayStack {
private int top;
private String[] storage;
public arrayStack(int capacity)
{
storage = new String[capacity];
top = -1;
}
public boolean isEmpty() {
return (top == 0);
}
String peek() {
return storage[top];
}
String pop() {
top--;
return storage[top];
}
public void push(String str) {
top++;
storage[top] = str;
}
}
StackMain.java:
public class StackMain {
public static void main(String[] args) {
//int j = 5;
String[] list = new String[5];
list[0] = "Beware";
list[1] = "The";
list[2] = "Ides";
list[3] = "Of";
list[4] = "March";
arrayStack stack = new arrayStack(5);
for(int i = 0; i < list.length; i++)
{
stack.push(list[i]);
}
for(int j = 0; j < list.length; j++)
System.out.println(stack.pop());
}
}
In pop(), you need to return the item that was popped, which is the item at the index of the old value of top. Cleanest way is to change the function to
String pop() {
return storage[top--];
}
Edit
You also need to change isEmpty() to return (top == -1). You could also change the implementation to use size (the number of elements) instead of top (the index of the highest element) like others mentioned.
In your constructor for arrayStack, you should set top to 0, rather than to -1. In your isEmpty method, you even check that top == 0, so clearly top == 0 means empty, rather than top == -1. This is why you always miss the last element when popping off values from the stack; putting the first element increments top to 0.
Oh, and I missed what tom said, below: decrementing top before you find the value at the top will return the wrong element. His code below is preferable, but this might be more easy to understand for a beginner:
public String pop() {
String topValue = storage[top];
top--;
return topValue;
}
If you push(String) just one element, with top initialized to -1, what will the value of top be after the push?
Now look at your pop() function, it decrements top before trying to get the element requested, so what array index is it going to try to access if you've pushed just one element?
Since you start top at -1, once you have added your 5 elements from the String array top will be 4, which is incorrect since you have 5 elements.
Then when you try to pop the stack 5 times, top goes back to -1 and storage[-1] doesn't exist so you get an ArrayIndexOutOfBoundsException
Start top at 0.
Alternatively if you decrement top after you retrieve the element from you stack, you won't get an error; but it would be better to start top at 0 because top is really representing the number of elements in your stack.
Please tag the question as homework. And coming to the problem, the problem is in the pop() function. You are decrementing the value of top first and then returning the element. But when you check the push() function, you are incrementing first and then adding the element. So, if you move the top-- to after getting the element from the stack your problem will be solved.
Your pop method is incorrect. In your code here, top starts at negative 1.
When you push an element, top becomes 0.
When you pop an element, the top becomes -1 before you access the element.
Also, your empty method is incorrect. In the initial state of the stack, top = -1, and isEmpty checks if it returns 0. Initially the stack should be empty.
your pop() function must be changed. You must store storage[pop] in a temporary variable and then reduce top by 1 and then return the temporary variable
It would be great if you can include java 1.5 generics facility to implement stack.Then your stack will be more flexible.It can hold any type of objects(in you case only Strings)
And one more advice is in the pop method you should tell garbage collector to discard to poped object as follows. (In the case if you are using generics) Following is a more flexible stack implementation which mentioned in effective java edition 2.
// Initial attempt to generify Stack = won’t compile!
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = (E[])new E[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size==0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}

Error with return in Java?

I get an error in the code from this part of my code:
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
}
return true;
}
When I remove the first return true and instead to the last return true, it don't get the error in my eclipse code, but why can't I have the first place and would this be the same? Thanks!
EDIT: The error message from eclipse say: This method must return a result of type boolean. I'm confused because isn't that what I have done?!
Yes, a break must be in the code
Can I write the method in some other way?
EDIT NUMBER 2
Why isn't this code working?
public boolean findCustomer(String inPersonalNumber){
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
}
This method returns a boolean value so I don't understand why I get an error!? The code looks right to me?
Your edit #2 doesn't compile because there is a possibility that your code won't enter the for-loop. This will be the case if customerList.size() is 0. To fix this, you'll simply need to add a return statement after the for-loop as well:
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
return true;
}
else {
return false;
}
}
return false;
Another point here is that this code doesn't logically make much sense: it will only return true or false based on the first item in your list. And this is probably not what you want. So take a closer look at several of the other answer here, many of which are good examples for how you can do this.
public boolean findCustomer(String inPersonalNumber){
boolean result = false;
// check if personal number already exist
for (int i=0; i<customerList.size();i++) {
if(customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)){
result = true;
break;
}
}
return result ;
}
When I remove the first return true and instead to the last return
true, it don't get the error in my eclipse code, but why can't I have
the first place and would this be the same?
If you remove the second return statement the code would be able to run and not return a value - this is not possible as you defined the method to have a return type of Boolean. So it must always return a value no matter what.
Just change the second return statement to false, should do what you want.
Looks like you have turned off the Build Automatically feature of eclipse. It maybe complaining about an error that used to be present when you still hadn't typed in your code fully! This can also happen if you have back-dated your system for some reason.
Also, shouldn't you be returning false if the condition doesn't satisfy?
public boolean findCustomer(String inPersonalNumber) {
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (customerList.get(i).getCustomerPersonalNumber().equals(inPersonalNumber)) {
return true;
}
}
return false;
}
First return will return only in case of all conditions satisfied, but this method should be returning boolean as per code. It would be expecting a return in failure case also.
Removing first return won't affect compilation as it has a return in second place which will work without any condtions.
Edit : Answer for your second question
This code has two return's, but what if your customerList is size 0, in that case also, method must return boolean. right? for that only, compiler is asking.
BTW, code doesn't have null checks.
Your final code could be this. Keeping multiple return statements in code in not a good practice.
public boolean findCustomer(String inPersonalNumber) {
boolean retVal = false;
if (!(inPersonalNumber == null || inPersonalNumber.trim().equals("")
|| customerList == null || customerList.size() == 0)) { // inputs are valid to run this check
// check if personal number already exist
for (int i = 0; i < customerList.size(); i++) {
if (inPersonalNumber.equals(customerList.get(i).getCustomerPersonalNumber()) { // to avoid NPE, kept inPersonalNumber in check
retVal = true;
break;
}
}
}
return retVal;
}
Because your for loop looses meaning if you're returning true anyway.
If you want to stop loop use break; instead of first return.

Categories