public class Node {
public String name;
public Node next;
public Node(String name, Node next ){
this.name = name;
this.next = next;
}
public String getName(){
return name;
}
public void setName(String n){
name = n;
}
public Node getNext(){
return next;
}
public void setNext(Node n){
next = n;
}
public String toString() {
return "Name " + name;
}
}
public class LinkedList {
Node head = null;
int nodeCount= 0;
int counter = 0;
LinkedList(){
head = null;
}
public boolean isEmpty(){
return (head != null);
}
public void insertNode( String name ){
if( head == null){
head = new Node(name, null);
nodeCount++;
}else{
Node temp = new Node(name, null);
temp.next = head;
head = temp;
nodeCount++;
}
}
public Node reverseTest(Node L){
if(L == null || L.next ==null){
return L;
}
Node remainingNode = reverseTest(L.next);
Node cur = remainingNode;
while(cur.next !=null){
cur=cur.next;
}
L.next = null;
cur.next = L;
return remainingNode;
}
public boolean searchLinkedList(Node L, String S){
if (L == null)
return false;
else{
while(L !=null){
if(S.equals(L.name))
return true;
L= L.next;
}
}
return false;
}
public String toString(){
Node current = head;
String output = "";
while(current !=null){
output += "[" + current.getName() + "]";
current = current.getNext();
}
return output;
}
}
public class LinkedListDemo {
public static void main(String[] args){
LinkedList FriendList = new LinkedList();
FriendList.insertNode("First");
FriendList.insertNode("Second");
FriendList.insertNode("Third");
FriendList.insertNode("Fourth");
FriendList.searchLinkedList(FriendList.head, "Hello");
String NameList = FriendList.toString();
System.out.println(NameList);
System.out.println("Finish");
}
}
I have a singly linked list. I wanted to search for a value that is not present in the linkedlist and in the last loop when it reaches L = L.next I receive NPE. I don't see what is the mistake here. Please point to the right direction.
As I pointed out in the comments, there is no errors. Your IDE is just showing you its last reading of these properties.
When you get to the last loop here:
public boolean searchLinkedList(Node L, String S){
if (L == null)
return false;
else{
while(L !=null){
if(S.equals(L.name))
return true;
L= L.next;
}
}
return false;
}
L is indeed equal to null; which means that when your IDE tries to read its properties (name and next), it (and only IT, not your program's actual output) gets a reasonable NullPointerException.
The program otherwise runs fine.
Related
I am currently trying to understand Singly linked lists.
I don't understand some of the code in the SinglyLinkedList.java class. How can the Node class be called and then assigned like: private Node first;
I would have thought that you would have to do something like this
Node<T> help =new Node<>();
help = first;
If someone could explain, or provide me to a link that would help me, it would be much appreciated.
Thanks!
public class Node<T> {
public T elem;
public Node<T> next;
public Node(T elem) {
this.elem = elem;
next = null;
}
public Node(T elem, Node<T> next) {
this.elem = elem;
this.next = next;
}
#Override
public String toString() {
return "Node{" + "elem=" + elem + '}';
}
}
package list;
/**
*
* #author dcarr
*/
public class SinglyLinkedList<T> implements List<T> {
private Node<T> first;
private Node<T> last;
public SinglyLinkedList() {
first = null;
last = null;
}
#Override
public boolean isEmpty() {
return first == null;
}
#Override
public int size() {
if (isEmpty()){
return 0;
} else {
int size = 1;
Node<T> current = first;
while(current.next != null){
current = current.next;
size++;
}
return size;
}
}
#Override
public T first() {
return first.elem;
}
#Override
public void insert(T elem) {
// if there is nothing in the list
if (isEmpty()){
first = new Node<>(elem);
last = first;
// if the list has elements already
} else {
// the new element will be the next of what was the last element
last.next = new Node<>(elem);
last = last.next;
}
}
#Override
public void remove(T elem) {
if (!isEmpty()){
int index = 0;
Node<T> current = first;
while (current != null && current.elem != elem){
current= current.next;
index++;
}
remove(index);
}
}
#Override
public String toString() {
if (isEmpty()){
return "Empty List";
} else {
String str = first.elem.toString() + " ";
Node<T> current = first;
while(current.next != null){
current = current.next;
str += current.elem.toString() + " ";
}
return str;
}
}
#Override
public void insertAt(int index, T e) {
if (index == 0){
first = new Node<>(e, first);
if (last == null){
last = first;
}
return;
}
Node<T> pred = first;
for (int i = 0; i < index-1; i++) {
pred = pred.next;
}
pred.next = new Node<>(e, pred.next);
System.out.println(pred);
if (pred.next.next == null){
// what does this mean pred.next is?
last = pred.next;
}
}
#Override
public void remove(int index) {
if (index < 0 || index >= size()){
throw new IndexOutOfBoundsException();
} else if (isEmpty()){
return;
}
if (index == 0){
first = first.next;
if (first == null){
last = null;
}
return;
}
Node<T> pred = first;
for (int i = 1; i <= index-1; i++) {
pred = pred.next;
}
// remove pred.next
pred.next = pred.next.next;
if (pred.next == null){
last = pred;
}
}
}
The first field is automatically initialized to null:
private Node<T> first;
I assume there will be some method to add an element at the end like so:
public void add(T element) {
if (first == null) {
first = new Node<T>(element);
last = first;
}
else {
last.next = new Node<>(element);
last = last.next;
}
}
So when you create a new SinglyLinkedList:
SinglyLinkedList<String> sillyList = new SinglyLinkedList<>();
The first and last fields both hold a null reference.
Note that the first method will cause a NullPointerException at this point. A better implementation would be:
#Override
public Optional<T> first() {
if (first != null) {
return Optional.ofNullable(first.elem);
}
else {
return Optional.empty();
}
}
Now if you add an element:
sillyList.add("Adam");
The code executed in the add method is:
first = new Node<>(elem);
last = first;
So first points to a new Node instance with an elem field holding the value "Adam". And last points to that same Node instance.
Some of the methods in this class I would implement differently, for example:
#Override
public void remove(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException("Index cannot be negative");
}
else if (index == 0 && first != null) {
first = null;
last = null;
}
else {
Node<T> curr = new Node<>("dummy", first);
int c = 0;
while (curr.next != null) {
if (c == index) {
curr.next = curr.next.next;
if (curr.next == null) {
last = curr;
}
return;
}
curr = curr.next;
c++;
}
throw new IndexOutOfBoundsException(String.valueOf(c));
}
Also, some of the methods don't actually exist in the java.util.List interface, like insert, insertAt and first. So these methods must not have the #Override annotation.
I’m trying to build a program (Java) that would take string input from user puts it into a stack and then reverses the stack using push and pop. When the user inputs “end-line” the program will stop pushing to the stack and print the strings entered by user in reverse order ?
public class stackReversal{
private class Node{
private String item;
private Node next;
}
private Node first = null;
public boolean isEmpty(){
return(first == null);
}
public void push(String s){
Node node = new Node();
node.item = s;
node.next = first;
first = node;
}
public String pop(){
if(first == null)
throw new RuntimeException("Stack Empty!");
String result = first.item;
first = first.next;
return result;
}
public String popString(){
String result="";
Node current = first;
while(current != null){
result += current.item;
current = current.next;
}
return result;
}
public static void main(String [] args)
{
stackReversal s = new stackReversal();
s.push("Hello");
s.push("world");
s.push("!");
System.out.println("Strings:" + s);
}
}
Please find the below code. All I did is I override the toString method to print the nodes item.
Now I am inputting 1,2,3 it will print Strings:3 -> 2 -> 1 as output.. Hope this helps
public class stackReversal {
private class Node {
private String item;
private Node next;
}
private Node first = null;
public boolean isEmpty() {
return (first == null);
}
public void push(String s) {
Node node = new Node();
node.item = s;
node.next = first;
first = node;
}
public String pop() {
if (first == null)
throw new RuntimeException("Stack Empty!");
String result = first.item;
first = first.next;
return result;
}
public String popString() {
String result = "";
Node current = first;
while (current != null) {
result += current.item;
current = current.next;
}
return result;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*
* This method prints the nodes in reerse order
*/
#Override
public String toString() {
StringBuilder nodes = new StringBuilder();
Node node = first;
while (node != null) {
nodes.append(node.item).append(" -> ");
node = node.next;
}
if(isEmpty()) {
return "";
} else {
return nodes.toString().substring(0, nodes.toString().length() - 4);
}
}
public static void main(String[] args) {
stackReversal s = new stackReversal();
s.push("1");
s.push("2");
s.push("3");
System.out.println("Strings:" + s);
}
}
I'm working on a simple program to brush up on my linked list. I'm having a problem with my remove student method. All it is supposed to do is check if two students have the same student id and, if they do, remove that student since students are unique.
I'm having one main problem and that is if the student is at the end of the list it's giving me all sorts of problems. It also seems to be removing the wrong student in general..
The method is as follows
public boolean remove(StudentIF s) {
// TODO Auto-generated method stub
StudentLLNode current = head;
if(s == null){
return false;
}
if(s.getId() == (head.getStd().getId())){
//StudentLLNode top = head;
head = head.getNext();
size--;
return true;
}
else{
while(current != null){
if(s.getId() == (current.getStd().getId())){
current.setNext(current.getNext().getNext());
size--;
return true;
}
current = current.getNext();
}
}
return false;
}
Here is the stub from my interface
// remove StudentIF s *** using its equals method ***
public boolean remove(StudentIF s);
By doing:
current.setNext(current.getNext().getNext());
it seems like you are removing the next element instead of the current one.
When you hit the end of the list, getNext() returns null. And there is no next element after null, which is why you would get an exception if you reach the end of the list.
Other containers are better suited to avoid duplicate elements. For example, Sets or Maps.
Here is complete solution:
package linkedList;
import java.util.Iterator;
public class StudentList {
private int size = 0;
private StudentIF head;
public StudentList(StudentIF studentTobeAdded) {
head = studentTobeAdded;
size++;
}
public void addStudent(StudentIF studentTobeAdded) {
StudentIF curent = head;
while (curent.getNext() != null) {
curent = curent.getNext();
}
size++;
curent.setNext(studentTobeAdded);
}
public boolean removeStudent(StudentIF studentToBeRemoved)
{
int id = studentToBeRemoved.getId();
StudentIF current = head;
if (head.getId() == id) {
head = head.getNext();
size--;
return true;
}
while (current.getNext() != null) {
StudentIF next = current.getNext();
if (next.getId() == id) {
current.setNext(next.getNext());
size--;
return true;
}
current = next;
}
return false;
}
public int getSize() {
return size;
}
public StudentIF getHead() {
return head;
}
public void addListOfStudents(StudentIF... list) {
for (StudentIF studentIF : list) {
this.addStudent(studentIF);
}
}
#Override
public String toString() {
StudentIF current = head;
StringBuilder sb = new StringBuilder();
while (current != null) {
sb.append(current.getId() + " ");
current = current.getNext();
}
return sb.toString();
}
}
Student:
package linkedList;
public class StudentIF {
private int id;
private StudentIF next;
public StudentIF(int id) {
this.id = id;
next=null;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public StudentIF getNext() {
return next;
}
public void setNext(StudentIF next) {
this.next = next;
}
}
In your while loop, you don't handle the case where the student to be removed is at the end of the linked list and hence current.getNext().getNext() is an NPE.
Additionally your code is not removing the student where the Ids are equal, it's actually removing the student AFTER said student.
The following should fix your woes (though hasn't been compiled or tested).
...
else {
// head == current and if we get here, the if branch has not fired
StudentLLNode previous, next;
previous = current;
current = current.getNext();
while(current != null){
next = current.getNext();
if(s.getId() == (current.getStd().getId())){
previous.setNext(next); //doesn't matter if next is null or not
size--;
return true;
}
previous = current;
current = next;
}
...
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.