I'm trying to make a Queue in java.
The problem is that I don't know how to remove(?) a value from the array, the index value which I dequeue.
This is my code.
front() method is the dequeue part. and I used iter_ to set the current index position.
but as you can see, it dequeue's the corret value though the value still remains inside the array:(
public class IntQueue {
private int[] items_;
private int top_;
private int capacity_;
private int iter_;
public IntQueue(int capacity)
{
if(capacity <=0) capacity = 10;
capacity_ = capacity;
top_=0;
count_ = 0;
iter_=0;
items_= new int[capacity_];
}
public void push_back(int value)
{
if(top_>= capacity_)
overflow();
items_[top_++]=value;
count_++;
}
public int front()
{
if(top_<=0)
return 0;
int temp=0;
temp=items_[iter_];
count_--;
iter_++;
return temp;
}
public IntQueue clone()
{
IntQueue result = new IntQueue(capacity_);
for(int i=0 ; i<top_; ++i)
{
result.push_back(items_[i]);
}
/*for(int i=0 ; i<top_ ; ++i)
{
result.items_[i] = items_[i];
}*/
return result;
}
public void log()
{
for(int i=0 ; i <top_; ++i)
{
System.out.print(items_[i]);
if(i<top_ -1)
System.out.print(", ");
}
System.out.println();
}
}
private void overflow()
{
int[] newItem = new int[capacity_*2];
for(int i=0 ; i <top_; ++i)
newItem[i] = items_[i];
items_=newItem;
capacity_ *=2;
}
public static void main(String args[])
{
IntQueue queue = new IntQueue(2);
System.out.println("queue push 3: "); queue.push_back(3);
System.out.println("queue push 2: "); queue.push_back(2);
System.out.println("queue push 1: "); queue.push_back(1);
System.out.print("queue log: "); queue.log();
System.out.println("front " + queue.front());
System.out.println("front " + queue.front());
System.out.print("queue log: "); queue.log();
System.out.println("queue push 12: "); queue.push_back(12);
System.out.println("queue push 11: "); queue.push_back(11);
System.out.println("queue push 21: "); queue.push_back(21);
System.out.println("queue push 31: "); queue.push_back(31);
System.out.print("queue log: "); queue.log();
System.out.println("front " + queue.front());
System.out.println("front " + queue.front());
System.out.print("clone queue log: "); queue.clone().log();
}
}
What I don't get about your implementation is the following:
in the front method you're using iter_, but nowhere else. What is it good for?
if you're not using some kind of variable to keep track of what was removed without actually removing it, technically you'd need to shift all the items of the array to the left by one position, such that the first item is gone. This however is an O(N) operation.
It's easier to implement a queue using a linked list instead of an array.
When building a queue using an array, you can make a cyclic "pointer" to the head of the array, that you can use to retrieve the top.
Popping from the array is simply done by increasing this cyclic pointer.
Maintain an int variable: top, and once you need to pop an element do top = (top + 1) % items_.length
Retrieving the head is simple using items_[top].
Make sure you are guarding against popping elements that are not there (popping from an empty array).
You will probably also need to maintan a size variable for the queue's size.
Below I share my proposed solution for a simple thread-safe FIFO queue :D
public class Queue extends Object {
private int numElements;
private Node first;
private Node last;
/**
* Helper linked list class
*/
private static class Node {
private Object item;
private Node next;
}
/**
* Creates a new Queue object.
*/
public Queue() {
numElements = 0;
first = last = null;
}
/**
* Puts an object at the end of the queue.
*
* #param object
*/
public void putObject(Object object) {
synchronized (this) {
Node newNode = new Node();
newNode.item = object;
newNode.next = null;
if ( numElements == 0 ) {
first = last = newNode;
} else {
last.next = newNode;
last = newNode;
}
numElements += 1;
}
}
/**
* Gets an object from the beginning of the queue. The object is removed
* from the queue. If there are no objects in the queue, returns null.
*/
public Object getObject() {
synchronized (this) {
Object item = null;
if ( numElements > 0 ) {
item = first.item;
first = first.next;
numElements -= 1;
if (numElements == 0) {
last = null;
}
}
return item;
}
}
}
You cant remove an element from an array like a List. You need to move the values up and set the last index of the array as null. Take a look at the source of a java class that implement Queue.remove() method. For example following is the code from removeAt(int index) method of ArrayBlockingQueue.
void removeAt(int i) {
final E[] items = this.items;
// if removing front item, just advance
if (i == takeIndex) {
items[takeIndex] = null;
takeIndex = inc(takeIndex);
} else {
// slide over all others up through putIndex.
for (;;) {
int nexti = inc(i);
if (nexti != putIndex) {
items[i] = items[nexti];
i = nexti;
} else {
items[i] = null;
putIndex = i;
break;
}
}
}
--count;
notFull.signal();
}
when you design a queue, you need to decide the priority like how you are going to add and remove element from it.You can go through this link and implement it similar to this.
FIFO
A typical example is :
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<String> qe=new LinkedList<String>();
qe.add("b");
qe.add("a");
qe.add("c");
qe.add("e");
qe.add("d");
Iterator it=qe.iterator();
System.out.println("Initial Size of Queue :"+qe.size());
while(it.hasNext())
{
String iteratorValue=(String)it.next();
System.out.println("Queue Next Value :"+iteratorValue);
}
// get value and does not remove element from queue
System.out.println("Queue peek :"+qe.peek());
// get first value and remove that object from queue
System.out.println("Queue poll :"+qe.poll());
System.out.println("Final Size of Queue :"+qe.size());
}
}
First of all, you can't delete an item from an array, you can just overwrite it. You can use a List instead.
Another option is to use a circular queue, as amit's answer pointed out.
A simple solution using array is:
int queue[SIZE];
int first = 0;
int last = 0;
void enque(int i) {
if(last == SIZE)
throw new RuntimeExeption("Queue is full");
queue[last++] = i;
}
int deque() {
if(first == last)
throw new RuntimeExeption("Queue is empty");
return queue[first++];
}
Check this: it has enqueue and dequeue methods:
import java.io.*;
import java.lang.*;
class clrqueue
{
DataInputStream get=new DataInputStream(System.in);
int a[];
int i,front=0,rear=0,n,item,count=0;
void getdata()
{
try
{
System.out.println("Enter the limit");
n=Integer.parseInt(get.readLine());
a=new int[n];
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
void enqueue()
{
try
{
if(count<n)
{
System.out.println("Enter the element to be added:");
item=Integer.parseInt(get.readLine());
a[rear]=item;
rear++;
count++;
}
else
System.out.println("QUEUE IS FULL");
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
void dequeue()
{
if(count!=0)
{
System.out.println("The item deleted is:"+a[front]);
front++;
count--;
}
else
System.out.println("QUEUE IS EMPTY");
if(rear==n)
rear=0;
}
void display()
{
int m=0;
if(count==0)
System.out.println("QUEUE IS EMPTY");
else
{
for(i=front;m<count;i++,m++)
System.out.println(" "+a[i]);
}
}
}
class Myqueue
{
public static void main(String arg[])
{
DataInputStream get=new DataInputStream(System.in);
int ch;
clrqueue obj=new clrqueue();
obj.getdata();
try
{
do
{
System.out.println(" 1.Enqueue 2.Dequeue 3.Display 4.Exit");
System.out.println("Enter the choice");
ch=Integer.parseInt(get.readLine());
switch (ch)
{
case 1:
obj.enqueue();
break;
case 2:
obj.dequeue();
break;
case 3:
obj.display();
break;
}
}
while(ch!=4);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
This is the code i implemented and is working fine in my system.
import java.util.Arrays;
public class Queue {
public int[] queue = new int[3];
int head = -1, tail =-1;
public void enqueue(int N){
if(tail == (queue.length-1))
queue = Arrays.copyOf(queue,2*queue.length);
if(head == -1){
head++;
tail++;
queue[head] = N;
}
else {
tail++;
queue[tail] = N;
}
}
public int dequeue(){
if(head == -1)
throw new IllegalStateException("Cannot dequeue if queue is empty");
int firstItem = queue[head];
if (head == tail) {
head = -1;
tail = -1;
}
else
head++;
return firstItem;
}
public void display(){
for (int i = head; i<= tail ; i++){
System.out.println("Display: " + queue[i]);
}
}
}
public class Main {
public static void main(String[] args) {
Queue queue = new Queue();
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
queue.enqueue(40);
queue.display();
int dequeue = queue.dequeue();
System.out.println(dequeue);
queue.display();
int dequeue1 = queue.dequeue();
System.out.println(dequeue1);
queue.display();
}
}
Related
I have the following code where I have implemented a circular array. The problem comes when I try to display it. The display method works well until the array gets full and last goes back to 0. Therefore last and first are both 0 and the for loop doesn't execute.
public class PassengerQueue
{
private Passenger[] queueArray = new Passenger[TrainStation.WAITING_ROOM_CAPACITY];
private int first = 0;
private int last = 0;
private int maxStayInQueue = 0; //number of seconds that the passenger who stayed longest in the queue
private int maxLength = 0; //the maximum legth that was reached by the queue
private int currentSize = 0;
public void add(Passenger next)
{
//if the queue is not full - check for the circular queue
if (isFull()){
System.out.println("The queue is full");
}
else
{
queueArray[last] = next;
last = (last + 1) % queueArray.length;
currentSize++;
maxLength++;
}
}
public Passenger remove()
{
Passenger removedPassenger = null;
//if the queue array is not empty
//remove passenger
if (isEmpty())
{
System.out.println("The queue is empty");
}
else
{
removedPassenger = queueArray[first];
queueArray[first] = null;
first = (first + 1) % queueArray.length;
currentSize--;
}
return removedPassenger;
}
public Boolean isEmpty()
{
return (currentSize == 0);
}
public Boolean isFull()
{
return (currentSize == queueArray.length);
}
public void display()
{
if (isEmpty())
{
System.out.println("The queue is empty");
}
else
{
for(int i = first; i < last; i++)
{
queueArray[i].display();
}
}
}
Any help would be appreciated! Thank You
You can change the loop so it iterates from 0 to size. This also fixes the problem where last is less than first because items have been removed.
for(int i = 0; i < currentSize; i++)
{
queueArray[(first + i) % queueArray.length].display();
}
Just use the properties on the array itself to display:
public void display()
{
if (isEmpty())
{
System.out.println("The queue is empty");
}
else
{
for(int i = 0; i < queueArray.length; i++)
{
queueArray[i].display();
}
}
}
I've been trying to double the size of my queue and I have tried several different methods, this one has given me the closest result to what I am trying to get, however, it copies all the values already in the queue into the newly created spaces instead of leaving them empty for me to add more objects.
I have two classes, and the only part I need to change is the enqueue method.
The last line should print 50 40 30 20 60 70 instead.
public class Queue{
private int QUEUE_SIZE = 5;
private Object[] items;
private int front, back, count;
public Queue() {
items = new Object[QUEUE_SIZE];
front = 0;
back = QUEUE_SIZE -1;
count =0;
}
public boolean isEmpty(){
return count ==0;
}
public boolean isFull(){
return count == QUEUE_SIZE;
}
public void enqueue(Object newItem){
if (!isFull()){
back = (back+1) % QUEUE_SIZE;
items[back] = newItem;
count++;
return;
} else
System.out.println("Queue is full. Doubling the size.");
count = (QUEUE_SIZE*2);
System.out.println("New max size is: " + QUEUE_SIZE);
}
public Object dequeue(){
if (!isEmpty()){
Object queueFront = items[front];
front = (front+1) % QUEUE_SIZE;
count--;
return queueFront;
}else
System.out.println("Trying to dequeue from empty queue");
return null;
}
public void dequeueAll(){
items = new Object[QUEUE_SIZE];
front = 0;
back = QUEUE_SIZE -1;
count =0;
}
public Object peek(){
if (!isEmpty()) {
return items[front];
}
else
System.out.println("Trying to peek with empty queue");
return null;
}
public int size(){
return count;
}
}
import java.util.Stack;
public class Runner {
public static void main(String[] args) {
Queue q = new Queue();
createQueue(q);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to dequque one element.");
q.dequeue();
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to reverse my queue: ");
reverseQueue(q);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to enqueue 60.");
q.enqueue(60);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to enqueue 70.");
q.enqueue(70);
System.out.println("My queue is as follows: ");
printQueue(q);
}
public static Queue createQueue(Queue q){
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
q.enqueue(40);
q.enqueue(50);
return q;
}
public static void printQueue(Queue q){
int s = q.size();
for(int i=0; i<s; i++){
int temp = (int)q.dequeue();
q.enqueue(temp);
System.out.print(temp+ " ");
}
System.out.println();
}
public static void reverseQueue(Queue q){
Stack s = new Stack();
while(!q.isEmpty()){
s.push(q.dequeue());
}while(!s.isEmpty()){
q.enqueue(s.pop());
}
}
}
The else block in enqueue(Object newItem) does not insert new Object so it should be like this :
public void enqueue(Object newItem) {
if (!isFull()) {
back = (back + 1) % QUEUE_SIZE;
items[back] = newItem;
count++;
return;
}
else {
System.out.println("Queue is full. Doubling the size.");
QUEUE_SIZE = (QUEUE_SIZE * 2); // double queue size not count
System.out.println("New max size is: " + QUEUE_SIZE);
Object[] temp = new Object[QUEUE_SIZE]; // temp array
System.arraycopy(items, front, temp, front, items.length - front); // copy the elements from front index to items.length-front
if (front != 0) {
System.arraycopy(items, 0, temp, items.length, front); // copy the elements in the range items[0] to items[back] into the new array
}
items = temp; // set items to temp array
back = front + count;
items[back] = newItem; // set new item
count++; // increment count
}
}
It is about printQueue() method, after the count = (QUEUE_SIZE*2); line of enqueue() method the size of items array actually didn't expand. It is still 5 in any case, count = (QUEUE_SIZE*2); provide that isFull() method returns false.
If you debug printQueue() method, you will see that int s = 10 but items array still [30, 20, 60, 50, 40].
After Queue becomes full, You are not enqueuing the items. So the item is not inserted into the queue after becomes full.Have modified the code.
package org.sunil.addressbook.dao;
import java.util.Stack;
class Queue{
private int QUEUE_SIZE = 5;
private Object[] items;
private int front, back, count;
public Queue() {
items = new Object[QUEUE_SIZE];
front = 0;
back = QUEUE_SIZE -1;
count =0;
}
public boolean isEmpty(){
return count ==0;
}
public boolean isFull(){
return count == QUEUE_SIZE;
}
public void enqueue(Object newItem){
if (!isFull()){
back = (back+1) % QUEUE_SIZE;
// System.out.println("back output is "+back);
items[back] = newItem;
count++;
} else{
System.out.println("Queue is full. Doubling the size.");
back=QUEUE_SIZE-1;
QUEUE_SIZE = (QUEUE_SIZE*2);
Object[] temp = new Object[QUEUE_SIZE];
int j=0;
for (int i = front; i < items.length; i++){
temp[j] = items[i];
j++;
}
for (int i = 0; i < front; i++){
temp[j] = items[i];
j++;
}
items = temp;
front=0;
back = (back+1) % QUEUE_SIZE;
items[back] = newItem;
count++;
}
}
public Object dequeue(){
if (!isEmpty()){
Object queueFront = items[front];
front = (front+1) % QUEUE_SIZE;
count--;
return queueFront;
}else
System.out.println("Trying to dequeue from empty queue");
return null;
}
public void dequeueAll(){
items = new Object[QUEUE_SIZE];
front = 0;
back = QUEUE_SIZE -1;
count =0;
}
public Object peek(){
if (!isEmpty()) {
return items[front];
}
else
System.out.println("Trying to peek with empty queue");
return null;
}
public int size(){
return count;
}
}
public class Runner {
public static void main(String[] args) {
Queue q = new Queue();
createQueue(q);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to dequque one element.");
q.dequeue();
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to reverse my queue: ");
reverseQueue(q);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to enqueue 60.");
q.enqueue(60);
System.out.println("My queue is as follows: ");
printQueue(q);
System.out.println("I am going to enqueue 70.");
q.enqueue(70);
System.out.println("My queue is as follows: ");
printQueue(q);
}
public static Queue createQueue(Queue q){
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
q.enqueue(40);
q.enqueue(50);
return q;
}
public static void printQueue(Queue q){
int s = q.size();
for(int i=0; i<s; i++){
int temp = (Integer)q.dequeue();
q.enqueue(temp);
System.out.print(temp+ " ");
}
System.out.println();
}
public static void reverseQueue(Queue q){
Stack s = new Stack();
while(!q.isEmpty()){
s.push(q.dequeue());
}while(!s.isEmpty()){
q.enqueue(s.pop());
}
}
}
I've attempted to implement a priority queue using an Array of Objects "Queue Items" which have some data (a string), and an integer which is the priority. I am trying to make those items comparable so that when I add a new object to the queue I can iterate through the items and add the new item in the correct location and move all items that are now behind it backwards, however when I add a new item to the queue I get a null pointer exception. I'll include all my code, but the toString method was just copied in from a queue so it won't work as expected.
class QueueItem implements Comparable<QueueItem> {
String data;
int pri;
public QueueItem(String data, int pri) {
this.data = data;
this.pri = pri;
}
#Override
public int compareTo(QueueItem item) {
return this.data.compareTo(item.data);
}
}
public class PriorityQueue implements Queue<String> {
private QueueItem[] arr;
private int frontPos, backPos;
public PriorityQueue() {
arr = new QueueItem[20];
backPos = -1;
frontPos = 0;
}
public boolean isEmpty() {
return frontPos == (backPos + 1) % arr.length;
}
public String front() {
if (frontPos == (backPos + 1) % arr.length)
throw new QueueException("Empty Queue - front");
return arr[frontPos].data;
}
public int frontPri() {
if (frontPos == (backPos + 1) % arr.length)
throw new QueueException("Empty Queue - frontPri");
return arr[frontPos].pri;
}
public void addToPQ(String str, int x) {
if (arr.length==0) {
arr[frontPos] = new QueueItem(str, x);
frontPos++;
return;
}
else {
for (int i = 0; i < arr.length; i++) {
arr[i].compareTo(new QueueItem(str, x));
}
}
}
public void deleteFront() {
if (frontPos==(backPos+1)%arr.length) {
throw new QueueException("Empty Queue - deleteFront");
}
frontPos = (frontPos+1)%arr.length;
}
public String toString() {
if (frontPos == (backPos + 1) % arr.length) {
return "<>";
}
StringBuffer sb = new StringBuffer();
sb.append('<');
int pos = frontPos;
while (pos != backPos) {
sb.append(arr[pos]);
sb.append(',');
pos = (pos + 1) % arr.length;
}
sb.append(arr[backPos]);
sb.append('>');
return (sb.toString());
}
}
public interface Queue<String> {
public void addToPQ(String str, int x);
public void deleteFront();
public String front();
public boolean isEmpty();
public int frontPri();
}
class QueueException extends RuntimeException {
QueueException(String s) {
super("Tried to apply " + s + " to empty queue");
}
}
public class pqTest {
public static void main(String[] args) {
PriorityQueue pQ = new PriorityQueue();
if (pQ.isEmpty()) {
System.out.println("Queue is Empty - isEmpty");
}
pQ.addToPQ("Dog", 4);
pQ.addToPQ("Cat", 20);
pQ.deleteFront();
pQ.addToPQ("Fish", 2);
}
}
The problem is that arr is size 20 so the first element won't even be added through the if statement in your addToPQ method because arr.length != 0. So it will then go to your else statement, which iterates through every single element in arr. But arr has 20 null elements since each spot within the array of QueueItems has not been initialized. So you should change your condition in the if statement to frontPos == 0 and change the terminating condition in your loop to i < frontPos so that the method won't iterate through null elements within arr
public void addToPQ(String str, int x) {
if (frontPos==0) {
arr[frontPos] = new QueueItem(str, x);
frontPos++;
return;
}
else {
QueueItem item = new QueueItem(str, x);
for (int i = 0; i < frontPos; i++) {
arr[i].compareTo(item);
}
}
}
You get NullPointerException, because when you are adding second item, you go to else statment where you iterate over array with one non-null element and 19 nulls. So you need to change your code to check if array element at i is null and if it is, assign new element to it.
I have here a single linked list for a program that makes a collage. This runs perfectly but I was wondering how to make it a double linked list. I really have no idea what a double linked is though or how to create one. Any help would be appreciated...
There are 3 classes.
class LinearCollage
{
private Picture myArray[];
private class Node
{
Picture data;
Node pNext;
};
private Node pFirst;
private Node pLast;
private int nPictures;
private Picture clipboard;
public LinearCollage()
{
pFirst = null;
pLast = null;
nPictures = 0;
}
public void addPictureAtEnd(Picture aPictureReference)
{
Node temp = new Node();
temp.data = aPictureReference;
temp.pNext = null;
if( pLast == null )
{
pLast = temp;
pFirst = temp;
}
else
{
pLast.pNext = temp;
pLast = temp;
}
nPictures++;
}
public Picture makeCollage()
{
int collageHeight = 400;
int collageWidth = 400;
for( Node finger = pFirst; finger != null; finger = finger.pNext )
{
System.out.println("Process Picture " + finger.data);
}
Picture retval = new Picture(collageHeight,collageWidth);
int i = 0;
for( Node finger = pFirst; finger != null; finger = finger.pNext )
{
System.out.println("Process Picture " + finger.data);
finger.data.compose(retval, 50*i, 50*i);
i++;
}
return retval;
}
public void cutMiddle()
{
int cutIndex = nPictures-1;
clipboard = myArray[cutIndex];
for( int i = cutIndex; i < nPictures - 1; i++ )
{
myArray[i] = myArray[i + 1];
}
nPictures--;
}
public void cutEnd()
{
int cutIndex = nPictures;
clipboard = myArray[cutIndex];
for( int i = cutIndex; i<nPictures - 1; i++)
{
myArray[i] = myArray[i + 1];
}
nPictures--;
}
public void pasteEnd()
{
myArray[nPictures] = clipboard;
nPictures++;
}
public boolean isFull()
{
return false;
}
public boolean isEmpty()
{
return nPictures == 0;
}
}
import java.util.Scanner;
class LineCollageMaker
{
public static void main(String a[])
{
LinearCollage myCollage;
Scanner uiInput = new Scanner(System.in);
myCollage = new LinearCollage();
FileChooser.pickMediaPath();
boolean inputting = true;
while( inputting )
{
System.out.println("Another picture? Type Y if so.");
String answer = uiInput.next();
if(answer.equals("Y"))
{
Picture pin = new Picture(FileChooser.pickAFile());
myCollage.addPictureAtEnd(pin);
}
else
{
inputting = false;
}
}
Picture firstToShow = myCollage.makeCollage();
firstToShow.show();
//YOU Code the user inteface loop and dispatch to methods
//of myCollage here..
boolean done = false;
while( !done )
{
System.out.println("MENU (CASE SENSITIVE!)");
System.out.println("CM - cut middle and move it to the clipboard");
System.out.println("PE - paste clipboard to end");
System.out.println("CE - cut end and move it to clipboard");
System.out.println("XX - stop running this program");
String command = uiInput.next();
if(command.equals("XX"))
done = true;
else if(command.equals("CM"))
{
if(myCollage.isEmpty())
{
System.out.println("Can't cut from an empty collage.");
}
else
{
myCollage.cutMiddle();
myCollage.makeCollage().show();
}
}
else if(command.equals("PE"))
{
if(myCollage.isFull())
{
System.out.println("Can't paste to an empty collage.");
}
else
{
myCollage.pasteEnd();
myCollage.makeCollage().show();
}
}
else if(command.equals("CE"))
{
if(myCollage.isEmpty())
{
System.out.println("Can't copy from an empty collage.");
}
else
{
myCollage.cutEnd();
myCollage.makeCollage().show();
}
}
else
System.out.println("Unrecognized command. Try again.");
}
}
}
public class Node
{
//le class variables
private Picture myPic;
private Node next;
//le constructors
public Node(Picture heldPic)
{
myPic=heldPic;
next=null;
}
public void setNext(Node nextOne)
{
this.next=nextOne;
}
public Node getNext()
{
return this.next;
}
public Picture getPicture()
{
return this.myPic;
}
//le methods
public void drawFromMeOn(Picture bg)
{
Node current;
int currentX=0, currentY=bg.getHeight()-1;
current = this;
while (current != null)
{
current.drawMeOn(bg,currentX, currentY);
currentX = currentX + current.getPicture().getWidth();
current=current.getNext();
}
}
private void drawMeOn(Picture bg, int left, int bottom)
{
this.getPicture().blueScreen(bg, left, bottom-this.getPicture().getHeight());
}
}
A doubly linked list is simply a linked list where every element has both next and prev mebers, pointing at the elements before and after it, not just the one after it in a single linked list.
so to convert your list to a doubly linked list, just change your node to be:
private class Node
{
Picture data;
Node pNext;
Node pPrev;
};
and when iterating the list, on each new node add a reference to the previous node.
A doubly-linked list takes a singly-linked list one step further by also having a reference to the previous node, rather than just the next one.
I confess I am slightly confused by your code as it looks like you have a private class for Node and then another public class for it. To make this a doubly-linked list add another Node instance variable into your Node class which references the previous node, and then update this variable when you add in new nodes.
You can convert Single linked list to Double linked list via a concept called XOR based linked list. The beauty of XOR truth table makes suitable for this use case.
Check this out : https://www.geeksforgeeks.org/xor-linked-list-a-memory-efficient-doubly-linked-list-set-1/
As a portion of a first year assignment, I need to create a class which uses a provided linked list implementation to implement a provided stack interface which is then tested by another provided class. I was able to easily complete the assignment using my own LL; however, I was told that I needed to use the one provided.
Exception in thread "main" java.lang.NullPointerException
at StackLL.<init>(StackLL.java:21)
at StackTester.main(StackTester.java:91)
Now I get null pointer exceptions whenever I try and run it. I thought this was being caused by the tester trying to grab the size of the list before the LL is initialized, but that doesn't seem to be the case and I am stumped.
Any tips on what I can do to fix the bug so that I can hand in the rest of the assignment? Thanks :)
The provided linked list implementation
LinkedList.java
/**
* LinkedList - a simple linked list of ints
*/
public class LinkedList
{
Node head;
int count;
public LinkedList ()
{
head = null;
count = 0;
}
/**
* Adds the given item to the start of the list
*/
public void addToStart (int item)
{
Node newNode = new Node();
newNode.value = item;
if (head != null)
newNode.next = head;
head = newNode;
count++;
}
/**
* Adds the given item to the end of the list
*/
public void addToEnd (int item)
{
if (size() == 0)
{
addToStart (item);
}
else
{
Node n = head;
while (n.next != null)
n = n.next;
n.next = new Node(item);
count++;
}
}
/**
* Remove and return the first item in the list
*/
public int removeFromStart ()
{
if (size() == 0)
throw new EmptyListException();
int valtoReturn = head.value;
head = head.next;
count--;
return valtoReturn;
}
/**
* Remove and return the last item in the list
*/
public int removeFromEnd ()
{
if (size() == 0)
throw new EmptyListException();
if (size() == 1)
return removeFromStart();
else
{
Node n = head;
while (n.next.next != null)
n = n.next;
int valtoReturn = n.next.value;
n.next = null;
count--;
return valtoReturn;
}
}
/**
* Return the number of items contained in this list
*/
public int size ()
{
return count;
}
/**
* A basic node class
*/
private class Node
{
int value;
Node next;
Node()
{
}
Node (int value)
{
this.value = value;
}
}
// random testing code for the Linked List
public static void main (String [] args)
{
LinkedList l = new LinkedList();
l.addToStart (5);
int val = l.removeFromStart();
System.out.println (val == 5 ? "passed" : "failed");
System.out.println (l.size() == 0 ? "passed" : "failed");
for (int x = 0; x < 10; x++)
l.addToEnd (x);
System.out.println (l.size() == 10 ? "passed" : "failed");
while (l.size() > 0)
System.out.print (l.removeFromEnd() + " ");
System.out.println ();
}
}
/**
* The exception class when a removal action is performed on
* an empty list.
*/
class EmptyListException extends RuntimeException
{
public EmptyListException ()
{
super();
}
public EmptyListException (String s)
{
super(s);
}
}
My implementation
StackLL.java
/**
* A linked list implementation of the Stack ADT.
*
*/
public class StackLL implements Stack
{
// The linked list that will contain the values in the stack
private LinkedList values;
public int size()
{
return values.size();
}
public boolean isEmpty()
{
if (values.size() <= 0) {
return true;
}
return false;
}
public void push(int element)
{
values.addToStart(element);
}
public int pop() throws StackEmptyException
{
if (values.size() == 0) {
throw new StackEmptyException();
}
else {
return values.removeFromStart();
}
}
public int peek() throws StackEmptyException
{
if (values.size() == 0) {
throw new StackEmptyException();
}
else { //This is a pretty silly way to do this, but I can't think of any other way without making my own linked list method.
int elementVal = values.removeFromStart();
values.addToStart(elementVal);
return elementVal;
}
}
}
The Provided Interface
Stack.java
/**
* Stack.java
*
* A specification of the Stack ADT
*
*/
public interface Stack
{
int size();
boolean isEmpty();
void push (int element);
int pop() throws StackEmptyException;
int peek() throws StackEmptyException;
}
class StackEmptyException extends Exception
{
public StackEmptyException ()
{
super();
}
public StackEmptyException (String s)
{
super(s);
}
}
The Tester
StackTester.java
/**
* StackTester.java
*
* Some test cases for a stack.
*/
public class StackTester
{
public static void testOne (Stack s)
{
try
{
if (s.size() != 0 || !s.isEmpty())
System.out.println("1: Failed size or isEmpty.");
s.push(1);
s.push(2);
if (s.size() != 2 || s.isEmpty())
System.out.println("2: Failed size or isEmpty.");
if (!(s.pop() == 2))
System.out.println("3: Failed pop");
if (!(s.peek() == 1))
System.out.println("4: Failed peek");
if (!(s.pop() == 1))
System.out.println("5: Failed pop");
if (s.size() != 0 || !s.isEmpty() )
System.out.println("6: Failed size or isEmpty.");
}
catch (StackEmptyException e)
{
System.out.println(e);
}
}
public static void testTwo (Stack s)
{
try
{
for (int i = 0; i < 100; i++)
{
s.push(i);
}
if (s.size() != 100)
System.out.println("7: Failed size.");
for (int i = 99; i >= 0; i--)
{
if (!(s.pop() == i))
{
System.out.println("Failed pop for: " + i);
break;
}
}
}
catch (StackEmptyException e)
{
System.out.println("Failed testTwo.");
System.out.println(e);
}
}
public static void testThree (Stack s)
{
try {
while (!s.isEmpty())
s.pop();
}
catch (StackEmptyException e) {
System.out.println ("Failed empty stack test (popped on a non empty stack threw exception)");
}
try
{
s.pop();
System.out.println("Failed empty stack test.");
}
catch (StackEmptyException e)
{
/* If we get here, we
* passed the previous test.
*/
}
}
public static void main (String args[])
{
Stack s1 = new StackLL();
Stack s2 = new StackLL();
Stack s3 = new StackLL();
testOne(s1);
testTwo(s2);
testThree(s3);
}
}
You have private LinkedList values; in StackLL.
That says "this class has a field called values of type LinkedList". It does not assign an object to values, so when you try to access it, a NullPointerException occurs.
You should be able to fix it by assigning a value to values, i.e.:
private LinkedList values = new LinkedList();
(I don't know if you've learned about generics yet, but if you have, remember to add the type, e.g. LinkedList<Person>.)
Look at the line of code given in the error message (I'm assuming its the return statement in your size() function) and think about the meaning of NullPointerException -- the variable which is null is not yet initialized. Then ask yourself, do I expect this variable to be initialized here? If yes, then ask why isn't it and where should it be initialized? If no, then you have a logic error at the given location.
You aren't ever instantiating a LinkedList object in StackLL. So the first time you try to access it, it blows a NPE.