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;
}
...
Related
Im trying to remove all people from the list who have the same course name in my custom LinkedList class. I have managed to get my programme to delete people individually based on number however can not figure out how to remove multiple at once. I have browsed online for any solutions and have tried multiple so far but none to any success I also attempted one myself but also no success any help or links to were I could learn mode would be greatly appreciated. Below is my Driver, LinkedList, and LinearNode class. I have also removed code I beleive is not relevant to this solution :).
Linked List Class
public class LinkedList<T> implements LinkedListADT<T> {
private int count; // the current number of elements in the list
private LinearNode<T> list; //pointer to the first element
private LinearNode<T> last; //pointer to the last element
//-----------------------------------------------------------------
// Creates an empty list.
//-----------------------------------------------------------------
public LinkedList()
{
this.count = 0;
this.last = null;
this.list = null;
}
public void add (T element)
{
LinearNode<T> node = new LinearNode<T> (element);
if (size() == 0) {
this.last = node; // This is the last and the
this.list = node; // first node
this.count++;
}//end if
else
{
last.setNext(node); // add node to the end of the list
last = node; // now make this the new last node.
this.count++;
} //end else
}
public T remove()
{
LinearNode<T> current = list;
LinearNode<T> temp = list;
T result = null;
if (current == null) {
System.out.println("There are no such employees in the list");
}//end if
else {
result = this.list.getElement();
temp = list;
this.list = this.list.getNext();
temp.setNext(null); //dereference the original first element
count--;
}//end else
return result;
}
public T remove(T element)
{
LinearNode<T> current = list;
LinearNode<T> previous = list;
LinearNode<T> temp;
T result = null;
if (current == null) {
System.out.println("There are no such employees in the list");
}//end if
else {
for (current = this.list; current != null && !current.getElement().equals(element); current = current.getNext())
{
previous = current;
}
if(current == null) {
System.out.println("No such employee on the list");
}
else if (current == list)
{
remove();
}
else if(current == last) {
previous.setNext(null);
this.last = previous.getNext();
count--;
}
else
{
previous.setNext(current.getNext());
count--;
}
}
return result;
}
**
My attempted Solution**
public T clear(T element) {
T result = null;
while (this.list != null && this.list.getElement() == element) {
this.list = this.list.getNext();
count--;
}
if (this.list == null) {
return result;
}
LinearNode<T> current = this.list;
while (current.getNext() != null) {
if (current.getNext().getElement() == element) {
current.setNext(current.getNext());
count--;
} else {
current = current.getNext();
}
}
return result;
}
}
LinearNode Class
public class LinearNode<T>
{
private LinearNode<T> next;
private T element;
//---------------------------------------------------------
// Creates an empty node.
//---------------------------------------------------------
public LinearNode()
{
this.next = null;
this.element = null;
}
//---------------------------------------------------------
// Creates a node storing the specified element.
//---------------------------------------------------------
public LinearNode (T elem)
{
this.next = null;
this.element = elem;
}
//---------------------------------------------------------
// Returns the node that follows this one.
//---------------------------------------------------------
public LinearNode<T> getNext()
{
return this.next;
}
//---------------------------------------------------------
// Sets the node that follows this one.
//---------------------------------------------------------
public void setNext (LinearNode<T> node)
{
this.next = node;
}
//---------------------------------------------------------
// Returns the element stored in this node.
//---------------------------------------------------------
public T getElement()
{
return this.element;
}
//---------------------------------------------------------
// Sets the element stored in this node.
//---------------------------------------------------------
public void setElement (T elem)
{
this.element = elem;
}
}
Driver Class
public class TrainingCourses {
LinkedList<employee>list;
int Size =10;
int numberofEmployees=0;
public TrainingCourses() {
list = new LinkedList<employee>();
inputEmployee();
displayEmployee();
deleteCourses();
displayEmployee();
}
public void inputEmployee() {
employee a;
a = null;
String number,name,courseName = null;
int years;
Scanner scan = new Scanner(System.in);
for (int count = 1; count<=numberofEmployees; count++){
System.out.println("Input employee number");
number = scan.nextLine();
System.out.println("Input employee name");
name = scan.nextLine();
System.out.println("Input years at organisation");
years = scan.nextInt(); scan.nextLine();
if(years >=5) {
System.out.println("Input course name");
courseName = scan.nextLine();
}else {
System.out.println("Can not join training course employee must be with organisation 5 or more years");
}
a = new employee(number,name,years,courseName);
list.add(a);
}
}
public void displayEmployee() {
System.out.println("\nDisplaying all employees....");
System.out.println(list.toString());
}
public void deleteCourses(){
{
Scanner scan = new Scanner(System.in);
employee b = null;
String number,name,courseName;
int years;
System.out.println("Enter employee number you wish to remove");
number = scan.nextLine();
System.out.println("Input employee name");
name = scan.nextLine();
System.out.println("Input years at organisation");
years = scan.nextInt(); scan.nextLine();
System.out.println("Input course name");
courseName = scan.nextLine();
b = new employee(number,name,years,courseName);
list.clear(b);
}
}
public static void main(String[]args) {
new TrainingCourses();
}
}
I don't understand exactly what you want, because of you wrote you want "to remove all people from the list who have the same course name", but your code never checks only property, your code checks equality everywhere.
This example clear function removes all elements equals to param and returns count of removed elements.
public long clear(T element) {
long result = 0L;
LinearNode<T> current = this.list;
LinearNode<T> previous = null;
while (current != null) {
if (current.getElement().equals(element)) {
if (previous != null) {
if (current.getNext() != null) {
previous.setNext(current.getNext());
} else {
this.last = previous;
}
} else if (current.getNext() != null) {
this.list = current.getNext();
} else {
this.list = this.last = null;
}
this.count--;
result++;
} else {
previous = current;
}
current = current.getNext();
}
return result;
}
And after all .equals(..) only true, if the compared Objects has an equals() method and checks its content equality, otherwise two Objects equals by == operator, if they are exactly the same (not by there's contents).
This is for a class assignment; I currently have a single-linked list and need to convert it into a doubly-linked list. Currently, the list is a collection of historical battles.
What in this program needs to be changed to turn this into a double-linked list? I feel like I'm really close, but stuck on a certain part (What needs to be changed in the 'add' part)
public static MyHistoryList HistoryList;
public static void main(String[] args) {
//Proof of concept
HistoryList = new MyHistoryList();
HistoryList.add("Battle of Vienna");
HistoryList.add("Spanish Armada");
HistoryList.add("Poltava");
HistoryList.add("Hastings");
HistoryList.add("Waterloo");
System.out.println("List to begin with: " + HistoryList);
HistoryList.insert("Siege of Constantinople", 0);
HistoryList.insert("Manzikert", 1);
System.out.println("List following the insertion of new elements: " + HistoryList);
HistoryList.remove(1);
HistoryList.remove(2);
HistoryList.remove(3);
System.out.println("List after deleting three things " + HistoryList);
}
}
class MyHistoryList {
//setting up a few variables that will be needed
private static int counter;
private Node head;
This is the private class for the node, including some getters and setters. I've already set up 'previous', which is supposed to be used in the implementation of the doubly-linked list according to what I've already googled, but I'm not sure how to move forward with the way MY single-list is set up.
private class Node {
Node next;
Node previous;
Object data;
public Node(Object dataValue) {
next = null;
previous = null;
data = dataValue;
}
public Node(Object dataValue, Node nextValue, Node previousValue) {
previous = previousValue;
next = nextValue;
data = dataValue;
}
public Object getData() {
return data;
}
public void setData(Object dataValue) {
data = dataValue;
}
public Node getprevious() {
return previous;
}
public void setprevious(Node previousValue) {
previous = previousValue;
}
public Node getNext() {
return next;
}
public void setNext(Node nextValue) {
next = nextValue;
}
}
This adds elements to the list. I think I need to change this part in order to make this into a doubly-linked list, but don't quite understand how?
public MyHistoryList() {
}
// puts element at end of list
public void add(Object data) {
// just getting the node ready
if (head == null) {
head = new Node(data);
}
Node Temp = new Node(data);
Node Current = head;
if (Current != null) {
while (Current.getNext() != null) {
Current = Current.getNext();
}
Current.setNext(Temp);
}
// keeping track of number of elements
incrementCounter();
}
private static int getCounter() {
return counter;
}
private static void incrementCounter() {
counter++;
}
private void decrementCounter() {
counter--;
}
This is just tostring, insertion, deletion, and a few other things. I don't believe anything here needs to be changed to make it a doubly linked list?
public void insert(Object data, int index) {
Node Temp = new Node(data);
Node Current = head;
if (Current != null) {
for (int i = 0; i < index && Current.getNext() != null; i++) {
Current = Current.getNext();
}
}
Temp.setNext(Current.getNext());
Current.setNext(Temp);
incrementCounter();
}
//sees the number of elements
public Object get(int index)
{
if (index < 0)
return null;
Node Current = null;
if (head != null) {
Current = head.getNext();
for (int i = 0; i < index; i++) {
if (Current.getNext() == null)
return null;
Current = Current.getNext();
}
return Current.getData();
}
return Current;
}
// removal
public boolean remove(int index) {
if (index < 1 || index > size())
return false;
Node Current = head;
if (head != null) {
for (int i = 0; i < index; i++) {
if (Current.getNext() == null)
return false;
Current = Current.getNext();
}
Current.setNext(Current.getNext().getNext());
decrementCounter();
return true;
}
return false;
}
public int size() {
return getCounter();
}
public String toString() {
String output = "";
if (head != null) {
Node Current = head.getNext();
while (Current != null) {
output += "[" + Current.getData().toString() + "]";
Current = Current.getNext();
}
}
return output;
}
}
public class LinkedList<T>
{
private Node head;
private int size;
public LinkedList()
{
}
public void addToHead(T value) // create new node, make new node point to head, and head point to new node
{
if (head == null)
{
head = new Node(value,null);
}
else
{
Node newNode = new Node(value,head);
head = newNode;
}
size++;
}
public boolean isEmpty()
{
return head == null;
}
public int size()
{
return size;
}
public void removeHead()
{
head = head.next;
size--;
}
public void addToTail(T value)
{
if (isEmpty())
{
System.out.println("You cannot addtoTail of a emptyList!");
}
else
{
System.out.println(value);
Node current = head;
System.out.println("we are pointing to head: "+current);
while (current.getNext() != null) // loop till the end of the list (find the last node)
{
System.out.println("we are now pointing to: "+current.getElement());
current = current.getNext();
}
System.out.println("We are at the last node:"+current); // its working
System.out.println("it should point to null:"+current.getNext()); // its working
current.setNext(new Node(value,null)); // make it point to our new node we want to insert
System.out.println(current.getNext()); // it is pointing to the new node.. yet the node is not actually inserted (local variable problem? )
size++;
}
}
public String toString()
{
String output = "";
if (!isEmpty())
{
Node current = head;
output = "";
while (current.getNext() != null)
{
output += current.toString()+ "->";
current = current.getNext();
}
}
return output;
}
protected class Node
{
private T element;
private Node next;
public Node()
{
this(null,null);
}
public Node(T value, Node n)
{
element = value;
next = n;
}
public T getElement()
{
return element;
}
public Node getNext()
{
return next;
}
public void setElement(T newElement)
{
element = newElement;
}
public void setNext(Node newNext)
{
next = newNext;
}
public String toString()
{
return ""+element;
}
}
}
So I have written this linkedlist class, and every method works except addtoTail. For example say I create a instance of my linkedlist class, and call addToHead(5), then addtoTail(6) and use my toString method to print out the linkedlist, it only contains 5->. I debugged the addToTail and everything seems to be pointing to the correct locations, yet for some reason it does not add the new node (6) to the list. Hopefully I explained that clearly. I am probably missing something really simple (I even drew it on paper to visualize it but do not see the problem).
Your addToTail function is probably fine. I think the culprit is your toString function. In particular, in this snippet:
while (current.getNext() != null)
{
output += current.toString()+ "->";
current = current.getNext();
}
Your condition terminates the loop before reaching the end. What you actually want is:
while(current != null) {
....
}
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.