Copy Elements From Stack to Queue - java

I'm supposed to copy elements from a stack to a queue.
I haven't been able to think of a way to keep the stack the way it is and still copy its elements to a queue.
I ended up with this method which removes the elements completely from the stack and adds them to the queue:
public void CopyFromStack(){
E t;
int c = w.size();
while(c != 0){
t = w.pop();
enqueue(t);
c--; }}
Trying to push elements back is not an option because it'll do it backwards.
Edit: This is the class that contains my method which is my queue class:
public class Queue<E> {
protected int size;
protected Node<E> head;
protected Node<E> tail;
NodeStack<E> w = new NodeStack<E>();
NodeStack<E> w2 = new NodeStack<E>();
public Queue(){
size = 0;
head = tail = null;}
public boolean isEmpty(){
return size==0;}
public void enqueue(E elem) {
Node<E> node = new Node<E>();
node.setElement(elem);
node.setNext(null);
if (size == 0) head = node;
else tail.setNext(node);
tail = node;
size++; }
public E dequeue() {
if (size == 0) System.out.print("Queue is empty.");
E tmp = head.getElement();
head = head.getNext();
size--;
if (size == 0) tail = null;
return tmp; }
public String toString(){
String s = "";
E t;
int c = size;
while(c != 0){
t = dequeue();
s += t + " ";
enqueue(t);
c--; }
return s;}
public int FindItem(E elem){
int index=0;
int c = size;
E t;
while(c != 0){
t = dequeue();
if (t == elem)
return index;
else index++;
c--;}
System.out.print("Not found!");
return -1;}
public void CopyToStack(){
System.out.print("Elements copied to the stack are: ");
E t;
int c = size;
while(c != 0){
t = dequeue();
w.push(t);
enqueue(t);
c--;
System.out.print(w.pop()+" "); }}
public void CopyFromStack(){
E t;
int c = w.size();
while(c != 0){
t = w.pop();
enqueue(t);
c--; }}

Q: I haven't been able to think of a way to keep the stack the way it is A:
A: That's because reading from a "classic" stack is destructive. "Reading" an element == removing that element from the stack.
TWO SOLUTIONS:
1) Modify your stack implementation so that you can "peek" each element
... or ...
2) Create a new stack containing all the elements from the first one.
Q: I ended up with this method ... Trying to push elements back is not an option because it'll do it backwards.
"A: This is a variation on "Option 2): above.
SOLUTION: Just create a new stack object, and push each element at the same time as you enqueue the element.
PS:
The standard JRE implementation of Stack includes peek() and search() methods. But I don't think they would help you here. If you wanted "Option 1)", you'd have to implement your own, custom stack.
================== UPDATE ==================
Note, too:
You should always indent your methods, and indent your "if" and "loop" blocks within your methods.
You should use "camel-case" (lower-case first letter) for your method names.
Here are the "official" Java coding conventions. They were useful in 1995; they're useful today:
http://www.oracle.com/technetwork/java/index-135089.html
There's actually a third option: Java's "Stack" happens to implement "iterator". Here's an example:
EXAMPLE CODE:
package com.testcopy;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;
import java.util.Stack;
public class TestCopy {
public static void main (String[] args) {
TestCopy app = new TestCopy ();
app.run ();
}
public void run () {
// Create and populate stack
Stack<String> myStack = new Stack<String> ();
mkData(myStack);
// Copy to queue
Queue<String> myQueue = new ArrayDeque<String> ();
copyFromStack (myStack, myQueue);
// Print
int i=0;
for (String s : myQueue) {
System.out.println ("myQueue[" + i++ + "]: " + s);
}
}
#SuppressWarnings("unchecked")
public void mkData (Stack stack) {
stack.push("A");
stack.push("B");
stack.push("C");
// Stack should now contain C, B, A
}
public void copyFromStack (Stack stack, Queue queue) {
#SuppressWarnings("rawtypes")
Iterator it = stack.iterator ();
while (it.hasNext()) {
queue.add(it.next());
}
}
}
EXAMPLE OUTPUT:
myQueue[0]: A
myQueue[1]: B
myQueue[2]: C

Related

Recursive function to reverse an array implementation of a queue in Java

import java.util.Scanner;
class ed {
int fr, r;
int q[];
int n;
ed(int x) {
n = x;
fr = -1;
r = -1;
q = new int[n];
}
void enque(int n) {
int val = n;
while (r < n-1) {
if (r==n-1) {
System.out.println("Overflow");
break;
}
else if (fr==-1 && r==-1) {
fr=0;
r=0;
q[r] = val;
}
else {
r += 1;
q[r] = val;
}
}
}
void deque() {
if (fr==-1 && r==-1) {
System.out.println("Underflow");
}
else if (fr==r) {
fr=-1;
r=-1;
}
else {
fr += 1;
}
}
void reverse(int[] q) {
int a = q[0];
deque();
reverse(q);
enque(a);
}
void printq() {
for (int i = fr; i<=r; i++) {
System.out.print(q[i] + " ");
}
}
}
public class q1 {
static Scanner f = new Scanner (System.in);
public static void main(String[] args) {
int n = f.nextInt();
ed que = new ed(n);
for (int i=0; i<n; i++) {
int x = f.nextInt();
que.enque(x);
}
// que.deque();
// que.printq();
que.reverse(que.q);
}
}
My aim is to reverse a queue (Array) using a recursive function, but in VS Code, the loop is running infinite times and I'm not getting a chance to see the error. I'd like to know my mistake, and any improvement is highly appreciated.
The class ed contains a constructor which initializes the array and the front, rear values. Enque method adds an element to the queue at the rear, deque method removes the front element. Reverse method takes an array input (queue), stores the foremost element in the variable a, deques it, calls itself, then enques it at the back. VS Code is showing the error at line 48 (reverse(q), when it calls itself) but it's not showing the error as it's so far up.
A lot of things are not going the right way in your queue implementation using arrays.
Like, in enque function, you can fill values from rear = 0 to rear = n - 1, because you have n positions available in the q array.
Your code was too long, unstructured, and a bit messy with no proper variable names, So, I didn't read it any further.
But one thing I can make out is that you need to read how to implement a queue using the array.
Now, coming to queue reversal using the recursion part.
Your approach was correct, you just missed out the base case condition.
Steps for reversing queue:
Your queue has some elements, we get the first element out of the queue.
Then, we assume I have a recursive function that reverses the rest of the queue.
In this reversed queue, I just have to push that first element to the back.
And coming to the base case, each time queue size is decreasing by 1, so at the end, the queue will become empty then we don't have to do anything, just return. THUS STOPPING THE RECURSION (which you missed).
Here, is my implementation if you need some reference:
/*package whatever //do not write package name here */
import java.io.*;
import java.util.*;
class Queue {
private int front, rear, capacity;
private int queue[];
Queue(int c) {
front = rear = 0;
capacity = c;
queue = new int[capacity];
}
int size() {
return rear - front;
}
void enqueue(int data) {
if (capacity == rear) {
System.out.printf("Queue is full.\n");
return;
}
else {
queue[rear] = data;
rear++;
}
}
void dequeue() {
if (front == rear) {
System.out.printf("Queue is empty.\n");
return;
}
else {
for (int i = 0; i < rear - 1; i++) {
queue[i] = queue[i + 1];
}
if (rear < capacity)
queue[rear] = 0;
rear--;
}
}
int front() {
if (front == rear) {
System.out.printf("\nQueue is Empty.\n");
return -1;
}
return queue[front];
}
void print() {
int i;
if (front == rear) {
System.out.printf("Queue is Empty.\n");
return;
}
for (i = front; i < rear; i++) {
System.out.printf(" %d, ", queue[i]);
}
System.out.println("");
return;
}
}
class GFG {
static Scanner scanner = new Scanner(System.in);
public static void reverseQueue(Queue queue) {
if (queue.size() == 0) {
return;
}
int frontElement = queue.front();
queue.dequeue();
reverseQueue(queue);
queue.enqueue(frontElement);
}
public static void main (String[] args) {
int queueSize = scanner.nextInt();
Queue queue = new Queue(queueSize);
for (int i = 0; i < queueSize; i++) {
int element = scanner.nextInt();
queue.enqueue(element);
}
queue.print();
reverseQueue(queue);
queue.print();
}
}
You can comment if anything is wrong, or need more clarification.

How to use generic in Stack data structure?

I have implemented a simple Stack in Java and it works. It uses Node class for holding the stack int values. Now, I'm planning another class NodeWithMin that should contain the node in concern and the minimum values from the node to bottom. That means when I will get the top node of the stack I will have node and the minimum value of the stack.
I want to use generic with the Stack class to switch whichever class ( Node / NodeWithMin) that I would like to plug with it. So, finally it will be something -
public class myStack extends Stack< Node or NodeWithMin >{
}
Where Stack needs to be
class Stack<T>{
}
Let me know if you need further clarification of the question. I understand inside of some methods in the Stack class needs to changed. Any advice on how can I do that ? THANK YOU.
import java.util.*;
class Node {
public Node above;
public Node below;
public int data;
public Node(int data) {
this.data = data;
}
}
class NodeWithMin {
public NodeWithMin above;
public NodeWithMin below;
public int data;
public int min;
public NodeWithMin(int data , int min){
this.data = data;
this.min = min;
}
}
class Stack {
private int capacity;
public Node top;
public Node bottom;
public int size;
HashSet<Integer> hashSet = new HashSet<Integer>();
public Stack ( int cap ){
this.top = null;
this.bottom = null;
this.capacity = cap;
this.size = 0;
}
public static int randomInt(int n) {
return (int) (Math.random() * n);
}
public static int randomIntInRange(int min, int max) {
return randomInt(max + 1 - min) + min;
}
public boolean isFull() {
return capacity == size;
}
public void join (Node newNode, Node stackTop) {
// not empty stack
if ( stackTop != null ){
stackTop.above = newNode;
}
// if the new node is not null
// previous top is now below of the inserted node which is the current top
if ( newNode != null){
newNode.below = stackTop;
}
}
public boolean push(int v) {
if (size >= capacity)
return false;
size++;
Node n = new Node(v);
if (size == 1) bottom = n;
join(n, top);
// define the new top
top = n;
// pushing is sucessful
return true;
}
public int min(){
if ( top == null) return -1;
Node curr = this.top;
int min =-1 ;
System.out.println("\n\n");
while( curr != null){
hashSet.add(curr.data);
curr = curr.below;
}
System.out.println();
min = Collections.min(hashSet);
return min;
}
public int pop() {
Node t = top;
top = top.below;
size--;
return t.data;
}
public int peek (){
Stack myStack = this;
return myStack.top.data ;
}
public boolean isEmpty() {
return size == 0;
}
public int removeBottom() {
Node b = bottom;
bottom = bottom.above;
if (bottom != null) bottom.below = null;
size--;
return b.data;
}
public void display(){
if ( top == null) return;
Node curr = this.top;
int min =-1 ;
System.out.println("\n\n");
while( curr != null){
System.out.println( curr.data);
curr = curr.below;
if ( curr != null){
System.out.println("↑");
}
}
System.out.println();
}
public static void main ( String[] args ){
// System.out.println("\nMy stack is here \n");
Stack s = new Stack(5);
for (int j = 0; j < 5; j ++){
s.push( randomIntInRange(0, 100) );
}
s.display();
System.out.println("the min of the stack is = "+ s.min());
}
}
It looks to me as if NodeWithMin does the same basic thing as Node, plus it has the Min stuff. So I'd make NodeWithMin extend Node. Then you could declare MyStack as:
public class myStack extends Stack< ? extends Node > {
...
}
MyStack will now work with either Node or NodeWithMin.
As for Stack, the most notable problem is that it is written to explicitly depend on instances of Node. That's an issue because you say you want Stack to be generic, able to take any T. So you'll have to keep all of the T instances in the correct order without expecting them to remember who comes before or after, and that's inconsistent with what you're trying to do with NodeWithMin.
So I think you need to rethink just how generic you want this stuff to be. If Stack should really be completely generic, i.e. it should be able to keep any kind of object in LIFO order, then MyStack will have to override large portions of the methods in Stack in order to make use of what it knows about Node. OTOH, if all you really want to do is keep a bunch of Node (or subtypes thereof) objects in LIFO order, then ditch Stack completely and just go straight to MyStack.
Oh BTW, your use of HashSet is troublesome. Since you instantiate it once, you run the risk of it keeping stuff around that no longer exists in the Stack, i.e. you could pop the current min, but the min() method would keep returning it. Better to make it a local variable in the min() method since that's the only place it's used.
Further, in order to use the Collections.min() method, all of the objects in the Stack must implement Comparable, and that argues against using a generic T. You will probably want to move the min() method to MyStack (assuming that you change Node to implement Comparable).

Java Using Nodes with LinkedList

I've been working through some standard coding interview questions from a book I recently bought, and I came across the following question and answer:
Implement an algorithm to find the nth to last element in a linked list.
Here's the provided answer:
public static LinkedListNode findNtoLast(LinkedListNode head, int n) { //changing LinkedListNode to ListNode<String>
if(head == null || n < 1) {
return null;
}
LinkedListNode p1 = head;
LinkedListNode p2 = head;
for(int j = 0; j < n-1; ++j) {
if(p2 == null) {
return null;
}
p2 = p2.next;
}
if(p2 == null) {
return null;
}
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
I understand the algorithm, how it works, and why the book lists this as its answer, but I'm confused about how to access the LinkedListNodes to send as an argument to the method. I know that I'd have to create a LinkedListNode class (since Java doesn't already have one), but I can't seem to figure out how to do that. It's frustrating because I feel like I should know how to do this. Here's something that I've been working on. I'd greatly appreciate any clarification. You can expand/comment on my code or offer your own alternatives. Thanks.
class ListNode<E> {
ListNode<E> next;
E data;
public ListNode(E value) {
data = value;
next = null;
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
public class MyLinkedList<E> extends LinkedList {
LinkedList<ListNode<E>> list;
ListNode<E> head;
ListNode<E> tail;
ListNode<E> current;
ListNode<E> prev;
public MyLinkedList() {
list = null;
head = null;
tail = null;
current = null;
prev = null;
}
public MyLinkedList(LinkedList<E> paramList) {
list = (LinkedList<ListNode<E>>) paramList; //or maybe create a loop assigning each ListNode a value and next ptr
head = list.getFirst();
tail = list.getLast(); //will need to update tail every time add new node
current = null;
prev = null;
}
public void addNode(E value) {
super.add(value);
//ListNode<E> temp = tail;
current = new ListNode<E>(value);
tail.setNext(current);
tail = current;
}
public LinkedList<ListNode<E>> getList() {
return list;
}
public ListNode<E> getHead() {
return head;
}
public ListNode<E> getTail() {
return tail;
}
public ListNode<E> getCurrent() {
return current;
}
public ListNode<E> getPrev() {
return prev;
}
}
How can the LinkedListNode head from a LinkedList?
Update: I think part of my confusion comes from what to put in the main method. Do I need to create a LinkedList of ListNode? If I do that, how would I connect the ListNodes to each other? How would I connect them without using a LinkedList collection object? If someone could show me how they would code the main method, I think that would put things into enough perspective for me to solve my issues. Here's my latest attempt at the main method:
public static void main(String args[]) {
LinkedList<ListNode<String>> list = new LinkedList<ListNode<String>>();
//MyLinkedList<ListNode<String>> list = new MyLinkedList(linkedList);
list.add(new ListNode<String>("Jeff"));
list.add(new ListNode<String>("Brian"));
list.add(new ListNode<String>("Negin"));
list.add(new ListNode<String>("Alex"));
list.add(new ListNode<String>("Alaina"));
int n = 3;
//ListIterator<String> itr1 = list.listIterator();
//ListIterator<String> itr2 = list.listIterator();
LinkedListNode<String> head = new LinkedListNode(list.getFirst(), null);
//String result = findNtoLast(itr1, itr2, n);
//System.out.println("The " + n + "th to the last value: " + result);
//LinkedListNode<String> nth = findNtoLast(list.getFirst(), n);
ListNode<String> nth = findNtoLast(list.getFirst(), n);
System.out.println("The " + n + "th to the last value: " + nth);
}
In an attempt to connect the nodes without using a custom linked list class, I have edited my ListNode class to the following:
class ListNode<E> {
ListNode<E> next;
ListNode<E> prev; //only used for linking nodes in singly linked list
ListNode<E> current; //also only used for linking nodes in singly linked list
E data;
private static int size = 0;
public ListNode() {
data = null;
next = null;
current = null;
if(size > 0) { //changed from prev != null because no code to make prev not null
prev.setNext(this);
}
size++;
}
public ListNode(E value) {
data = value;
next = null;
current = this;
System.out.println("current is " + current);
if(size > 0) {
prev.setNext(current);//this line causing npe
}
else
{
prev = current;
System.out.println("prev now set to " + prev);
}
size++;
System.out.println("after constructor, size is " + size);
}
public ListNode(E value, ListNode<E> n) {
data = value;
next = n;
current = this;
if(size > 0) {
prev.setNext(this);
}
size++;
}
public void setNext(ListNode<E> n) {
next = n;
}
}
As is right now, the program will run until it reaches prev.setNext(current); in the single argument constructor for ListNode. Neither current nor prev are null at the time this line is reached. Any advice would be greatly appreciated. Thanks.
You don't actually need a separate LinkedList class; the ListNode class is a linked list. Or, to state it differently, a reference to the head of the list is a reference to the list.
The use of head, tail, current, prev in the sample code you posted has come from a double-linked list which is a data type that has links in both directions. This is more efficient for certain types of applications (such as finding the nth last item).
So I would recommend renaming your ListNode class to LinkedList and renaming next to tail.
To add a new item to the list you need a method that creates a new list with the new item at it's head. Here is an example:
class LinkedList<E> {
...
private LinkedList(E value, LinkedList<E> tail) {
this.data = value;
this.tail = tail;
}
public LinkedList<E> prependItem(E item) {
return new LinkedList(item, this);
}
}
Then to add a new item i to list you use list = list.prependItem(i);
If for some reason you need to always add the items to the end, then:
private LinkedList(E value) {
this.data = value;
this.tail = null;
}
public void appendItem(E item) {
LinkedList<E> list = this;
while (list.tail != null)
list = list.tail;
list.tail = new LinkedList<>(item);
}
However this is obviously pretty inefficient for long lists. If you need to do this then either use a different data structure or just reverse the list when you have finished adding to it.
Incidentally, an interesting side effect of this is that a reference to any item in the list is a reference to a linked list. This makes recursion very easy. For example, here's a recursive solution for finding the length of a list:
public int getLength(LinkedList list) {
if (list == null) {
return 0;
} else {
return 1 + getLength(list.getTail());
}
}
And using this a simple (but very inefficient!) solution to the problem you provided - I've renamed the method to make its function more obvious:
public LinkedList getTailOfListOfLengthN(LinkedList list, int n) {
int length = getLength(list);
if (length < n) {
return null;
} else if (length == n) {
return list;
} else {
return getTailOfLengthN(list.getTail(), n);
}
}
And to reverse the list:
public LinkedList<E> reverse() {
if (tail == null) {
return this;
} else {
LinkedList<E> list = reverse(tail);
tail.tail = this;
tail = null;
return list;
}
}
As I hope you can see this makes the methods a lot more elegant than separating the node list classes.
Actually you have created a linked list with you class ListNode.
A linked list is made of a node and a reference to another linked list (see the recursion?).

Shuffling a singly linked list using up to log N extra memory and N log N time

I am trying to shuffle a linked list by recursively, breaking it into two lists and then merging them to ensure a random shuffle.
The two problems I face are:
While I run the program, there is an infinite loop at line 56 where I tell the program to shuffle the first list.
I am unable to figure out how to add a dummy variable in case the lengths of list 1 and list 2 vary to ensure randomness in shuffling.
PS - I found it through internet search that the length of 2 lists should be same to ensure randomness but I do not know the logic behind it. Also, please let me know if there is a better way of doing it than I am trying.
Thanks in advance!
public class LinkedListShuffle
{
static public class LinkedList<E> // static nested class
{
private int N = 0;
private Node first = null;
public class Node
{
E elem;
Node next;
}
public boolean isEmpty()
{ return N == 0; }
public void push (E elem)
{
Node oldfirst = first;
first = new Node();
first.elem = elem;
first.next = oldfirst;
N++;
}
public E pop()
{
E elem = first.elem;
first = first.next;
N--;
return elem;
}
public int size ()
{ return N; }
}
public static void shuffle(LinkedList l)
{
if (l.size() == 1) return;
LinkedList.Node current = l.first;
LinkedList l1 = new LinkedList();
LinkedList l2 = new LinkedList();
while (! l.isEmpty())
{
l1.push(l.pop());
if (! l.isEmpty()) l2.push(l.pop());
}
shuffle(l1);
shuffle(l2);
/*------------------------------------------
* if (l2.size() < l1.size())
* introduce a dummy node to ensure the
* randomness in the process of shuffling
-----------------------------------------*/
merge(l, l1, l2);
/*-----------------------------------------------
* remove the dummy variable
* ----------------------------------------------*/
}
public static void merge (LinkedList l, LinkedList l1, LinkedList l2)
{
while (l1.size() != 0 && l2.size() != 0)
{
double chance = StdRandom.uniform(1);
if (chance < 0.5) l.push(l1.pop());
else l.push(l2.pop());
}
if (! l1.isEmpty())
while (! l1.isEmpty()) l.push(l1.pop());
if (! l2.isEmpty())
while (! l2.isEmpty()) l.push(l2.pop());
}
public static void main (String[] args)
{
LinkedList<String> l = new LinkedList<String>();
LinkedList<String> copy = new LinkedList<String>();
l.push("A"); l.push("B"); l.push("C"); l.push("D");
l.push("E"); l.push("F"); l.push("G"); l.push("H");
copy = l;
while (copy.size() != 0) StdOut.println(copy.pop()+" ");
shuffle(l);
while (l.size() != 0) StdOut.println(l.pop()+" ");
}
}
Your problem is that you are emptying the list when you print it in your main method, prior to calling shuffle(l).
You are assigning the list l to a variable called copy, but this variable doesn't contain a copy of the list. It refers to the same list. When you call copy.pop(), you remove an element from the original list. Therefore you call shuffle on an empty list.
public static void main (String[] args)
{
LinkedList<String> l = new LinkedList<String>();
LinkedList<String> copy = new LinkedList<String>();
l.push("A"); l.push("B"); l.push("C"); l.push("D");
l.push("E"); l.push("F"); l.push("G"); l.push("H");
copy = l;
while (copy.size() != 0) StdOut.println(copy.pop()+" "); // remove this line
// and your method will
// work
shuffle(l);
while (l.size() != 0) StdOut.println(l.pop()+" ");
}
Of course, this means your shuffle method can't handle an empty list as input.
This can be solved with a tiny fix :
public static void shuffle(LinkedList l)
{
if (l.size() <= 1) return; // instead of == 1
...
I think the randomness can be introduced in the splitting stage, in which case the merge simply needs to concatenate 2 randomly shuffled lists. Following is an implementation using a LinkedBag Linked List implementation from Robert Sedgewick's algo course, which is clearly where you got your homework from.
public static <T> LinkedBag<T> shuffle(LinkedBag<T> ll) {
if (ll.size() <= 1) return ll;
LinkedBag<T>[] sublists = split(ll);
LinkedBag<T> l1 = shuffle(sublists[0]);
LinkedBag<T> l2 = shuffle(sublists[1]);
return merge(l1, l2);
}
private static <T> LinkedBag<T>[] split(LinkedBag<T> ll) {
LinkedBag<T> l1 = new LinkedBag<>();
LinkedBag<T> l2 = new LinkedBag<>();
Iterator<T> it = ll.iterator();
while (it.hasNext()) {
if (StdRandom.bernoulli())
l1.add(it.next());
else
l2.add(it.next());
}
return (LinkedBag<T>[]) new LinkedBag<?>[]{l1, l2};
}
private static <T> LinkedBag<T> merge(LinkedBag<T> l1, LinkedBag<T> l2) {
Iterator<T> it = l2.iterator();
while (it.hasNext()) {
l1.add(it.next());
}
return l1;
}

Implement a Stack with a circular singly linked list

I'm trying to implement the a Stack in Java with a circular singly linked list as the underlying data structure. I placed the insert function for a circular linked list in replacement of the push function for the stack and so on. I don't have any errors but I'm having troubles displaying the stack. If anyone could point me in the right direction of how to display the stack or what's going wrong I'd really appreciate it!
Here is my stack class:
public class Stack {
private int maxSize; // size of stack array
private long[] stackArray;
private int top; // top of stack
private Node current = null; // reference to current node
private int count = 0; // # of nodes on list
private long iData;
public Stack(int s) // constructor
{
maxSize = s; // set array size
stackArray = new long[maxSize]; // create array
top = -1; // no items yet
}
public void push(long j) // put item on top of stack
{
Node n = new Node(j);
if(isEmpty()){
current = n;
}
n.next = current;
current = n;
count++;
}
//--------------------------------------------------------------
public Node pop() // take item from top of stack
{
if(isEmpty()) {
return null;
}
else if(count == 1){
current.next = null;
current = null;
count--;
return null;
}else{
Node temp = current;
current = current.next;
temp.next = null;
temp = null;
count--;
}
return current;
}
//--------------------------------------------------------------
public Node peek(long key) // peek at top of stack
{
Node head = current;
while(head.iData != key){
head = head.next;
}
return head;
}
//--------------------------------------------------------------
public boolean isEmpty() // true if stack is empty
{
return (count == 0);
}
//--------------------------------------------------------------
public boolean isFull() // true if stack is full
{
return (count == maxSize-1);
}
//--------------------------------------------------------------
Here is my constructor class
public class Node{
public long iData; // data item (key)
public Node next; // next node in the list
public Node(long id){ // constructor
iData = id; // next automatically nulls
}
public void displayNode(){
System.out.print(iData + " ");
}
public static void main(String[] args) {
Stack newlist = new Stack(3);
newlist.push(1);
newlist.push(2);
newlist.push(3);
newlist.push(4);
newlist.pop();
newlist.pop();
newlist.push(4);
newlist.pop();
newlist.peek(1);
newlist.push(5);
while( !newlist.isEmpty() ) // until it’s empty,
{ // delete item from stack
Node value = newlist.pop();
System.out.print(value); // display it
System.out.print(" ");
} // end while
System.out.println("");
}
//newlist.displayList();
}
First, in your main function you are printing value using System.out.print function. This displays the object's class name representation, then "#" followed by its hashcode.
Replace following lines
System.out.print(value); // display it
System.out.print(" ");
with
value.displayNode();
Second, in pop method, you are returning null when count is 1. It should return the last element which is present in the list. Also, in last else if clause, you should return temp. Replace your code with this.
public Node pop() // take item from top of stack
{
if (isEmpty()) {
return null;
}
Node temp = current;
if (count == 1) {
current = null;
} else {
current = current.next;
}
count--;
temp.next = null;
return temp;
}
A few notes on your implementation:
1) stackArray member seems to be a leftover from another array based stack implementation.
2) is max size really a requirement? if so, you don't enforce the stack size limitation in push(..)
3) Your push(..) method doesn't keep the list circular. You should close the loop back to the new node.
4) Adding a dummy node allows you to keep the linked list circular, regardless of the stack size. This can make your push(..) method simpler (as well as any iteration for printing purposes for example)
5) The peek() method contract is unclear. Usually you want the peek method to return the value in the top of the stack, without removing it. Also, why do you return type Node? This class should be hidden from the caller - it's an internal implementation detail, not something you want to expose in your API.
Following is an alternative implementation, that also supports toString():
public class Stack {
private Node EOS;
private int count = 0;
public Stack() {
EOS = new Node(0);
EOS.next = EOS;
}
public void push(long j) {
Node newNode = new Node(j);
Node tmp = EOS.next;
EOS.next = newNode;
newNode.next = tmp;
count++;
}
public Long pop() {
if (isEmpty()) {
return null;
} else {
count--;
Node node = EOS.next;
EOS.next = node.next;
return node.iData;
}
}
public Long peek() {
if (isEmpty()) {
return null;
} else {
Node node = EOS.next;
return node.iData;
}
}
public boolean isEmpty() {
return (count == 0);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node p = EOS.next;
while (p != EOS) {
sb.append(p).append("\n");
p = p.next;
}
return sb.toString();
}
private static class Node {
public long iData;
public Node next;
public Node(long id) {
iData = id;
}
#Override
public String toString() {
return "<" + iData + ">";
}
}
}

Categories

Resources