I am trying to create a function to delete an element from a linked list. However, I keep getting a NullPointerException. When I run the program, it states:
Exception in thread "main" java.lang.NullPointerException
at ElephantList.delete(ElephantList.java:30)
at BabyElephantWalk.main(BabyElephantWalk.java:15)
How can I delete an element from the linked list without having this exception thrown? Here is the code
BabyElephantWalk.java
public class BabyElephantWalk
{
public static void main (String[] args)
{
ElephantList walk = new ElephantList();
walk.add (new Elephant("Charlie"));
walk.add (new Elephant("Donna"));
walk.add (new Elephant("Chilli"));
walk.add (new Elephant("Piper"));
walk.add (new Elephant("Ziva"));
walk.delete ("Charlie");
System.out.println (walk);
}
}
ElephantList.java
public class ElephantList
{
private ElephantNode head;
private ElephantNode list;
public ElephantList()
{
list = null;
}//end ElephantList constructor
public void add(Elephant cat)
{
ElephantNode node = new ElephantNode(cat);
ElephantNode current;
if (list == null)
list = node;
else
{
current = list;
while (current.next != null)
current = current.next;
current.next = node;
}
}//end add
public void delete(Object x)
{
{
if (head.data == x)
{
head = head.next;
}
else
{
ElephantNode temp = head;
while (temp.next != null)
{
if (temp.next.data.equals(x))
{
temp.next = temp.next.next;
break;
}
else
{
temp = temp.next;
}
}
}
}
}
public String toString ()
{
String result = "";
ElephantNode current = list;
while (current != null)
{
result += current.elephant + "\n";
current = current.next;
}
return result;
}//end toString
private class ElephantNode
{
public Elephant elephant;
public ElephantNode next;
public Object data;
public ElephantNode(Elephant cat)
{
elephant = cat;
next = null;
data = null;
}//end ElephantNode constructor
}//ElephantNode
}//end ElephantList
Elephant.java
public class Elephant
{
private String title;
public Elephant(String newname)
{
title = newname;
}//end Elephant constructor
public String toString ()
{
return title;
}
}
In add method you work with 'list', in delete method you work with 'head'. Retain the only property and work with it:
public void delete(Object x)
{
if (list.data.equals(x)) // <<= 'head' replaced with 'list'; == replaced with .equals
{
list = list.next; // <<= 'head' replaced with 'list'
}
else
{
ElephantNode temp = list; // <<= 'head' replaced with 'list'
while (temp.next != null)
{
if (temp.next.data.equals(x))
{
temp.next = temp.next.next;
break;
}
else
{
temp = temp.next;
}
}
}
}
Related
I think I'm having trouble with my Queue class because I know using a Queue uses the FIFO method, but want to make sure that when I add an element that it is added at the end of the Queue. In my main program I have added numbers 1-4, but when I want to print my entire Queue using the toString method in my Queue class it will only print out the first element which is 1. I would appreciate some help!
Thank you!
public class QuestionFive
{
public static void main(String[] args)
{
// creating a queue
Queue q = new Queue();
// adding numbers 1,2,3 and 4
q.insert(1);
q.insert(2);
q.insert(3);
q.insert(4);
System.out.println(q);
}
}
class Queue
{
//Private Data Member
private Link _head;
//Constructor: A constructor to create an empty Queue,
public Queue()
{
_head = null;
}
//Insert Method: A method to insert a given Object into the Queue.
//Note: We will inserton
public void insert(Object item)
{
Link add = new Link();
add.data = item;
add.next = null;
if(_head == null)
{
_head = add;
}
else
{
for(Link curr = _head; curr.next != null; curr = curr.next)
{
curr.next = add;
}
}
}
//Delete Method: A method to delete an Object from the Queue
public Object delete()
{
if ( _head == null ) return null;
Link prev = null;
Link curr = _head;
while (curr.next != null )
{
prev = curr;
curr = curr.next;
}
if ( prev != null )
{
prev.next = null;
}
else
{
_head = null;
}
return curr.data;
}
// IsEmpty Method: A method to test for an empty Queue
public boolean isEmpty()
{
// queue is empty if front is null
return (_head == null);
}
//toString Method:
public String toString()
{
String s = "";
for (Link curr = _head; curr != null; curr = curr.next)
{
s = s + " " + curr.data;
}
return s;
}
}
//Link Class
class Link
{
public Object data;
public Link next;
}
A much simpler approach is to introduce a tail as well as a head making your queue double-ended, no need to iterate through the entire queue every time you add an item.
class Queue {
private Link head;
private Link tail;
public void insert(Object item) {
Link add = new Link();
add.data = item;
add.next = null;
if(head == null)
{
head = add;
tail = add;
}
else {
tail.next = add;
tail = add;
}
}
}
The method should really be called add since it is appending to the end not inserting.
The logic in your insert() method needs attention. I have modified the else part of the method as follows and it worked:
else
{
for(Link curr = _head; ; curr = curr.next)
{
if(curr.next == null){
curr.next = add;
break;
}
}
}
Here is the full working class:
public class QuestionFive
{
public static void main(String[] args)
{
// creating a queue
Queue q = new Queue();
// adding numbers 1,2,3 and 4
q.insert(1);
q.insert(2);
q.insert(3);
q.insert(4);
System.out.println(q);
}
}
class Queue
{
//Private Data Member
private Link _head;
//Constructor: A constructor to create an empty Queue,
public Queue()
{
_head = null;
}
//Insert Method: A method to insert a given Object into the Queue.
//Note: We will inserton
public void insert(Object item)
{
Link add = new Link();
add.data = item;
add.next = null;
if(_head == null)
{
_head = add;
}
else
{
for(Link curr = _head; ; curr = curr.next)
{
if(curr.next == null){
curr.next = add;
break;
}
}
}
}
//Delete Method: A method to delete an Object from the Queue
public Object delete()
{
if ( _head == null ) return null;
Link prev = null;
Link curr = _head;
while (curr.next != null )
{
prev = curr;
curr = curr.next;
}
if ( prev != null )
{
prev.next = null;
}
else
{
_head = null;
}
return curr.data;
}
// IsEmpty Method: A method to test for an empty Queue
public boolean isEmpty()
{
// queue is empty if front is null
return (_head == null);
}
//toString Method:
public String toString()
{
String s = "";
for (Link curr = _head; curr != null; curr = curr.next)
{
s = s + " " + curr.data;
}
return s;
}
}
//Link Class
class Link
{
public Object data;
public Link next;
}
Fixed in your Code(instead toString method printList):
public class QuestionFive
{
public static void main(String[] args)
{
// creating a queue
Queue q = new Queue();
// adding numbers 1,2,3 and 4
q.insert(1);
q.insert(2);
q.insert(3);
q.insert(4);
q.printList();
System.out.println(q);
}
}
class Queue
{
//Private Data Member
private Link _head;
//Constructor: A constructor to create an empty Queue,
public Queue()
{
_head = null;
}
//Insert Method: A method to insert a given Object into the Queue.
//Note: We will inserton
public void insert(Object item)
{
Link add = new Link();
add.data = item;
add.next = _head;
_head = add;
}
//Prints list data
public void printList() {
Link currentLink = _head;
System.out.print("List: ");
while(currentLink != null) {
currentLink.printLink();
currentLink = currentLink.next;
}
System.out.println("");
}
//Delete Method: A method to delete an Object from the Queue
public Object delete()
{
if ( _head == null ) return null;
Link prev = null;
Link curr = _head;
while (curr.next != null )
{
prev = curr;
curr = curr.next;
}
if ( prev != null )
{
prev.next = null;
}
else
{
_head = null;
}
return curr.data;
}
// IsEmpty Method: A method to test for an empty Queue
public boolean isEmpty()
{
// queue is empty if front is null
return (_head == null);
}
}
//Link Class
class Link
{
public Object data;
public Link next;
//Print Link data
public void printLink() {
System.out.print("{" + data + "}");
}
}
created java linked list to add some data. want to compare first data inside that linked list. when i use peek() it not working. any other way to get front element and compare or how to write peek() method
LinkList class :
package list;
public class LinkList {
private class Node<T> {
public final T data;
public Node next;
public Node(T data) {
this.data = data;
}
public void displayNode() {
System.out.print(data + " ");
}
}
public static Node first = null;
private Node last = null;
public boolean isEmpty() {
return (first == null);
}
public <T> void addLast(T data) {
Node n = new Node(data);
if (isEmpty()) {
n.next = first;
first = n;
last = n;
} else {
last.next = n;
last = n;
last.next = null;
}
}
public void removeFirst() {
Node temp = first;
if (first.next == null) {
last = null;
}
first = first.next;
}
public void displayList() {
Node current = first;
while (current != null) {
current.displayNode();
current = current.next;
}
}
}
LinkListQueue:
package list;
public class LinkListQueue {
LinkList newLinkList = new LinkList();
public <T> void enqueue(T data) {
newLinkList.addLast(data);
}
public void dequeue() {
if (!newLinkList.isEmpty()) {
newLinkList.removeFirst();
}
}
public String displayQueue() {
newLinkList.displayList();
System.out.println();
return "";
}
public boolean isEmpty() {
return newLinkList.isEmpty();
}
}
LinkListQueueMain :
package list;
public class LinkListqueueMain {
public String getValue=null;
public static String displayQ = null;
static LinkListQueue queueImpl = new LinkListQueue();
static LinkList linkList = new LinkList();
public static void main(String[] args) {
runData();
}
public static void runData() {
queueImpl.enqueue("80%");
queueImpl.enqueue("70%");
queueImpl.enqueue("60%");
queueImpl.enqueue("85%");
queueImpl.enqueue("45%");
queueImpl.enqueue("55%");
for (int i = 0; i < 5; i++) {
System.out.println(linkList.toString());
}
}
}
This is my code. Any idea how to do that?
First you need to paramtrize the LinkList, not necessarily the node, as the LinkList is the public API to the outer world.
public class LinkList<T> {
private static class Node {
Then you could return the removed value. (removeFirst can throw a NullPointerException on an empty list.)
public T removeFirst() {
T removed = first.data;
if (first.next == null) {
last = null;
}
first = first.next;
return removed;
}
public T peekFirst() {
return first.data;
}
I'm wondering if this has something to do with how I specified my Singly Linked List class, but the problem is eluding me.
Here is the Singly Linked List class:
class SLList {
private static Node head;
private static long size;
public SLList() {
head = new Node(null, null);
setSize(0);
}
static class Node {
private Object data;
private Node next;
public Node(Object newData, Node n) {
data = newData;
next = n;
}
public Node getNext() {
return next;
}
public void setElement(Object element) {
data = element;
}
public void setNext(Node newNext) {
next = newNext;
}
public String toString() {
String result = data + " ";
return result;
}
public Object getObject() {
return data;
}
}
public Node getHead() {
return head;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public void addLast(Object object) {
Node temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = new Node(object, null);
size++;
}
public void remove(Object object) {
Node pre = head;
Node temp = head.next;
while(temp.next != null) {
pre = temp;
temp = temp.next;
if(temp.data.equals(object)) {
pre = temp.next;
temp = temp.next.next;
size--;
}
}
}
public void printElements() {
Node temp = head;
if(temp.next == null) {
System.out.println("List is empty.");
}
else {
while(temp.next != null) {
temp = temp.next;
System.out.println(temp.data);
}
}
}
}
This is the Set class with a method to add new values to the lists, barring duplicates already in the list:
public class Set {
SLinkedList aList;
SLinkedList bList;
SLinkedList cList;
SLinkedList dList;
public Set() {
aList = new SLinkedList();
bList = new SLinkedList();
cList = new SLinkedList();
dList = new SLinkedList();
}
public SLinkedList getList(char x) {
if(x == 'a') {
return aList;
}
else if(x == 'b') {
return bList;
}
else if(x == 'c') {
return cList;
}
else {
return dList;
}
}
public boolean addElement(SLinkedList list, Object newData) {
SLinkedList.Node newNode = new SLinkedList.Node(newData, null);
SLinkedList.Node traverseNode = list.getHead();
while(traverseNode.getNext() != null) {
traverseNode = traverseNode.getNext();
if(traverseNode.getObject().equals(newNode.getObject())) {
System.out.println("This data is already in the list.");
return false;
}
}
list.addLast(newData);
System.out.println("Node added!");
return true;
}
public void fillList() {
aList.addLast("dog");
aList.addLast(4);
bList.addLast("test");
System.out.println("aList: ");
aList.printElements();
System.out.println("bList: ");
bList.printElements();
}
}
This is the output when I try to use fillList() to add values to the first Singly Linked List, aList
aList:
dog 4 test
bList:
dog 4 test
As you can see, adding values to aList adds the same values to bList. Any help would be greatly appreciated!
This:
private static Node head;
means you have one head for all your instances of SLLIst. So all SLList instance share the same head.
This should be a member of your class, and as such you'll have an instance of head per instance of SLLIst.
e.g.
private Node head;
The same applies to your size field. I don't think you'll need any static members.
I have LinkedList with test program. As you can see in that program I add some Students to the list. I can delete them. If I choose s1,s2,s3 oraz s4 to delete everything runs well, and my list is printed properly and information about number of elements is proper. But if I delete last element (in this situation - s5) info about number of elements is still correct, but this element is still printed. Why is that so? Where is my mistake?
public class Lista implements List {
private Element head = new Element(null); //wartownik
private int size;
public Lista(){
clear();
}
public void clear(){
head.setNext(null);
size=0;
}
public void add(Object value){
if (head.getNext()==null) head.setNext(new Element(value));
else {
Element last = head.getNext();
//wyszukiwanie ostatniego elementu
while(last.getNext() != null)
last=last.getNext();
// i ustawianie jego referencji next na nowowstawiany Element
last.setNext(new Element(value));}
++size;
}
public Object get(int index) throws IndexOutOfBoundsException{
if(index<0 || index>size) throw new IndexOutOfBoundsException();
Element particular = head.getNext();
for(int i=0; i <= index; i++)
particular = particular.getNext();
return particular.getValue();
}
public boolean delete(Object o){
if(head.getNext() == null) return false;
if(head.getNext().getValue().equals(o)){
head.setNext(head.getNext().getNext());
size--;
return true;
}
Element delete = head.getNext();
while(delete != null && delete.getNext() != null){
if(delete.getNext().getValue().equals(o)){
delete.setNext(delete.getNext().getNext());
size--;
return true;
}
delete = delete.getNext();
}
return false;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
public IteratorListowy iterator() {
return new IteratorListowy();
}
public void wyswietlListe() {
IteratorListowy iterator = iterator();
for (iterator.first(); !iterator.isDone(); iterator.next())
{
System.out.println(iterator.current());
}
System.out.println();
}
public void infoOStanie() {
if (isEmpty()) {
System.out.println("Lista pusta.");
}
else
{
System.out.println("Lista zawiera " + size() + " elementow.");
}
}
private static final class Element{
private Object value;
private Element next; //Referencja do kolejnego obiektu
public Element(Object value){
setValue(value);
}
public void setValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
//ustawia referencję this.next na obiekt next podany w atgumencie
public void setNext(Element next) {
if (next != null)
this.next = next;
}
public Element getNext(){
return next;
}
}
private class IteratorListowy implements Iterator{
private Element current;
public IteratorListowy() {
current = head;
}
public void next() {
current = current.next;
}
public boolean isDone() {
return current == null;
}
public Object current() {
return current.value;
}
public void first() {
current = head.getNext();
}
}
}
test
public class Program {
public static void main(String[] args) {
Lista lista = new Lista();
Iterator iterator = lista.iterator();
Student s1 = new Student("Kowalski", 3523);
Student s2 = new Student("Polański", 45612);
Student s3 = new Student("Karzeł", 8795);
Student s4 = new Student("Pałka", 3218);
Student s5 = new Student("Konowałek", 8432);
Student s6 = new Student("Kłopotek", 6743);
Student s7 = new Student("Ciołek", 14124);
lista.add(s1);
lista.add(s2);
lista.add(s3);
lista.add(s4);
lista.add(s5);
lista.wyswietlListe();
lista.delete(s5);
lista.wyswietlListe();
lista.infoOStanie();
lista.clear();
lista.infoOStanie();
}
}
The problem is that your setNext(Element next) method does not set anything if next == null. And that is the case for the last element of your list.
So when you call delete.setNext(delete.getNext().getNext());, nothing is actually set because delete.getNext().getNext() is null!
Remove the if (next != null) condition in setNext and it will work.
Alright, so I hate to ask for help on a problem so vague, but I'm working on a project right now that doesn't seem to be getting any compile-time errors, yet won't do what's asked of it. To sum it up simply, this project is a linked list(unordered list, to be specific) that functions as a text editor. It takes in a file as a command line argument, then stores every separate line of the document as a node in the list. Whether it's doing that for sure or not I don't know, but after that the program takes in specific commands(keyboard input) and edits or lists the text of the file as requested.
The problem is, I can't even tell if the file is being stored in the list or not because every time I give the command L for list, the program just 'skips' it and continues on as if nothing was asked of it. It may be that the file isn't being stored for whatever reason, or there may be an issue with the toString method of the unorderedList class.
The code for all of my classes is as follows:
public class LinearNode<T> {
//Begin by declaring the basic node and its data
private LinearNode<T> next;
private T element;
public LinearNode() {
//The basic null constructor
next = null;
element = null;
}
public LinearNode(T elem) {
//The overloaded constructor to create a node
next = null;
element = elem;
}
public LinearNode<T> getNext() {
//Get the node reference
return next;
}
public void setNext(LinearNode<T> node) {
//Create or redirect a node reference
next = node;
}
public T getElement() {
//Get the actual data stored in the node
return element;
}
public void setElement(T elem) {
//Create or redirect the node's data
element = elem;
}
}
And for the lists
public abstract class LinkedList<T> implements ListADT<T>, UnorderedListADT<T> {
protected int count;
protected LinearNode<T> head, tail;
protected int modCount;
public LinkedList () {
count = 0;
head = null;
tail = null;
head = tail;
head.setNext(tail);
modCount = 0;
}
public T remove(T targetElement) throws EmptyCollectionException, ElementNotFoundException {
if(isEmpty())
throw new EmptyCollectionException("LinkedList");
boolean found = false;
LinearNode<T> previous = null;
LinearNode<T> current = head;
while(current!=null&&!found) {
if(targetElement.equals(current.getElement())) {
found = true;
}
else {
previous = current;
current = current.getNext();
}
}
if(!found)
throw new ElementNotFoundException("Linked List");
if(size()==1) {
head = tail = null;
}
else if(current.equals(head))
head = current.getNext();
else if(current.equals(tail)) {
tail = previous;
tail.setNext(null);
}
else {
previous.setNext(current.getNext());
}
count--;
modCount++;
return current.getElement();
}
}
import java.util.Iterator;
public class UnorderedList<T> extends LinkedList<T>{
public UnorderedList() {
super();
}
public void addToFront(T element) {
if(head==null) {
head = new LinearNode<T>(element);
if(tail==null) {
tail = head;
}
count++;
modCount++;
}
else {
LinearNode<T> current = head;
head.setElement(element);
head.setNext(current);
count++;
modCount++;
}
}
public void addToRear(T element) {
if(tail.getElement()==null) {
tail.setElement(element);
count++;
modCount++;
}
else {
LinearNode<T> current = tail;
tail = new LinearNode<T>(element);
current.setNext(tail);
count++;
modCount++;
}
}
public void addAfter(T element, T target) {
LinearNode<T> current = head;
LinearNode<T> node = new LinearNode<T>(element);
LinearNode<T> temp = null;
while(!(current.getElement()==target)) {
current = current.getNext();
}
if(!(current.getNext()==null)) {
temp = current.getNext();
//temp.setElement(current.getElement());
}
current.setNext(node);
node.setNext(temp);
count++;
modCount++;
}
public T removeLast() {
T last = tail.getElement();
tail = null;
LinearNode<T> current = head;
while(!(current.getNext()==null)) {
current = current.getNext();
}
current = tail;
count--;
modCount++;
return last;
}
public int size() {
return count;
}
public Iterator<T> iterator() {
Iterator<T> itr = this.iterator();
return itr;
}
public boolean isEmpty() {
boolean result = false;
if(head==null&&tail==null) {
result = true;
}
else
result = false;
return result;
}
public T first() {
return head.getElement();
}
public T last() {
return tail.getElement();
}
public boolean contains(T elem) {
boolean result = false;
for(T element : this) {
if(element==elem) {
result = true;
break;
}
}
return result;
}
public T removeFirst() {
LinearNode<T> current = head;
head = current.getNext();
count--;
modCount++;
return current.getElement();
}
public String toString() {
LinearNode<T> current = head;
String s = "";
for(int countA=0;countA<count;count++) {
s += (countA+1)+"> "+current.getElement()+"\n";
current = current.getNext();
}
return s;
}
}
and for the main editor
import java.util.Scanner;
import java.util.Iterator;
import java.io.*;
public class myEditor {
public static void saveToFile(String text, String filename) throws IOException{
PrintWriter out = new PrintWriter(new File(filename));
out.println(text);
out.close();
}
public static void main(String args[]) {
boolean quit = false;
try {
if(args.length!=1) {
throw new IllegalArgumentException();
}
String filename = args[0];
Scanner input = new Scanner(new File(filename));
//Add exception
UnorderedList<String> list = new UnorderedList<String>();
while(input.hasNextLine()) {
if(list.head==null) {
list.addToFront(input.nextLine());
}
list.addToRear(input.nextLine());
}
System.out.println(">");
do {
Scanner command = new Scanner(System.in);
String comm = command.next();
String[] comm1 = comm.split(" ");
if(comm1.length==1) {
if(comm1[0].equalsIgnoreCase("I")) {
System.out.println("Type a line of text >");
comm = command.next();
list.addToRear(comm);
}
else if(comm1[0].equalsIgnoreCase("L")) {
System.out.print(list.toString());
}
else if(comm1[0].equalsIgnoreCase("E")) {
saveToFile(list.toString(), filename);
quit = true;
break;
}
}
else {
if(comm1[0].equalsIgnoreCase("I")) {
int linNum = Integer.parseInt(comm1[1]);
Iterator<String> itr = list.iterator();
String current = "";
for(int count=0;count<linNum;count++) {
current = itr.next();
}
list.addAfter(comm, current);
}
else if(comm1[0].equalsIgnoreCase("D")) {
int linNum = Integer.parseInt(comm1[1]);
if(linNum<=list.count&&linNum>0) {
Iterator<String> itr = list.iterator();
String current = "";
for(int count=0;count<linNum;count++) {
current = itr.next();
}
list.remove(current);
}
}
}
}
while(!quit);
}
catch(IllegalArgumentException e) {
System.err.print(e.getMessage());
}
catch(FileNotFoundException e) {
System.err.print(e.getMessage());
}
catch(IOException e) {
System.err.print(e.getMessage());
}
}
}
There's a few other classes and some interfaces as well, but for the issue I'm experiencing, I don't think they're that relevant.
Does anyone see what might be happening here, or what I might have written wrong to cause my program to ignore the command?
Look at your LinkedList constructor
head = null;
tail = null;
head = tail;
head.setNext(tail);
head is null yet you call its setNext method, it should throw an NPE.