Implementing a linkedlist in java - java

I am learning data structures current and below is my implementation for linkedlist.I have kept it as simple as possible as my aim here is to understand the logic.
/*
* Singly linked list
*/
package linkedlisttest;
class Node {
int data;
Node next;
public Node(int data)
{
this.data = data;
}
}
class LinkedList {
Node head;
public void add(int data)
{
if (head == null)
{
head = new Node(data);
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(data);
}
public int getSize() {
int i = 0;
Node current = head;
while (current != null) {
i += 1;
current = current.next;
}
return i;
}
public void add(int data, int index)
{
if (head == null && index == 0)
{
head = new Node(data);
return;
} else if (head == null && index != 0) {
return; // invalid position
} else if ( index > getSize() ) {
return;
}
Node current = head;
//iterate through whole list
int pos = -1;
Node previous = null;
Node next = null;
Node newNode = new Node(data);
//find next and previous nodes with relation to position
while (current != null) {
if (pos == index - 1) {
previous = current;
} else if (pos == index + 1) {
next = current;
}
pos++;
current = current.next;
}
previous.next = newNode;
newNode.next = next;
}
public void print()
{
Node current = head;
while (current.next != null) {
System.out.print(current.data + "->");
current = current.next;
}
System.out.print(current.data);
}
}
public class LinkedListTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
LinkedList lt = new LinkedList();
lt.add(3);
lt.add(5);
lt.add(6);
lt.add(4,1);
lt.print();
}
}
The bug happens for lt.add(4,1) and i suspect its an off by one error.
Expected output: 3->4->6
Actual output: 3->5->4
Thanks for the help guys...
Edit
Thanks to #StephenP and #rosemilk for their help.Indeed the code above has a logical bug as it replaces the value at index and not add it.
Here is the new optimized code
/*
* Singly linked list
*/
package linkedlisttest;
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
class LinkedList {
Node head;
int size;
/**
*
* #param data element to add to list
* Time Complexity : O(n)
*/
public void add(int data) {
if (head == null) {
head = new Node(data);
size += 1;
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(data);
size += 1;
}
/**
*
* #return size of list
* Time Complexity: O(1)
* This is because we use a class
* variable size to keep track of size of linked list
*/
public int getSize() {
return size;
}
/**
*
* #param data element to insert
* #param index position at which to insert the element (zero based)
* Time Complexity : O(n)
*/
public void add(int data, int index) {
if (index > getSize()) {
return; // invalid position
}
Node current = head; //iterate through whole list
int pos = 0;
Node newNode = new Node(data);
if (index == 0) // special case, since its a single reference change!
{
newNode.next = head;
head = newNode; // this node is now the head
size += 1;
return;
}
while (current.next != null) {
if (pos == index - 1) {
break;
}
pos++;
current = current.next;
}
// These are 2 reference changes, as compared to adding at index 0
newNode.next = current.next; // here we are changing a refernce
current.next = newNode; // changing a reference here as well
size += 1;
}
/**
* Prints the whole linked list
* Time Complexity : O(n)
*/
public void print() {
if(getSize() == 0) { //list is empty
return;
}
Node current = head;
while (current.next != null) {
System.out.print(current.data + "->");
current = current.next;
}
System.out.print(current.data + "\n");
}
}
public class LinkedListTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
LinkedList lt = new LinkedList();
lt.print();
lt.add(3);
lt.add(5);
lt.add(6);
lt.print();
lt.add(4, 1);
lt.print();
lt.add(4, 7);// 7 is an invalid index
lt.add(8, 3);
lt.print();
}
}

Your add (int , int ) function has a logical bug and can be made better. You don't need previous current and next references, and can cleverly manipulate the list using just the reference to current node, handling inseration at index 0 separately. I would write the add function as follows
public void add(int data, int index)
{
if ( index > getSize() ) {
return; // invalid position
}
Node current = head; //iterate through whole list
int pos = 0;
Node newNode = new Node(data);
if (index == 0) // special case, since its a single reference change!
{
newNode.next = head;
head = newNode; // this node is now the head
return;
}
while (current.next != null) {
if (pos == index - 1) {
break;
}
pos++;
current = current.next;
}
// These are 2 reference changes, as compared to adding at index 0
newNode.next = current.next; // here we are changing a refernce
current.next = newNode; // changing a reference here as well
}
Also, your print function gives a NullPointerException when you try to print an empty list. I would write the print function like this,
public void print()
{
Node current = head;
while (current != null) {
System.out.print(current.data + "->");
current = current.next;
}
System.out.println("null"); // this is just to say last node next points to null!
}
Hope this helps :)

Currently, if you print out pos in your loop, the indices are -1, 0, 1 (instead of 0, 1, 2), so it'll never "find" the correct next. Replace int pos = -1; with int pos = 0; and it'll work.
I do agree with #StephenP that the output should (arguably) be 3->4->5->6, but that's a design decision.

Related

Make a moving cursor using doubly linked list in java

I'm trying to write a code for a simple moving cursor in java. I have to use doubly linked list. Also I should implement doubyLinkedList class myself. In this program first we take an integer like n from user as number of lines. Then we take n lines of input. Each line contains only one character which can be < or > or - or one of the lower case English alphabet. For > or < we move the cursor to right or left. For - we delete the character in the place of cursor. For alphabets we add them to the doubly linked list. At last we print the result in one line without spaces. I have made the doubyLinkedList class and needed methods. I think it is working properly but the time complexity of the code must be O(n). I guess it's O(n^2) now.
import java.util.*;
public class DoublyLinkedList {
static Node head = null;
static int size = 0;
class Node {
String data;
Node prev;
Node next;
Node(String d) {
data = d;
}
}
static Node deleteNode(Node del) {
if (head == null || del == null)
return null;
if (head == del)
head = del.next;
if (del.next != null)
del.next.prev = del.prev;
if (del.prev != null)
del.prev.next = del.next;
del = null;
size --;
return head;
}
public String GetNth(int index) {
Node current = head;
int count = 0;
while (current != null)
{ if (count == index)
return current.data;
count++;
current = current.next;
}
assert (false);
return null;
}
public static void deleteNodeAtGivenPos(int n) {
size--;
if (head == null || n <= 0)
return;
Node current = head;
int i;
for (i = 1; current != null && i < n; i++)
current = current.next;
if (current == null)
return;
deleteNode(current);
}
void insertFirst (String data){
size++;
Node newNode = new Node(data);
if (head == null) {
newNode.prev = null;
head = newNode;
return;
}
else
head.prev= newNode;
newNode.next=head;
head = newNode;
}
void append(String data) {
size++;
Node newNode = new Node(data);
Node last = head;
newNode.next = null;
if (head == null) {
newNode.prev = null;
head = newNode;
return;
}
while (last.next != null)
last = last.next;
last.next = newNode;
newNode.prev = last;
}
public void insertAtGivenPos(String s , int index){
Node newNode= new Node(s);
Node current= head;
if (index==0)
insertFirst(s);
else if(index==size)
append(s);
else{
for(int j = 0; j < index && current.next != null; j++){
current = current.next;
}
newNode.next = current;
current.prev.next = newNode;
newNode.prev = current.prev;
current.prev = newNode;
size++;
}
}
public void print(Node node) {
while (node != null) {
System.out.print(node.data + "");
node = node.next;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
String [] arr= new String[n];
for (int i=0; i< n; i++)
arr[i] = sc.nextLine();
DoublyLinkedList dll = new DoublyLinkedList();
int cursor= 0;
for (int i=0; i< n; i++){
if (arr[i].matches("[a-z]")){
dll.insertAtGivenPos(arr[i], cursor);
cursor++;
}
else if (arr[i].contains("-")&& dll.GetNth(cursor-1)!= null) {
dll.deleteNodeAtGivenPos(cursor);
cursor--;
}
else if (arr[i].contains("<") && dll.GetNth(cursor-1)!= null)
cursor--;
else if (arr[i].contains(">") && dll.GetNth(cursor+1)!= null)
cursor++;
}
dll.print(dll.head);
}
}
How can I improve my code to reduce time complexity?
Edit: Also I understood that my code is giving wrong answer for some cases. Could you help me debug it?
If you are not forced to follow implementation details, I suggest not to have a cursor. Instead, keep a variable currentNode which is the node that the cursor would point to. So for every command (or data) in the input loop, you have one O(1) operation as bellow and hence will get O(n) time complexity.
1 - for > : change the currentNode to currentNode.next
2 - for < do the reverse
3 - for - change the previous and the next node of currentNode to
point to each other (so the current is deleted)
4 - and finally for insertion : create a node and like 3, change the
the side nodes to point to it
You don't need inner for loop. process the input as soon as as you accept it.
for (int i=0; i< n; i++)
arr[i] = sc.nextLine();
DoublyLinkedList dll = new DoublyLinkedList();
int cursor= 0;
if (arr[i].matches("[a-z]")){
dll.insertAtGivenPos(arr[i], cursor);
cursor++;
}
else if (arr[i].contains("-")&& dll.GetNth(cursor-1)!= null) {
dll.deleteNodeAtGivenPos(cursor);
cursor--;
}
else if (arr[i].contains("<") && dll.GetNth(cursor-1)!= null)
cursor--;
else if (arr[i].contains(">") && dll.GetNth(cursor+1)!= null)
cursor++;
}

Doubly Linked List moving item to end java

I found this code for adding an item to the front of the linked list, but since I have a last node, it doesn't work quite right, so I changed it a tiny bit:
public void moveToFront(String node) {
DoubleNode previous = first;
temp = first;
while (temp != null) {
if (node.equals(temp.item)) {
//Found the item
previous.next = temp.next;
temp.next = first;
first = temp;
if (last.next != null) {
last = last.prev;
last.prev = previous;
}
return;
}
previous = temp;
temp = temp.next;
}
The if (last.next != null) is asking if the original last was moved, and checking if the new last has the right links. Now I think it works properly for my code.
I'd like to implement this code, but for adding an item to the end. However, last just isn't right now. When calling last.prev it only gets the one item behind it, but last.prev.prev to infinity is the same item.
My idea was instead of working from first like in moveToFront(), I work from last, and step through each node backwards, but obviously that doesn't work when last doesn't work anymore.
public void moveToEnd(String node) {
DoubleNode previous = last;
temp = last;
System.out.println("last = " + last.prev.item);
System.out.println("temp = " + temp.item);
while (!temp.item.equals(first.item)) {
if(node.equals(temp.item)){
System.out.println("previous.prev = " + previous.prev.item);
}
previous = temp;
temp = temp.prev;
System.out.println("temp.prev = " + temp.prev.prev.prev.prev.prev.prev.prev.prev.prev.prev.prev.item);
}
Here's how I implement my linked list:
public class LinkedListDeque {
public DoubleNode first = new DoubleNode(null);
public DoubleNode last = new DoubleNode(null);
public DoubleNode temp;
public int N;
LinkedListDeque() {
first.next = last;
last.prev = first;
}
private class DoubleNode {
String item;
int counter = 0;
DoubleNode next;
DoubleNode prev;
DoubleNode(String i) {
this.item = i;
}
}
I found this example of a complete doubly linked list. It does not have an add to front method, but it is adding to the back of the linked list each time. Hopefully, it will help and give you a better idea of how this data structure is supposed to work and function. I would definitely test it first as it states in the readme for this GitHub that none of the code has been tested. Sorce
/*******************************************************
* DoublyLinkedList.java
* Created by Stephen Hall on 9/22/17.
* Copyright (c) 2017 Stephen Hall. All rights reserved.
* A Linked List implementation in Java
********************************************************/
package Lists.Doubly_Linked_List;
/**
* Doubly linked list class
* #param <T> Generic type
*/
public class DoublyLinkedList<T extends Comparable<T>> {
/**
* Node class for singly linked list
*/
public class Node{
/**
* private Members
*/
private T data;
private Node next;
private Node previous;
/**
* Node Class Constructor
* #param data Data to be held in the Node
*/
public Node(T data){
this.data = data;
next = previous = null;
}
}
/**
* Private Members
*/
private Node head;
private Node tail;
private int count;
/**
* Linked List Constructor
*/
public DoublyLinkedList(){
head = tail = null;
count = 0;
}
/**
* Adds a new node into the list with the given data
* #param data Data to add into the list
* #return Node added into the list
*/
public Node add(T data){
// No data to insert into list
if (data != null) {
Node node = new Node(data);
// The Linked list is empty
if (head == null) {
head = node;
tail = head;
count++;
return node;
}
// Add to the end of the list
tail.next = node;
node.previous = tail;
tail = node;
count++;
return node;
}
return null;
}
/**
* Removes the first node in the list matching the data
* #param data Data to remove from the list
* #return Node removed from the list
*/
public Node remove(T data){
// List is empty or no data to remove
if (head == null || data == null)
return null;
Node tmp = head;
// The data to remove what found in the first Node in the list
if(equalTo(tmp.data, data)) {
head = head.next;
count--;
return tmp;
}
// Try to find the node in the list
while (tmp.next != null) {
// Node was found, Remove it from the list
if (equalTo(tmp.next.data, data)) {
if(tmp.next == tail){
tail = tmp;
tmp = tmp.next;
tail.next = null;
count--;
return tmp;
}
else {
Node node = tmp.next;
tmp.next = tmp.next.next;
tmp.next.next.previous = tmp;
node.next = node.previous = null;
count--;
return node;
}
}
tmp = tmp.next;
}
// The data was not found in the list
return null;
}
/**
* Gets the first node that has the given data
* #param data Data to find in the list
* #return Node First node with matching data or null if no node was found
*/
public Node find(T data){
// No list or data to find
if (head == null || data == null)
return null;
Node tmp = head;
// Try to find the data in the list
while(tmp != null) {
// Data was found
if (equalTo(tmp.data, data))
return tmp;
tmp = tmp.next;
}
// Data was not found in the list
return null;
}
/**
* Gets the node at the given index
* #param index Index of the Node to get
* #return Node at passed in index
*/
public Node indexAt(int index){
//Index was negative or larger then the amount of Nodes in the list
if (index < 0 || index > size())
return null;
Node tmp = head;
// Move to index
for (int i = 0; i < index; i++)
tmp = tmp.next;
// return the node at the index position
return tmp;
}
/**
* Gets the current count of the array
* #return Number of items in the array
*/
public int size(){
return count;
}
/**
* Determines if a is equal to b
* #param a: generic type to test
* #param b: generic type to test
* #return boolean: true|false
*/
private boolean equalTo(T a, T b) {
return a.compareTo(b) == 0;
}
}
There is a problem with your moveToFront() method. It does not work for if node == first. If the node that needs to be moved is the first node, you end up setting first.next = first which is incorrect. The below code should work
public void moveToFront(DoubleNode node) {
DoubleNode previous = first;
temp = first;
while (temp != null && node != first) {
if (node.equals(temp.item)) {
//Found the item
previous.next = temp.next;
temp.next = first;
first = temp;
if (last.next != null) {
last = last.prev;
last.prev = previous;
}
return;
}
previous = temp;
temp = temp.next;
}
Now coming to moveToLast() the following code should work
public void moveToLast(DoubleNode node) {
DoubleNode temp = first;
DoubleNode prev = new DoubleNode(null); //dummy sentinel node
while (temp != null && node != last) {
if (temp == node) {
if (temp == first) first = temp.next;
prev.next = temp.next;
if (temp.next != null) temp.next.prev = prev;
last.next = temp;
temp.prev = last;
last = temp;
last.next = null;
break;
}
prev = temp;
temp = temp.next;
}
}

Apending to Linked List in Java

The code compiles and runs but addToEnd method doesn't work, it seems right to me but I'm not sure where the mistake is, could someone guide me as to what or where the code needs to be fixed
Here is the code for my other class
public class LinkedList {
private Node head;
/**
* constructor
* pre: none
* post: A linked list with a null item has been created.
*/
public LinkedList() {
head = null;
}
/**
* Activity: finds size of the Linked List.
* Pre-Condition: none
* Post-Condition: The size of the list is returned
*/
public int size() {
int counter = 0;
Node current = head;
while(current != null) {
counter++;
current = current.getNext();
}
return counter;
}
/**
* Adds a node to the end of the linked list.
* pre: String parameter
* post: The linked list has a new node at the end.
*/
public void addAtEnd(String s) {
Node current = head;
Node newNode = new Node(s);
if(head == null) {
head = newNode;
head.setNext(null);
}
else {
while(current.getNext() == null) {
current.setNext(newNode);
current = newNode;
}
}
}
private class Node {
private String data;
private Node next;
/**
* constructor
* pre: none
* post: A node has been created.
*/
public Node(String newData) {
data = newData;
next = null;
}
/**
* The node pointed to by next is returned
* pre: none
* post: A node has been returned.
*/
public Node getNext() {
return(next);
}
/**
* The node pointed to by next is changed to newNode
* pre: none
* post: next points to newNode.
*/
public void setNext(Node newNode) {
next = newNode;
}
/**
* The node pointed to by next is returned
* pre: none
* post: A node has been returned.
*/
public String getData() {
return(data);
}
}
}
Here is my code for the main class, Blume and Dahl never get added to the list:
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.addAtFront("Sachar");
list.addAtFront("Osborne");
list.addAtFront("Suess");
System.out.println("List has " + list.size() + " items.");
System.out.println(list);
list.addAtEnd("Blume");
list.addAtEnd("Dahl");
System.out.println(list);
}
}
public void addAtEnd(String s) {
Node current = head;
Node newNode = new Node(s);
if(head == null) {
head = newNode;
head.setNext(null);
}
else {// problem is here. You need to find the node that has getNext()==null,
//so you need to loop all nodes where get next != null
while(current.getNext() == null) {
current.setNext(newNode);
current = newNode;
}
}
Change to this
else{
//iterate to the last node
while(current.getNext() != null) {
current = current.getNext();
}
//Append the new node to the end
current.setNext(newNode);
}
while (current.getNext() == null) {
current.setNext(newNode);
current = newNode;
}
This is just incorrect; because you're not keeping track of the tail of the list, you need to iterate over the entire list and then add newNode onto the end (which I believe you understand already). To do this, just keep setting current to current.getNext() until current.getNext() is null, and then call current.setNext(newNode);
Node next;
while ((next = current.getNext()) != null) {
current = next;
}
current.setNext(newNode);
public void addAtEnd(String s) {
Node current = head;
Node newNode = new Node(s);
if(current == null) {
head = newNode;
} else {
while(current.getNext() != null) {
current = current.getNext();
}
current.setNext(newNode);
}
}

Delete all occurrences of an element in a linkedlist

On my quest to understand data structures , i started implementing them in java.The time complexity for deleteAll would be O(n + n^2).How can i improve the deleteAll method ?
/*
* Singly linked list
*/
package linkedlisttest;
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
class LinkedList {
Node head;
int size;
/**
*
* #param data element to add to list
* Time Complexity : O(n)
*/
public void add(int data) {
if (head == null) {
head = new Node(data);
size += 1;
return;
}
Node current = head;
while (current.next != null) {
current = current.next;
}
current.next = new Node(data);
size += 1;
}
/**
*
* #return size of list
* Time Complexity: O(1)
* This is because we use a class
* variable size to keep track of size of linked list
*/
public int getSize() {
return size;
}
/**
*
* #param data element to insert
* #param index position at which to insert the element (zero based)
* Time Complexity : O(n)
*/
public void add(int data, int index) {
if (index > getSize()) {
return; // invalid position
}
Node current = head; //iterate through whole list
int pos = 0;
Node newNode = new Node(data);
if (index == 0) // special case, since its a single reference change!
{
newNode.next = head;
head = newNode; // this node is now the head
size += 1;
return;
}
while (current.next != null) {
if (pos == index - 1) {
break;
}
pos++;
current = current.next;
}
// These are 2 reference changes, as compared to adding at index 0
newNode.next = current.next; // here we are changing a refernce
current.next = newNode; // changing a reference here as well
size += 1;
}
/**
* Find the first occurrence of an element
* #param data element to find
* #return index at which element is found , -1 if not exist
* Time Complexity: O(n)
*/
public int find(int data) {
Node current = head;
int pos = 0;
int index = -1;
if(head == null) { //empty list
return index;
}
while(current != null) {
if (current.data == data) {
index = pos;
break;
}
pos++;
current = current.next;
}
return index;
}
/**
* Delete the first occurrence of data
* #param data element to delete
* Time complexity : O(n)
*/
public void delete(int data) {
Node current = head;
if (head == null) { // list is empty
return;
}
if(head.data == data) { // if we want to delete the head , make next node head
head = head.next;
size -= 1;
return;
}
while(current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
return;
}
current = current.next;
}
}
/**
* Delete all occurrences of data
* #param data element to delete
*
*/
public void deleteAll(int data) {
Node current = head;
if (head == null) { // list is empty
return;
}
//while loop to delete consecutive occurances of data
while(head.data == data) { // if we want to delete the head , make next node head
head = head.next;
size -= 1;
}
while(current.next != null) {
//while loop to delete consecutive occurances of data
while (current.next.data == data) {
current.next = current.next.next;
size -= 1;
}
current = current.next;
}
}
public void reverse() {
}
/**
* Prints the whole linked list
* Time Complexity : O(n)
*/
public void print() {
if(head == null) { //list is empty
return;
}
Node current = head;
while (current.next != null) {
System.out.print(current.data + "->");
current = current.next;
}
System.out.print(current.data + "\n");
}
}
public class LinkedListTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
LinkedList lt = new LinkedList();
lt.print();
lt.add(3);
lt.add(5);
lt.add(6);
lt.print();
lt.add(4, 1);
lt.print();
lt.add(4, 7);// 7 is an invalid index
lt.add(8, 3);
lt.add(8, 4);
lt.print();
System.out.println("Position : " + lt.find(8));
lt.delete(5);
lt.print();
lt.deleteAll(8);
lt.print();
System.out.println("Size : " + lt.getSize());
}
}
The time complexity of your implementation is O(n), not O(n + n^2) as you believed.
Although a nested loop is a common sign of O(n^2) it's not always the case.
The important point is the number of iterations.
In your case,
if you take k steps in the nested loop,
that reduces the remaining steps in the outer loop by k.
Overall,
you will still be taking n steps to reach the end.
But your implementation has some bugs,
and can also be improved:
Bug: you assign current = head, but if head.data == data then it will be deleted, and current will still point to it
There is no need for a nested loop. After the special treatment for the head, you can simply follow the nodes and delete the matching items
Like this:
public void deleteAll(int data) {
while (head != null && head.data == data) {
head = head.next;
size -= 1;
}
if (head == null) {
return;
}
Node current = head;
while (current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
} else {
current = current.next;
}
}
}
By the way, the special treatment of the head can be a bit annoying.
An elegant alternative is to create a dummy that points to head:
public void deleteAll(int data) {
Node dummy = new Node();
dummy.next = head;
Node current = dummy;
while (current.next != null) {
if (current.next.data == data) {
current.next = current.next.next;
size -= 1;
} else {
current = current.next;
}
}
head = dummy.next;
}
Note that everything in Java is reference except those primitive types. So current still stays at the original head.
It is unnecessary to treat consecutive occurrences as special cases. A simple iterate&judge through the linked list with O(n) - linear complexity will do exactly what you want.
Besides, a nested loop doesn't necessarily means it will definitely cost O(n^2). If you move current every times, it still walk through the linked list in linear time.
Another personal suggestion: If you need to write something like node.next.next when dealing with linked list, it's time to set another reference or to refactor your code.

deleteBack java program

I am doing some exercises on practice-it website. And there is a problem that I don't understand why I didn't pass
Write a method deleteBack that deletes the last value (the value at the back of the list) and returns the deleted value. If the list is empty, your method should throw a NoSuchElementException.
Assume that you are adding this method to the LinkedIntList class as defined below:
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
My work so far is this:
public int deleteBack(){
if(front==null){
throw new NoSuchElementException();
}else{
ListNode current = front;
while(current!=null){
current = current.next;
}
int i = current.data;
current = null;
return i;
}
}
Don't you want to iterate until the current.next is != null?
What you have now passes the entire list, and your last statements do nothing, since current is null already.
Think about the logic you have here
while(current!=null){
current = current.next;
}
When that loop exits, current == null, and then you try to access current's data. Does this point you in the right direction?
// This is the quick and dirty
//By Shewan
public int deleteBack(){
if(size()== 0){ throw new NoSuchElementException(); }
if(front==null){ throw new NoSuchElementException();
}else{
if(front.next == null){
int i = front.data;
front = null;
return i;
}
ListNode current = front.next;
ListNode prev= front;
while(current.next!=null){
prev = current;
current = current.next;
}
int i = current.data;
prev.next = null;
return i;
}
}

Categories