Java: NPE in Circular Linked List :( - java

import javax.swing.JOptionPane;
public class RotateArrayCircularLL
{
private Node head=null;
public void init()
{
int choice = 0;
while (choice != -1){
choice = Integer.parseInt(JOptionPane.showInputDialog("Enter -1 to stop loop, 1 to continue"));
if(choice == -1)
break;
inputNum();
}
printList();
}
public void inputNum()
{
Node n;
Node temp;
int k;
k = Integer.parseInt(JOptionPane.showInputDialog(null,"Enter a number:"));
n = new Node(k);
if (head == null) {
head = n;
} else {
temp = head;
while (temp.getNext() != null)
temp = temp.getNext();
temp.setNext(n);
}
}
public void printList()
{
Node temp = head;
int count = Integer.parseInt(JOptionPane.showInputDialog("Enter the value to shift to the right"));
for (int i = 1; i <= count; i++) // Rotates the head
temp = temp.getNext();
for (Node c = temp; c != null && c.getNext() != head; c= c.getNext()){ // Prints the new LL
System.out.print(c.getInfo());
}
}
}
I get an NPE during the second for loop. I understand that it is giving me a NPE because I reach the end of the list, but how can I stop it from doing this?

It appears from the behavior you are seeing that one of the nodes in your linked list is returning null instead of the next element of the list. At a guess, I'd suggest that the last node of your list is probably not pointing to the first node of your list. Hence as Hovercraft Full Of Eels suggests, you don't really have a properly circular linked list. If you can post the code showing how temp is populated, it may be possible to give a more concrete solution to your issue. Otherwise, you need to treat the case where getNext() returns null as a special case and ensure that you instead get the first element from the initial list.

Related

What's wrong with sorted set code? My output should match sample

Can anyone help on what's wrong with my code? Only the first input number shows up when I run it (it doesn't create a sorted list), the delete command isn't working, and the 'true' 'false' in exists command doesn't show up. My output should match the given sample I put at the end.
The areas I had to fill in to make the code work are the areas after the TODOTODOTODO symbols which would be 44-61, 75-83, 97-105. I'm not sure where I went wrong in those areas and why it is not working correctly to give the desired output?
import java.util.Scanner;
// Defines the a Sorted Set collection and implements a driver program in main
public class SortedSet {
// Define a basic element of a linked list
private class LinkedNode {
int x; // Value stored in the node
LinkedNode next; // Reference to the next node in the list
}
LinkedNode front = null; // Reference to the front of the singly linked list
// Adds the integer x to the collection.
// The resulting collection is sorted in increasing order and
// does not contain any duplicate values.
public void add(int x) {
// Initialize a new node to be added to the collection
LinkedNode newNode = new LinkedNode();
LinkedNode cur = front;
newNode.x = x;
// Check if list is empty
if (cur == null) {
front = newNode;
}
// If list is not empty, check if node should be placed in front
else if (front != null) {
if (newNode.x < front.x) {
newNode.next = front;
front = newNode;
}
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur;
LinkedNode prev = cur;
int middle = x;
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
prev = newNode;
}
}
}
}
// Deletes the integer x from the sorted set.
// The remaining collection remains sorted and without duplicates.
public void delete(int x){
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty
if (front == null) {
System.out.print("There is nothing to delete!");
} else { // Not empty
// Go through list, checking whether node is in the list, and delete if found
// <TODO><TODO><TODO>
LinkedNode prev = new LinkedNode();
while (cur.x != x && cur != null) {
prev = cur;
cur = cur.next;
}
if (cur != null)
prev.next = cur.next;
}
}
// Returns true if the integer x exists in the sorted set and false otherwise.
public void exists(int x) {
// Declare a new reference and initialize it to the front of the list
LinkedNode cur = front;
// Check if list is empty.
if (front == null) {
System.out.println("false");
}
// If not empty, check for the node.
// <TODO><TODO><TODO>
else {
while (cur != null) {
if (cur.x==x)
return;
cur=cur.next;
}
return;
}
}
// Returns a string representing the sorted set as a space separated list.
public String toString() {
String s = "";
LinkedNode cur = front;
while (cur!=null) {
s+= cur.x + " ";
cur = cur.next;
}
return s;
}
// Driver method
public static void main(String[] args) {
// Declare variables
SortedSet sortedSet = new SortedSet();
Scanner scan = new Scanner(System.in);
String[] tokens;
String command;
int num;
// Print header info
System.out.println("Programming Fundamentals\n"
+ "NAME: Andres Reyes\n"
+ "PROGRAMMING ASSIGNMENT 4\n");
// Enter command loop
while (true) {
// Prompt the user for a command
System.out.print("Enter command: ");
String input = scan.nextLine();
// Parse input
if (input.equals("q")) break; // user quits
tokens = input.split("\\s");
if (tokens.length < 2) continue; // invalid input
command = tokens[0];
num = Integer.parseInt(tokens[1]);
// Execute command
if (command.equals("add")){
sortedSet.add(num);
System.out.println(sortedSet);
} else if (command.equals("del")) {
sortedSet.delete(num);
System.out.println(sortedSet);
} else if (command.equals("exists")) {
sortedSet.exists(num);
} else {
System.out.print("Command does not exist");
}
}
System.out.println("\nGood bye!");
}
}
I made following changes in the add-function and they got it working for me:
// If not in front, check for the middle or the end, or duplicate.
else {
// <TODO><TODO><TODO>
LinkedNode temp = cur.next; // start at cur.next as your temp-variable
LinkedNode prev = cur;
int middle = 0; // set middle to 0
while (temp != null) {
if(temp.x > newNode.x) {
middle = 1;
newNode.next = temp;
prev.next = newNode;
}
prev = temp;
temp = temp.next;
}
if (middle == 0) {
// add node to the end
prev.next = newNode;
}
}
}
You have to start at cur.next as your temp-variable.
As far as I can see, you're not yet checking if there are any duplicate values in your list.
Edit: I didn't work on the exists-method, which is not giving you any output at the moment. The problem is simply that you're generating any output while you're checking if a value exists in your list. You could either write a System.out.print which prints "true" in case the value was found or "false" in case if wasn't. Or you change the return type of the exists-function to boolean, return a boolean according to the result and print the return value.
It might also help you to visualize a linked list to unterstand why you have to change the temp-variable to cur.next. I think https://www.tutorialspoint.com/data_structures_algorithms/linked_lists_algorithm.htm gives a good explaination of the insertion process.
I can give you some hints. The main problem I see with this code is that you really need a reference to the start of the LinkedList (the head) would be the only way to print the list and check for duplicates.
The following should be added to your class
LinkedList head = null; //start of the list
Then you have to update your toString() or you will never print the correct elements in your list no matter what you do. Try this:
public String toString(){
StringBuilder output = new StringBuilder();
LinkedNode current = head;
while(current != null){
output.append(current.x).append(" ");
current = current.next;
}
return output.toString();
}
You have to be really careful when you are appending to a String in a loop because Strings are immutable. Everytime you are appending to a list you are creating a new String. Instead, use StringBuilder.
//s+= cur.x + " ";
Your add method should handle the following cases:
Case 1: List is empty: ( don't forget to set ref to head)
Case 2: new element is great than front of list
Case 3: new element is less than current head
Case 4: new element is less than current and greater than head

Segregate even and odd nodes in a Linked List

Given, a linked-list, I'm trying to partition it into so that the even nodes come before the odd nodes. My approach is to create two different linked-list (even and odd) to store even numbers and odd numbers. However, I'm running into a problem when I want to add to the even or odd linked list (I commented the part that I think is giving me problem in my code below). Thanks!
public class SeperateOddEven {
static Node head;
static int count;
public static class Node {
int data;
Node next;
private Node(int data) {
this.data = data;
next = null;
count++;
}
}
public void seperate() {
Node even = null;
Node odd = null;
Node temp;
// go through each linked-list and place node in new list depending on whether they are even or odd
while(head != null) {
// if even, place in even linked-list
if(head.data % 2 == 0) {
temp = new Node(head.data);
even = temp; // Problem here
even = even.next; // and here
} else { // if head.data % 2 != 0
temp = new Node(head.data);
odd = temp;
odd = odd.next;
}
head = head.next;
}
toString(even);
//toString(odd);
}
public void toString(Node node) {
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
public static void main(String[] args) {
SeperateOddEven s = new SeperateOddEven();
head = new Node(8);
head.next = new Node(12);
head.next.next = new Node(10);
head.next.next.next = new Node(5);
head.next.next.next.next = new Node(4);
head.next.next.next.next.next = new Node(1);
head.next.next.next.next.next.next = new Node(6);
System.out.println("original list: ");
s.toString(head);
s.seperate();
}
}
I believe you identified exactly where the problem is. Let's go line by line:
temp = new Node(head.data);
The extra temp variable is unnecessary but fine.
even = temp;
A problem arises on the next line however. You assign even to temp (making temp unnecessary). If something was previously stored in even, it is now lost to the garbage collector because you now have no reference to it. even and temp are now both references to the same Node object.
What I think you might have wanted to do was to say even.next = temp. This would start to create a list, but with only a single reference you would have to use that reference to point to the head of the list. Each time you wanted to append to the list, you would need to loop through it until you found the end. If you instead tried to make this single reference point to the tail of the list, you would no longer have any way to get back to the head because your Nodes only have next references, and not prev references (a list with bidirectional references is called a doubly linked list).
even = even.next;
Because even (and temp) both point to the newly created Node object, the even.next property is null. So when this line executes, even now points to null. The work inside the loop has accomplished nothing because you immediately lose references to every Node you create.
Try something like this:
// Must keep track of head reference, because your Nodes can only go forward
Node evenHead = null;
Node evenTail = null;
Node oddHead = null;
Node oddTail = null;
while (head != null) {
if(head.data % 2 == 0) {
if (evenHead == null) {
// The even list is empty, set the head and tail
evenHead = new Node(head.data);
evenTail = evenHead;
} else {
// Append to the end of the even list
evenTail.next = new Node(head.data);
evenTail = evenTail.next;
}
} else {
// similar code for odd, consider creating a method to avoid repetition
}
}
You can also try this :
while (head != null) {
// if even, place in even linked-list
temp = new Node(head.data);
if (head.data % 2 == 0) {
if(even == null) {
even = temp;
} else{
Node insertionNode = even;
while(insertionNode.next != null)
insertionNode = insertionNode.next;
insertionNode.next = temp;
}
} else { // if head.data % 2 != 0
if(odd == null) {
odd = temp;
} else{
Node insertionNode = odd;
while(insertionNode.next != null)
insertionNode = insertionNode.next;
insertionNode.next = temp;
}
}
head = head.next;
}

Why is this linked list returning null? Java

Here is my code. It is supposed to put integers into a linked list until the user enters -1. It does that fine, but at the end it prints nothing. I don't see why the integers aren't being properly stored in the list.
public static Node read(Scanner scan)
{
int i = scan.nextInt();
Node n = new Node();
if (i == -1)
{
return n;
} else {
n.data = i;
n = n.next;
read(scan);
return n;
}
}
private static void printlist(Node head)
{
if(head == null)
{}
else
{
System.out.print(head.data + " ");
printlist(head.next);
...
}
}
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
Node head = read(scan);
printlist(head);
}
I added the main and print methods as requested. I also noticed that I am creating a new Node in my recursive read method.
How do I declare the node in the read method while also not making an extra node?
n = n.next
What is the value of n.next at this point? Why are you setting your new node n to this? My guess is that your problem lies here, and that you're actually trying to set a previous node's "next" value to the new node n. Does this sound right?
David pointed out the problem. You can resolve it in this way:
public static Node read(Scanner scan)
{
int i = scan.nextInt();
Node n = new Node();
if (i == -1)
{
return null;
} else {
n.data = i;
n.next=read(scan); //you probably wanted to do this
return n;
}
}

remove at index linked list

Hi im trying to remove a link in part of a linked list but i'm not sure how to remove the link. when i run it the links are still there. im using a junit to test the function if that matters .
Here is what i have so far.
public void removeAt(int k)
{
Node w = first;
int counter = 0;
if (k<0 || k >= size())
{
throw new IndexOutOfBoundsException("Error ");
}
else
{
while (w!= null)
{
counter++;
if (counter == k)
{
Node now = w.next;
w= now.next;
}
w=w.next;
}
}
assert check();
}
Thanks for the help
You need to change a node's .next field in order to remove a node, e.g. w.next = w.next.next removes the w.next node from the list (because nothing is pointing to it anymore); be sure to check for null pointers (if w.next is null then w.next.next will throw an exception). Also, add a break statement to the end of your if block since there's no need to traverse the rest of the list.
if (counter == k){
Node now = w.next;
w.next= now.next;
break;
}
test this.
You are updating a local variable. What you need to do is update the link prior to the current node:
if (k == 0)
{
first = first.next ;
// you also have to free the memory for first.
}
else
{
Node Last = first ;
w = first.next ;
counter = 1 ;
while (w!= null)
{
counter++; // Not sure your conventions, but I think this should be at the end
if (counter == k)
{
last.next = w.next ; /// happily skipping w :)
// remember you have to free w
break ; // no point in continuing to the end.
}
w=w.next;
}
}
}
You always need to keep track of the previous node. And also what if the node that's to be deleted is the first node? I guess you need to change the while block to look something like:
Node l = first;
while (w!= null)
{
if (counter == k)
{
if (w == first)
first = w.next;
else
l.next = w.next;
w.next = null;
break;
}
l=w;
w=w.next;
counter++;
}
Check the following code that remove the element from linked list,
public void delete(T element){
if(head != null){ // first check your header node is null or not
// create two references of your linked list
Node<T> tmp = head; // it will hold current value
Node<T> tmp1 = head.getNextRef(); // it will hold next value
while(true){ // iterate through whole linked list
if(head.getValue() == element){ // if you found element at first place
head = head.getNextRef(); // then point head to next node of it
break;
}
if(tmp1.getValue()==element){ // to remove node refer to next of tmp1
tmp.setNextRef(tmp1.getNextRef());
break;
}else{
tmp = tmp1;
tmp1 = tmp1.getNextRef();
if(tmp1==null)
break;
}
}
}
}

Cannot find symbol- method getNext()?

I am running BlueJ as my IDE. For some odd reason I get an error in this line of code:
import javax.swing.*;
public class RotateArrayCircularLL
{
private Node head=null;
// ==================================================================================
public void init()
{
int choice = 0;
while (choice != -1){
choice = Integer.parseInt(JOptionPane.showInputDialog("Enter -1 to stop loop, 1 to continue"));
if(choice == -1)
break;
inputNum();
}
printList();
}
public void inputNum()
{
Node n;
Node temp;
int k;
k = Integer.parseInt(JOptionPane.showInputDialog(null,"Enter a number:"));
n = new Node(k);
if (head == null) {
head = n;
} else {
temp = head;
while (temp.getNext() != null)
temp = temp.getNext();
temp.setNext(n);
}
}
public void printList()
{
Node temp = head;
Node d, e;
int count = Integer.parseInt(JOptionPane.showInputDialog("Enter the value to shift to the right"));
for (int i = 1; i <= count; i++) // Rotates the head
temp = temp.getNext();
for (e = head; e != null; e = e.getNext()){
if (e.getNext() != null)
System.out.print(e.getInfo() + "-");
if (e.getNext() == null)
System.out.print(e.getInfo());
}
for (Node c = temp; c != null && c.getNext() != head; c= c.getNext()){
System.out.print(c.getInfo() + "-");
}
for (d = head; d != null && d.getNext() != temp; d = d.getNext())
{
System.out.print(d.getInfo()+ "-");
}
System.out.println(d.getInfo());
}
}
The error is: Cannot find symbol- method getNext().
The code was working perfectly before but recently my compiler froze and was not responding so I ended the process via Task Manager. Since then it started to act up.
Can anyone explain why it is not working? I don't think that it is my issue, but rather the compilers.
The likely cases are either:
The method getNext() does not exist within the Node class, or
the calling signature of getNext() doesn't match with how it's defined (despite it being an accessor).
I can't say for certain which line of code is causing it, as you haven't provided code for the Node class. However, comb through the Node class and make certain that both getNext() exists, and you're calling it the way you're supposed to (passing valid arguments, and so forth).
Check the xml files. I had the same problem. I was calling a TextView that I previously rename and forgot to change the name.

Categories