I'm trying to create a priority queue in java with the use of a linked list, but something isn't working. I understand the general functionality of the priority queue, but I'm a complete beginner when it comes to java. I've looked at other examples and can't seem to find what's wrong in mine. Any advice? One thing I've noticed is the use of type or or whatever, but I'm not exactly sure what that is.
First class:
public class Node { //Node class structure
int data; //data contained in Node
Node next; //pointer to Next Node
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
Second class:
import work.Node;
//basic set-up of a singly linked list
public class SLList{
Node head; //head of SLList
Node tail; //tail of SLList
int n; //number of elements in SLList
}
Third class:
import work.Node;
public class PriorityQueue extends SLList{
//add a new node
public void add(int x){
Node y = new Node();
y.data = x;
if (tail == null){ //if there is no existing tail, thus an empty list
tail = y; //assign tail and head as new node y
head = y;
}
else if (y.data < head.data){ //if new node y is the smallest element, thus highest priority
y.next = head; //assign y's next to be current head of queue
head = y; //reassign head to be actual new head of queue (y)
}
else{ //if there is already a tail node
tail.next = y; //assign the tail's pointer to the new node
tail = y; //reassign tail to actual new tail of queue (y)
}
n++; //increment the queue's size
}
//delete the minimim (highest priority value) from the queue
public Node deleteMin(){
if (n == 0){ //if the list is of size 0, and thus empty
return null; //do nothing
}
else{ //if there are node(s) in the list
Node min = head; //assign min to the head
head = head.next; //reassign head as next node,
n--; //decrement list size
return min; //return the minimum/highest priority value
}
}
//return the size of the queue
public int size() {
return n;
}
}
Tester code:
import work.Node;
import work.SLList;
import work.PriorityQueue;
public class Test {
public static void main(String[] args){
PriorityQueue PQueue1 = new PriorityQueue();
PQueue1.add(3);
PQueue1.add(2);
PQueue1.add(8);
PQueue1.add(4);
System.out.println("Test add(x): " + PQueue1);
System.out.println("Test size() " + PQueue1.size());
PriorityQueue PQueue2 = new PriorityQueue();
PQueue2 = PQueue1.deleteMin(); //the data types don't line up but I don't know what should be changed
System.out.println("Test deleteMin() " + PQueue2);
System.out.println("Test size() " + PQueue2.size());
}
}
Code from your Test class
PQueue2 = PQueue1.deleteMin(); //this line isn't working*
This line is not working because of Type mismatch: you cannot convert from Node to PriorityQueue.
API Specifications for the ClassCastException:
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. For example, the following code generates a ClassCastException:
In your example, this will work;
Node node = PQueue1.deleteMin(); //this will work
Related
I am taking a course in Data Structures at University and I am having troubles understanding why my Singly Linked List is not following FIFO algorithm.
Here is my Node/PSVM class:
public class Node {
protected int data;
protected Node next;
Node(int element){
this.data = element;
next = null;
}
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.addElement(300);
ll.addElement(600);
ll.addElement(900);
ll.addElement(1200);
ll.printList();
}
}
This is my Linked List Class:
public class LinkedList {
// create a reference of type node to point to head
Node head;
// keep track of the size of ll
int size = 0;
void printList() {
Node n = head;
for (int i = 0; i < llSize(); i++) {
System.out.print(n.data + " ");
n = n.next;
}
System.out.println("");
}
int llSize() {
return this.size;
}
boolean isEmpty() {
return size == 0;
}
void addElement(int element) {
if (isEmpty()) {
head = new Node(element);
} else {
Node nNode = new Node(element);
Node current = head;
while(current.next != null){
current = current.next;
}
current.next = nNode;
}
this.size++;
}
}
Sorry in advance if this is a basic question/problem. I have asked my professor and she sent me a YouTube link which really didn't help.
Thank you for your time.
The code has no bugs.
For the list to behave as FIFO, nodes will be added to one end and deleted from the opposite end.
Therefore, you will have to implement a delete operation. You can maintain separate reference to the head and tail node.
I can't seem to get the printing and adding to the LinkedList working as it is now.
When I add one or two nodes, it works fine. Any more than that it doesn't work as expected.
For example: adding 4 and 3 using adding first
3->4->
But when I add one more, this is what I get:
2->3->3->
Can anyone tell me with this is the case. I am fairly new to programming.
public class LinkedListPractice{
public static void main(String[]args){
//add items to the LinkedList
GenericLinkedList<Integer> gLink = new GenericLinkedList<>();
gLink.addFirst(4);
gLink.addFirst(3);
gLink.addFirst(2);
gLink.addFirst(1);
gLink.printList();
}//main method
} //LinkedListPractice
class GenericLinkedList<E>{
int size; //represents number of nodes in the LinkedList
Node<E> head;
public GenericLinkedList(){
size = 0;
head = null;
} //GenericLinkedList no parameter constructor
//printList
public void printList(){
Node<E> current = head;
for(int i = 0; i < size; i++){
System.out.print(current.getData() + "->");
current = head.next;
} //for
} //printList
public void addFirst(E element){
Node<E> newNode = new Node<E>(element);
if(head == null){head = newNode;}
else{
newNode.next = head;
head = newNode;
}
size++;
} //addFirst
public boolean isEmpty(){
if(head == null){
return true;
}else
return false;
} //isEmpty
//inner node class
private static class Node<E>{
//private data fields
private E data;
private Node<E> next; //represents the next link in the LinkedList
public Node(E element){
data = element;
next = null;
} //Node class constructor
public E getData(){
return data;
} //getData
} //Node class
} //GenericLinkedList
There's a problem in printList(). Head never seems to get updated, so you are always printing the node after head which would be 3 in this case.
A better solution could be to update current after each iteration of a loop.
So I am having trouble trying to build a linked list from a method that has two integer parameters n and m. Parameter n is the length of nodes of the linked list, and m is the parameter that contains random integers from 0 to m-1 inside the list of nodes. I am required to build this linked list from a predefined Node class that cannot be changed, and to return the reference to the first element from the linked list. I don't know how to traverse the linked list in the while loop.
Node class
public class iNode{
public int item;
public iNode next;
public iNode(int i, iNode n){
item = i;
next = n;
}
public iNode(int i){
item = i;
next = null;
}
Build the linked list method
public static iNode list(int n, int m){
iNode first;
iNode newNode;
iNode last;
first = null;
while ( )
{
newNode = new iNode(m, first.next);
if (m > 0){
newNode.item = m-1;
}
newNode.next = null;
if (first == null)
{
first = newNode;
last = newNode;
}
else
{
last.next = newNode;
last = newNode;
}
}
return first;
}
You are overcomplicating it. Just go from the end of the list and add nodes with the link to the previous one. In the end just return the last created node. Also, you are not adding random int from the range 0..m-1. Here it is:
public static void main(String[] args) {
iNode res = list(5, 10);
while(res != null){
System.out.println(res.item);
res = res.next;
}
}
public static iNode list(int n, int m) {
iNode previous;
iNode current;
int i = 0;
previous = null;
while (i < n) {
current = new iNode(ThreadLocalRandom.current().nextInt(0, m), previous);
previous = current;
i++;
}
return previous;
}
Output:
2
5
7
8
9
P.S. Please follow java code convention. Class names should start with capital letter - iNode
So I'm trying to implement a priority queue with a linked list. I think I have the basics together, but for some reason my test cases aren't working. When I run it, the size show up fine, but none of the node values are showing (only an arrow "->" pops up once). If anyone could help me figure out why it isn't working, or suggest a better way to set up test cases in java (I've never done that before) it would be appreciated!
Node class:
public class Node { //Node class structure
int data; //data contained in Node; for assignment purposes, data is an int
Node next; //pointer to Next Node
//Node Constructor
public Node(int data) {
this.data = data;
next = null;
}
//Set Methods
public void setData(int data) { //set Node value
this.data = data;
}
public void setNext(Node next) { //set next Node value
this.next = next;
}
//Get Methods
public int getData() { //get Node value
return this.data;
}
public Node getNext() { //get next Node value
return this.next;
}
//Display the Node Value
public void displayNode() {
System.out.println(data + "urgh"); //display value as a string
}
}
Linked List Class:
import Question1.Node;
//basic set-up of a FIFO singly linked list
public class SLList{
protected Node head; //head of SLList
protected Node tail; //tail of SLList
int n; //number of elements in SLList
//SLList constructor
public SLList() {
head = null;
n = 0;
}
//check if list is empty
public boolean isEmpty() {
return head == null;
}
//return the size of the list
public int size() {
return n;
}
//add a new node to the end of the list
public boolean insert(int x){
Node y = new Node(x);
if (head == null){ //if head is null, thus an empty list
head = y; //assign head as y
}
else{ //if there is already a tail node
tail.next = y; //assign the tail's pointer to the new node
}
tail = y; //assign tail to y
this.n++; //increment the queue's size
return true; //show action has taken place
}
//remove and return node from head of list
public Node remove(){
if (n == 0){ //if the list is of size 0, and thus empty
return null; //do nothing
}
else{ //if there are node(s) in the list
Node pointer = head; //assign pointer to the head
head = head.next; //reassign head as next node,
n--; //decrement list size
return pointer; //return the pointer
}
}
//display SLList as string
public void displayList() {
Node pointer = head;
while (pointer != null) {
pointer.displayNode();
pointer = pointer.next;
}
System.out.println(" ");
}
}
Priority Queue Class:
import Question1.Node;
import Question1.SLList;
public class PriorityQueue extends SLList {
private SLList list; //SLList variable
public PriorityQueue(){ //create the official SLList
list = new SLList();
}
//add a new node; new add method that ensures the first element is sorted to be the "priority"
public boolean add(int x){
Node y = new Node(x);
if (n == 0){ //if there are 0 elements, thus an empty list
head = y; //assign head as y
}
else if (y.data < head.data){ //if new node y is the smallest element, thus highest priority
y.next = head; //assign y's next to be current head of queue
head = y; //reassign head to be actual new head of queue (y)
}
else{ //if there is already a tail node
tail.next = y; //assign the tail's pointer to the new node
}
tail = y; //assign tail to y
n++; //increment the queue's size
return true; //show action has taken place
}
//delete the minimim value (highest priority value) from the queue and return its value
public Node deleteMin(){
return list.remove(); //the list is sorted such that the element being removed in indeed the min
}
//return the size of the queue
public int size() {
return n;
}
//display Queue as string
public void displayQueue() {
System.out.println("->");
list.displayList();
}
}
Test Cases (so far, the delete one wasn't working so it's commented out):
import Question1.PriorityQueue;
public class TestQ1 { //Test code
public static void main(String[] args){
PriorityQueue PQueue1 = new PriorityQueue();
PQueue1.add(3);
PQueue1.add(2);
PQueue1.add(8);
PQueue1.add(4);
System.out.println("Test add(x): ");
PQueue1.displayQueue();
System.out.println("Test size(): " + PQueue1.size());
PriorityQueue PQueue2 = new PriorityQueue();
//Node node1 = PQueue1.deleteMin();
System.out.println("Test deleteMin():");
PQueue2.displayQueue();
System.out.println("Test size(): " + PQueue2.size());
}
}
Change list.displayList() to displayList(), and you'll see the expected output.
Why? Because your queue is already a list (that is, an instance of SLList). When a class A extends another class B, an instance of A is also an instance of B. This is inheritance.
You've also included an instance variable private SLList list within your PriorityQueue implementation, which is an example of composition. Generally you'll only do one or the other of these two options, depending on your situation. In this case it seems you're trying to use inheritance, so there's no reason to create a separate list instance variable. You're adding the data directly to the queue (using the fact that, intrinsically, it is a list in its own right).
You should remove the list instance variable, and all the usages of it should refer to the parent class' methods or variables.
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?).