I find ConcurrentSkipListSet in Java Collection Framework, which is backed up with a skip list. But is there a skip list in Java? A set does not work in my use case. I need a indexable list that supports duplicates.
This answer is 3 years late but I hope it will be useful for those wanting a Java skip list from this moment on :)
This solution allows duplicates as you asked. I follow roughly the guide here http://igoro.com/archive/skip-lists-are-fascinating, so the complexities are similar to that, except delete costs O(nlogn) - as I didn't bother using doubly-linked nodes, I imagine doing so would bring delete down to O(logn).
Code comprises of: an interface, the skip list implementing the interface, and the node class. It is also generic.
You can tune the parameter LEVELS for performance, but remember the space-time tradeoff.
import java.util.Random;
interface SkippableList<T extends Comparable<? super T>> {
int LEVELS = 5;
boolean delete(T target);
void print();
void insert(T data);
SkipNode<T> search(T data);
}
public class SkipList<T extends Comparable<? super T>> implements SkippableList<T> {
public static void main(String[] args) {
SkipList<Integer> sl = new SkipList<>();
int[] data = {4,2,7,0,9,1,3,7,3,4,5,6,0,2,8};
for (int i : data) {
sl.insert(i);
}
sl.print();
sl.search(4);
sl.delete(9);
sl.print();
sl.insert(69);
sl.print();
sl.search(69);
}
private final SkipNode<T> head = new SkipNode<>(null);
private final Random rand = new Random();
#Override
public void insert(T data) {
SkipNode<T> SkipNode = new SkipNode<>(data);
for (int i = 0; i < LEVELS; i++) {
if (rand.nextInt((int) Math.pow(2, i)) == 0) { //insert with prob = 1/(2^i)
insert(SkipNode, i);
}
}
}
#Override
public boolean delete(T target) {
System.out.println("Deleting " + target.toString());
SkipNode<T> victim = search(target, false);
if (victim == null) return false;
victim.data = null;
for (int i = 0; i < LEVELS; i++) {
head.refreshAfterDelete(i);
}
System.out.println();
return true;
}
#Override
public SkipNode<T> search(T data) {
return search(data, true);
}
#Override
public void print() {
for (int i = 0; i < LEVELS; i++) {
head.print(i);
}
System.out.println();
}
private void insert(SkipNode<T> SkipNode, int level) {
head.insert(SkipNode, level);
}
private SkipNode<T> search(T data, boolean print) {
SkipNode<T> result = null;
for (int i = LEVELS-1; i >= 0; i--) {
if ((result = head.search(data, i, print)) != null) {
if (print) {
System.out.println("Found " + data.toString() + " at level " + i + ", so stoppped" );
System.out.println();
}
break;
}
}
return result;
}
}
class SkipNode<N extends Comparable<? super N>> {
N data;
#SuppressWarnings("unchecked")
SkipNode<N>[] next = (SkipNode<N>[]) new SkipNode[SkippableList.LEVELS];
SkipNode(N data) {
this.data = data;
}
void refreshAfterDelete(int level) {
SkipNode<N> current = this.getNext(level);
while (current != null && current.getNext(level) != null) {
if (current.getNext(level).data == null) {
SkipNode<N> successor = current.getNext(level).getNext(level);
current.setNext(successor, level);
return;
}
current = current.getNext(level);
}
}
void setNext(SkipNode<N> next, int level) {
this.next[level] = next;
}
SkipNode<N> getNext(int level) {
return this.next[level];
}
SkipNode<N> search(N data, int level, boolean print) {
if (print) {
System.out.print("Searching for: " + data + " at ");
print(level);
}
SkipNode<N> result = null;
SkipNode<N> current = this.getNext(level);
while (current != null && current.data.compareTo(data) < 1) {
if (current.data.equals(data)) {
result = current;
break;
}
current = current.getNext(level);
}
return result;
}
void insert(SkipNode<N> SkipNode, int level) {
SkipNode<N> current = this.getNext(level);
if (current == null) {
this.setNext(SkipNode, level);
return;
}
if (SkipNode.data.compareTo(current.data) < 1) {
this.setNext(SkipNode, level);
SkipNode.setNext(current, level);
return;
}
while (current.getNext(level) != null && current.data.compareTo(SkipNode.data) < 1 &&
current.getNext(level).data.compareTo(SkipNode.data) < 1) {
current = current.getNext(level);
}
SkipNode<N> successor = current.getNext(level);
current.setNext(SkipNode, level);
SkipNode.setNext(successor, level);
}
void print(int level) {
System.out.print("level " + level + ": [");
int length = 0;
SkipNode<N> current = this.getNext(level);
while (current != null) {
length++;
System.out.print(current.data.toString() + " ");
current = current.getNext(level);
}
System.out.println("], length: " + length);
}
}
Fixed the bug in the implementation provided by #PoweredByRice. It threw an NPE for cases when the node deleted was the first node. Other updates include renamed variable names and reverse printing the order of the skip list.
import java.util.Random;
interface SkippableList<T extends Comparable<? super T>> {
int LEVELS = 5;
boolean delete(T target);
void print();
void insert(T data);
SkipNode<T> search(T data);
}
class SkipNode<N extends Comparable<? super N>> {
N data;
#SuppressWarnings("unchecked")
SkipNode<N>[] next = (SkipNode<N>[]) new SkipNode[SkippableList.LEVELS];
SkipNode(N data) {
this.data = data;
}
void refreshAfterDelete(int level) {
SkipNode<N> current = this;
while (current != null && current.getNext(level) != null) {
if (current.getNext(level).data == null) {
SkipNode<N> successor = current.getNext(level).getNext(level);
current.setNext(successor, level);
return;
}
current = current.getNext(level);
}
}
void setNext(SkipNode<N> next, int level) {
this.next[level] = next;
}
SkipNode<N> getNext(int level) {
return this.next[level];
}
SkipNode<N> search(N data, int level, boolean print) {
if (print) {
System.out.print("Searching for: " + data + " at ");
print(level);
}
SkipNode<N> result = null;
SkipNode<N> current = this.getNext(level);
while (current != null && current.data.compareTo(data) < 1) {
if (current.data.equals(data)) {
result = current;
break;
}
current = current.getNext(level);
}
return result;
}
void insert(SkipNode<N> skipNode, int level) {
SkipNode<N> current = this.getNext(level);
if (current == null) {
this.setNext(skipNode, level);
return;
}
if (skipNode.data.compareTo(current.data) < 1) {
this.setNext(skipNode, level);
skipNode.setNext(current, level);
return;
}
while (current.getNext(level) != null && current.data.compareTo(skipNode.data) < 1 &&
current.getNext(level).data.compareTo(skipNode.data) < 1) {
current = current.getNext(level);
}
SkipNode<N> successor = current.getNext(level);
current.setNext(skipNode, level);
skipNode.setNext(successor, level);
}
void print(int level) {
System.out.print("level " + level + ": [ ");
int length = 0;
SkipNode<N> current = this.getNext(level);
while (current != null) {
length++;
System.out.print(current.data + " ");
current = current.getNext(level);
}
System.out.println("], length: " + length);
}
}
public class SkipList<T extends Comparable<? super T>> implements SkippableList<T> {
private final SkipNode<T> head = new SkipNode<>(null);
private final Random rand = new Random();
#Override
public void insert(T data) {
SkipNode<T> skipNode = new SkipNode<>(data);
for (int i = 0; i < LEVELS; i++) {
if (rand.nextInt((int) Math.pow(2, i)) == 0) {
//insert with prob = 1/(2^i)
insert(skipNode, i);
}
}
}
#Override
public boolean delete(T target) {
System.out.println("Deleting " + target);
SkipNode<T> victim = search(target, true);
if (victim == null) return false;
victim.data = null;
for (int i = 0; i < LEVELS; i++) {
head.refreshAfterDelete(i);
}
System.out.println("deleted...");
return true;
}
#Override
public SkipNode<T> search(T data) {
return search(data, true);
}
#Override
public void print() {
for (int i = LEVELS-1; i >= 0 ; i--) {
head.print(i);
}
System.out.println();
}
private void insert(SkipNode<T> SkipNode, int level) {
head.insert(SkipNode, level);
}
private SkipNode<T> search(T data, boolean print) {
SkipNode<T> result = null;
for (int i = LEVELS-1; i >= 0; i--) {
if ((result = head.search(data, i, print)) != null) {
if (print) {
System.out.println("Found " + data.toString() + " at level " + i + ", so stopped" );
System.out.println();
}
break;
}
}
return result;
}
public static void main(String[] args) {
SkipList<Integer> sl = new SkipList<>();
int[] data = {4,2,7,0,9,1,3,7,3,4,5,6,0,2,8};
for (int i : data) {
sl.insert(i);
}
sl.print();
sl.search(4);
sl.delete(4);
System.out.println("Inserting 10");
sl.insert(10);
sl.print();
sl.search(10);
}
}
Since you've mentioned a List that is both Indexable (I assume you want speedy retrieval) and need to allow duplicates, I would advise you go for a custom Set with a LinkedList or ArrayList perhaps.
You need to have a base Set, an HashSet for example and keep adding values to it. If you face a duplicate, the value of that Set should point to a List. So, that you will have both Speedy retrieval and of course you will store your objects in a psuedo Collection manner.
This should give you good efficiency for retrieval. Ideally if your Keys are not duplicates, you will achieve an O(1) as the retrieval speed.
When you create a ConcurrentSkipListSet, you pass a comparator to the constructor.
new ConcurrentSkipListSet<>(new ExampleComparator());
public class ExampleComparator implements Comparator<Event> {//your impl }
You could create a comparator that will make your SkipListSet behave as a normal List.
You can make use the below to code make your own basic skiplist :
1)Make start and end to represent start and end of skip list.
2)Add the nodes and assign pointers to next based on
if(node is even)
then ,assign a fast lane pointer with next pointer
else
assign only pointer to next node
Java code for basic skip list (you can add more features if you want):
public class MyClass {
public static void main(String args[]) {
Skiplist skiplist=new Skiplist();
Node n1=new Node();
Node n2=new Node();
Node n3=new Node();
Node n4=new Node();
Node n5=new Node();
Node n6=new Node();
n1.setData(1);
n2.setData(2);
n3.setData(3);
n4.setData(4);
n5.setData(5);
n6.setData(6);
skiplist.insert(n1);
skiplist.insert(n2);
skiplist.insert(n3);
skiplist.insert(n4);
skiplist.insert(n5);
skiplist.insert(n6);
/*print all nodes*/
skiplist.display();
System.out.println();
/* print only fast lane node*/
skiplist.displayFast();
}
}
class Node{
private int data;
private Node one_next; //contain pointer to next node
private Node two_next; //pointer to node after the very next node
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getOne_next() {
return one_next;
}
public void setOne_next(Node one_next) {
this.one_next = one_next;
}
public Node getTwo_next() {
return two_next;
}
public void setTwo_next(Node two_next) {
this.two_next = two_next;
}
}
class Skiplist{
Node start; //start pointer to skip list
Node head;
Node temp_next; //pointer to store last used fast lane node
Node end; //end of skip list
int length;
public Skiplist(){
start=new Node();
end=new Node();
length=0;
temp_next=start;
}
public void insert(Node node){
/*if skip list is empty */
if(length==0){
start.setOne_next(node);
node.setOne_next(end);
temp_next.setTwo_next(end);
head=start;
length++;
}
else{
length++;
Node temp=start.getOne_next();
Node prev=start;
while(temp != end){
prev=temp;
temp=temp.getOne_next();
}
/*add a fast lane pointer for even no of nodes*/
if(length%2==0){
prev.setOne_next(node);
node.setOne_next(end);
temp_next.setTwo_next(node);
temp_next=node;
node.setTwo_next(end);
}
/*odd no of node will not contain fast lane pointer*/
else{
prev.setOne_next(node);
node.setOne_next(end);
}
}
}
public void display(){
System.out.println("--Simple Traversal--");
Node temp=start.getOne_next();
while(temp != end){
System.out.print(temp.getData()+"=>");
temp=temp.getOne_next();
}
}
public void displayFast(){
System.out.println("--Fast Lane Traversal--");
Node temp=start.getTwo_next();
while(temp !=end){
System.out.print(temp.getData()+"==>");
temp=temp.getTwo_next();
}
}
}
Output:
--Simple Traversal--
1=>2=>3=>4=>5=>6=>
--Fast Lane Traversal--
2==>4==>6==>
I approve to use TreeList from apache-collections and decorate it with SortedList from Happy Java Libraries
https://sourceforge.net/p/happy-guys/wiki/Sorted%20List/
I am not claiming that this is my own implementation. I just cannot remember where I found it. If you know let me know and I will update. This has been working quite well for me:
public class SkipList<T extends Comparable<? super T>> implements Iterable<T> {
Node<T> _head = new Node<>(null, 33);
private final Random rand = new Random();
private int _levels = 1;
private AtomicInteger size = new AtomicInteger(0);
/// <summary>
/// Inserts a value into the skip list.
/// </summary>
public void insert(T value) {
// Determine the level of the new node. Generate a random number R. The
// number of
// 1-bits before we encounter the first 0-bit is the level of the node.
// Since R is
// 32-bit, the level can be at most 32.
int level = 0;
size.incrementAndGet();
for (int R = rand.nextInt(); (R & 1) == 1; R >>= 1) {
level++;
if (level == _levels) {
_levels++;
break;
}
}
// Insert this node into the skip list
Node<T> newNode = new Node<>(value, level + 1);
Node<T> cur = _head;
for (int i = _levels - 1; i >= 0; i--) {
for (; cur.next[i] != null; cur = cur.next[i]) {
if (cur.next[i].getValue().compareTo(value) > 0)
break;
}
if (i <= level) {
newNode.next[i] = cur.next[i];
cur.next[i] = newNode;
}
}
}
/// <summary>
/// Returns whether a particular value already exists in the skip list
/// </summary>
public boolean contains(T value) {
Node<T> cur = _head;
for (int i = _levels - 1; i >= 0; i--) {
for (; cur.next[i] != null; cur = cur.next[i]) {
if (cur.next[i].getValue().compareTo(value) > 0)
break;
if (cur.next[i].getValue().compareTo(value) == 0)
return true;
}
}
return false;
}
/// <summary>
/// Attempts to remove one occurence of a particular value from the skip
/// list. Returns
/// whether the value was found in the skip list.
/// </summary>
public boolean remove(T value) {
Node<T> cur = _head;
boolean found = false;
for (int i = _levels - 1; i >= 0; i--) {
for (; cur.next[i] != null; cur = cur.next[i]) {
if (cur.next[i].getValue().compareTo(value) == 0) {
found = true;
cur.next[i] = cur.next[i].next[i];
break;
}
if (cur.next[i].getValue().compareTo(value) > 0)
break;
}
}
if (found)
size.decrementAndGet();
return found;
}
#SuppressWarnings({ "rawtypes", "unchecked" })
#Override
public Iterator<T> iterator() {
return new SkipListIterator(this, 0);
}
public int size() {
return size.get();
}
public Double[] toArray() {
Double[] a = new Double[size.get()];
int i = 0;
for (T t : this) {
a[i] = (Double) t;
i++;
}
return a;
}
}
class Node<N extends Comparable<? super N>> {
public Node<N>[] next;
public N value;
#SuppressWarnings("unchecked")
public Node(N value, int level) {
this.value = value;
next = new Node[level];
}
public N getValue() {
return value;
}
public Node<N>[] getNext() {
return next;
}
public Node<N> getNext(int level) {
return next[level];
}
public void setNext(Node<N>[] next) {
this.next = next;
}
}
class SkipListIterator<E extends Comparable<E>> implements Iterator<E> {
SkipList<E> list;
Node<E> current;
int level;
public SkipListIterator(SkipList<E> list, int level) {
this.list = list;
this.current = list._head;
this.level = level;
}
public boolean hasNext() {
return current.getNext(level) != null;
}
public E next() {
current = current.getNext(level);
return current.getValue();
}
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}
Related
I am struggling to understand how to implement a remove(); for both a double and single linked class. I have figured out how to remove the first node in the double, but not in the single. First I would like to debug, problem solve the single linked class, then work on the double after that.
Here is the code I have so far for the Single Linked Class.
public class SingleLinkedClass<T> {
private Node <T> head;
private Node <T> tail;
private int size;
public SingleLinkedClass() {
size = 0;
head = null;
tail = null;
}
public void insertAtHead(T v)
{
//Allocate new node
Node newNode = new Node(v, head);
//Change head to point to new node
head = newNode;
if(tail == null)
{
tail = head;
}
//Increase size
size++;
}
public void insertAtTail(T v)
{
if(tail == null)
{
tail = new Node(v, null);
head = tail;
size++;
return;
}
Node newNode = new Node(v, null);
tail.nextNode = newNode;
tail = newNode;
size++;
}
public T removeHead()
{
if(head == null)
{
throw new IllegalStateException("list is empty! cannot delete");
}
T value = head.value;
head = head.nextNode;
size--;
return value;
}
public void removeTail()
{
//Case 1: list empty
if(head == null)
{
return;
}
//Case 2: list has one node
else if(head == tail)
{
head = tail = null;
}
else
{
Node temp = head;
while(temp.nextNode != tail)
{
temp = temp.nextNode;
}
tail = temp;
tail.nextNode = null;
}
size--;
}
public boolean remove(T v) {
Node<T> previous = head;
Node<T> cursor = head.nextNode;
if (head.nextNode == null) {
return false;
}
while(cursor != tail){
if (cursor.value.equals(v)) {
previous = cursor.nextNode;
return true;
}
previous = cursor;
cursor = cursor.nextNode;
}
return false;
}
public String toString() {
if (head == null) {
return "The list is Empty!";
}
String result = "";
Node temp = head;
while (temp != null) {
result += temp.toString() + " ";
temp = temp.nextNode;
}
return result;
}
public int size() {
return size;
}
private class Node <T> {
private T value;
private Node <T> nextNode;
public Node(T v, Node<T> n) {
value = v;
nextNode = n;
}
public String toString() {
return "" + value;
}
}
}
Here is my Double Linked Class
public class DoubelyLinkedList<E> {
private int size;
private Node<E> header;
private Node<E> trailer;
public DoubelyLinkedList() {
size = 0;
header = new Node<E>(null, null, null);
trailer = new Node<E>(null, null, header);
header.next = trailer;
}
public boolean remove(E v) {
//If the list is empty return false
if(header.next == trailer){
return false;
}
//If v is the head of the list remove and return true
Node <E> cursor = header.next;
for (int i = 0; i < size; i++) {
//Remove at Head
if(cursor.value.equals(v)){
removeAtHead();
}
cursor = cursor.next;
}
return true;
}
/*
} */
public void insertAtHead(E v) {
insertBetween(v, header, header.next);
}
public void insertAtTail(E v) {
insertBetween(v, trailer.prev, trailer);
}
private void insertBetween(E v, Node<E> first, Node<E> second) {
Node<E> newNode = new Node<>(v, second, first);
first.next = newNode;
second.prev = newNode;
size++;
}
public E removeAtHead() {
return removeBetween(header, header.next.next);
}
public E removeAtTail() {
return removeBetween(trailer.prev.prev, trailer);
}
private E removeBetween(Node<E> first, Node<E> second) {
if (header.next == trailer)// if the list is empty
{
throw new IllegalStateException("The list is empty!");
}
E result = first.next.value;
first.next = second;
second.prev = first;
size--;
return result;
}
public String toStringBackward() {
if (size == 0) {
return "The list is empty!";
}
String r = "";
Node<E> temp = trailer.prev;
while (temp != header) {
r += temp.toString() + " ";
temp = temp.prev;
}
return r;
}
public String toString() {
if (size == 0) {
return "The list is empty!";
}
String r = "";
Node<E> temp = header.next;
while (temp != trailer) {
r += temp + " ";
temp = temp.next;
}
return r;
}
private static class Node<T> {
private T value;
private Node<T> next;
private Node<T> prev;
public Node(T v, Node<T> n, Node<T> p) {
value = v;
next = n;
prev = p;
}
public String toString() {
return value.toString();
}
}
}
Here is my Driver
public class Driver {
public static void main(String[] args) {
DoubelyLinkedList<String> doubley = new DoubelyLinkedList();
SingleLinkedClass<String> single = new SingleLinkedClass();
single.insertAtHead("Bob");
single.insertAtHead("Sam");
single.insertAtHead("Terry");
single.insertAtHead("Don");
System.out.println(single);
single.remove("Bob");
System.out.println("Single Remove Head: " + single);
/*
single.remove("Don");
System.out.println("Single Remove Tail: " + single);
single.remove("Terry");
System.out.println("Single Remove Inbetween: " + single);
*/
System.out.println();
System.out.println();
doubley.insertAtHead("Bob");
doubley.insertAtHead("Sam");
doubley.insertAtHead("Terry");
doubley.insertAtHead("Don");
System.out.println(doubley);
doubley.remove("Bob");
System.out.println("Double Remove Head: " + doubley);
doubley.remove("Don");
System.out.println("Double Remove Tail: " + doubley);
/*
doubley.remove("Sam");
System.out.println("Double Remove Inbetween: " + doubley);
*/
}
}
In the removeHead moving head to its next, it might become null. Then tail was the head too. Then tail should be set to null too.
DoublyLinkedList is better English than DoubelyLinkedList.
As this is homework, I leave it by this.
I'm trying to calculate the total 'wait time' and the average wait time for my 'restaurant waitlist' application. I can't figure that part out and I've tried to display the total, but it keeps displaying the total for one. I'm using a linkedlist and want it to keep adding as I add people to the waitlist. I also do not know how to display the average as the name is a string and if I do the total/name, it gives me an error. If I parse it to an Int, it gives me an error. Any help would be appreciated. When I click the following button, it should display the running total.
private void btnAddActionPerformed(java.awt.event.ActionEvent evt) {
Random rand = new Random();
String name = txtName.getText();
int time = rand.nextInt(30) + 1;
int totaltime = time;
int partySize = Integer.parseInt(txtSize.getText());
txtTotal.setText(String.valueOf(totaltime) + " minutes until your table is ready.");
Highest = partySize;
String result = " Name: " + txtName.getText() + " Party Size: " + partySize + " Wait Time: " + time + " minutes.";
stack.enqueue(result);
Wait++;
}
private void btnDisplayActionPerformed(java.awt.event.ActionEvent evt) {
String result;
int s;
int size = stack.size();
lstOutput.removeAll();
for (s = 0; s < size; s++) {
result = (String)stack.dequeue();
lstOutput.add(result);
}
}
stack is my LinkedList.
LinkedListStack stack = new LinkedListStack();
This is the LinkedListStack
public class LinkedListStack<E> implements QueueInterface<E> {
private LinkedList<E> list = new LinkedList<>(); // an empty list
public LinkedListStack() {
} // new queue relies on the initially empty list
public int size() {
return list.getSize();
}
public boolean isEmpty() {
return list.isEmpty();
}
public void enqueue(E element) {
list.addLast(element);
}
public E first() {
return list.first();
}
public E dequeue() {
return list.removeFirst();
}
}
This is my QueueInterface
public interface QueueInterface<E> {
int size();
boolean isEmpty();
// adds an item to the stack
void enqueue(E e);
// return but not remove the top item on the stack
E first();
// remove item at the top of the stack
E dequeue();
}
And this is the LinkedList I'm using.
public class LinkedList<E> {
private int size;
private Node<E> head;
private Node<E> tail;
// default constructor
public LinkedList() {
size = 0;
head = null;
tail = null;
}
// read-only property
public int getSize() {
return size;
}
public boolean isEmpty() {
// replaces an if/else
return (size == 0);
}
// return but not remove head of the list
public E first() {
if ( isEmpty() ) {
return null;
}
else {
return head.getElement();
}
}
public E last() {
if ( isEmpty() ) {
return null;
}
else {
return tail.getElement();
}
}
public void addFirst(E e) {
// create a new node and make it the new head of the list
head = new Node<>(e, head);
if (size == 0) {
tail = head; // special case first item in the list
}
size++;
}
public void addLast(E e) {
// create a new node and add to the tail of the list
Node<E> newest = new Node<>(e, null);
if (size == 0) { // special case for the first item
head = newest; // now head points to the new node
}
else {
tail.setNext(newest);
}
tail = newest;
size++;
}
public E removeFirst() {
if (isEmpty() ) {
return null;
}
else {
E tets = head.getElement();
head = head.getNext();
size--;
if (size == 0) {
tail = null; // list is now empty
}
return tets;
}
}
// nested class
public class Node<E> {
private E element;
private Node<E> next;
// custom constructor
public Node(E e, Node<E> n) {
element = e;
next = n;
}
// get element
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> n) {
next = n;
}
} // end nested node class
} // end of LinkedList
I am having problem with sorting patient list based on seriousness and arrival time. Can take a look what wrong with my code? See the LList.java, the SortPatient method is correct?
ListInterface.java
public interface ListInterface<T> {
public boolean add(T newEntry);
public boolean add(int newPosition, T newEntry);
public T remove(int givenPosition);
public void clear();
public boolean replace(int givenPosition, T newEntry);
public T getEntry(int givenPosition);
public boolean contains(T anEntry);
public int getLength();
public boolean isEmpty();
public boolean isFull();
public int getPosition(T anObject);
public void SortPatient(ListInterface<Patient> patientList);
}
Llist.java
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
public class LList<T> implements ListInterface<T> {
private Node firstNode; // reference to first node
private int length; // number of entries in list
public LList() {
clear();
}
public LList(T[] arr) {
clear();
firstNode = new Node(arr[0], null);
Node p = firstNode;
for (int index = 1; index < arr.length; index++) {
p.next = new Node(arr[index], null);
p = p.next;
//index must start with 0
//or add(arr[index]);
}
length = arr.length;
}
public int getPosition(T anObject) {
Node currentNode = firstNode;
int position = 0;
while (currentNode != null) {
position++;
if (currentNode.data.equals(anObject)) {
return position;
}
currentNode = currentNode.next;
}
return -1;
}
public final void clear() {
firstNode = null;
length = 0;
}
public boolean add(T newEntry) {
Node newNode = new Node(newEntry);
// create the new node
if (isEmpty()) // if empty list
{
firstNode = newNode;
} else { // add to end of nonempty list
Node currentNode = firstNode; // traverse linked list with p pointing to the current node
while (currentNode.next != null) { // while have not reached the last node
currentNode = currentNode.next;
}
currentNode.next = newNode; // make last node reference new node
}
length++;
return true;
}
public boolean add(int newPosition, T newEntry) { // OutOfMemoryError possible
boolean isSuccessful = true;
if ((newPosition >= 1) && (newPosition <= length + 1)) {
Node newNode = new Node(newEntry);
if (isEmpty() || (newPosition == 1)) { // case 1: add to beginning of list
newNode.next = firstNode;
firstNode = newNode;
} else { // case 2: list is not empty and newPosition > 1
Node nodeBefore = firstNode;
for (int i = 1; i < newPosition - 1; ++i) {
nodeBefore = nodeBefore.next; // advance nodeBefore to its next node
}
newNode.next = nodeBefore.next; // make new node point to current node at newPosition
nodeBefore.next = newNode; // make the node before point to the new node
}
length++;
} else {
isSuccessful = false;
}
return isSuccessful;
}
public T remove(int givenPosition) {
T result = null; // return value
if ((givenPosition >= 1) && (givenPosition <= length)) {
if (givenPosition == 1) { // case 1: remove first entry
result = firstNode.data; // save entry to be removed
firstNode = firstNode.next;
} else { // case 2: givenPosition > 1
Node nodeBefore = firstNode;
for (int i = 1; i < givenPosition - 1; ++i) {
nodeBefore = nodeBefore.next; // advance nodeBefore to its next node
}
result = nodeBefore.next.data; // save entry to be removed
nodeBefore.next = nodeBefore.next.next; // make node before point to node after the
} // one to be deleted (to disconnect node from chain)
length--;
}
return result; // return removed entry, or
// null if operation fails
}
public boolean replace(int givenPosition, T newEntry) {
boolean isSuccessful = true;
if ((givenPosition >= 1) && (givenPosition <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < givenPosition - 1; ++i) {
// System.out.println("Trace| currentNode.data = " + currentNode.data + "\t, i = " + i);
currentNode = currentNode.next; // advance currentNode to next node
}
currentNode.data = newEntry; // currentNode is pointing to the node at givenPosition
} else {
isSuccessful = false;
}
return isSuccessful;
}
public T getEntry(int givenPosition) {
T result = null;
if ((givenPosition >= 1) && (givenPosition <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < givenPosition - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
public boolean contains(T anEntry) {
boolean found = false;
Node currentNode = firstNode;
while (!found && (currentNode != null)) {
if (anEntry.equals(currentNode.data)) {
found = true;
} else {
currentNode = currentNode.next;
}
}
return found;
}
public int getLength() {
return length;
}
public boolean isEmpty() {
boolean result;
if (length == 0) {
result = true;
} else {
result = false;
}
return result;
}
public boolean isFull() {
return false;
}
public String toString() {
String outputStr = "";
Node currentNode = firstNode;
while (currentNode != null) {
outputStr += currentNode.data;
currentNode = currentNode.next;
}
return outputStr;
}
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
this.next = null;
}
private Node(T data, Node next) {
this.data = data;
this.next = next;
}
} // end Node
public void SortPatient(ListInterface<Patient> patientList) {
if (patientList == null) {
return;
}
boolean swapped;
Patient patient;
do {
swapped = false;
patient = head;
while (patientList.next != null) {
if (patient.compareTo(patientList.next) < 1) {
swap(patientList.current, patientList.next);
swapped = true;
}
patient = patientList.next;
}
} while (swapped);
}
}
Patient.java
import java.util.Date;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import static javafx.scene.input.KeyCode.T;
public class Patient implements Comparable<Patient> {
String patientId;
String patientName;
String patientGender;
String patientIcNumber;
String patientContactNumber;
Date date;
int seriousness;
static int count = 0;
public Patient() {
}
public Patient(String patientId, String patientName, String patientGender, String patientIcNumber, String patientContactNumber, Date date, int seriousness) {
this.patientId = patientId;
this.patientName = patientName;
this.patientGender = patientGender;
this.patientIcNumber = patientIcNumber;
this.patientContactNumber = patientContactNumber;
this.date = date;
this.seriousness = seriousness;
count++;
}
public String getPatientId() {
return patientId;
}
public void setPatientId(String patientId) {
this.patientId = patientId;
}
public String getPatientName() {
return patientName;
}
public void setPatientName(String patientName) {
this.patientName = patientName;
}
public String getPatientGender() {
return patientGender;
}
public void setPatientGender(String patientGender) {
this.patientGender = patientGender;
}
public String getPatientIcNumber() {
return patientIcNumber;
}
public void setPatientIcNumber(String patientIcNumber) {
this.patientIcNumber = patientIcNumber;
}
public String getPatientContactNumber() {
return patientContactNumber;
}
public void setPatientContactNumber(String patientContactNumber) {
this.patientContactNumber = patientContactNumber;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getSeriousness() {
return seriousness;
}
public void setSeriousness(int seriousness) {
this.seriousness = seriousness;
}
public int getCount() {
return count;
}
#Override
public String toString() {
return patientId + " " + patientName + " " + patientGender + " " + patientIcNumber + " " + patientContactNumber + " " + date + " " + seriousness + "\n";
}
#Override
public int compareTo(Patient t) {
int patientSeriouness = t.seriousness;
Date arrival = t.date;
if (this.seriousness == patientSeriouness) {
return this.date.compareTo(arrival);
} else {
return Integer.compare(this.seriousness, patientSeriouness);
}
}
}
Couple of issues in your code (I just went through add,getentry and sort method):
In getEntry method, Remember index always start with 0 and go after till length - 1, so you should change our method to:
public T getEntry(int givenPosition) {
T result = null;
if ((givenPosition >= 0) && (givenPosition < length)) {
Node currentNode = firstNode;
for (int i = 0; i < givenPosition; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
Change your interface and class implementation to remove passing on the ListInterface reference and your implementation should look like:
public void SortPatient() {
if (firstNode == null) {
return;
}
boolean swapped;
Node patient;
do {
swapped = false;
patient = firstNode;
while (patient.next != null) {
if (patient.data.compareTo(patient.next.data) > 0) {
swap(patient, patient.next);
swapped = true;
}
patient = patient.next;
}
} while (swapped);
}
private void swap(Node patient, Node nextPatient) {
T temp = patient.data;
patient.data = nextPatient.data;
nextPatient.data = temp;
}
Your compare to method in Patient class needs some improvements and it should be as below:
#Override
public int compareTo(Patient t) {
int patientSeriouness = t.seriousness;
Date arrival = t.date;
if (this.seriousness == patientSeriouness) {
return this.date.compareTo(arrival);
} else {
return ((Integer)this.seriousness).compareTo(patientSeriouness);
}
}
Last but not the least, your class definition LList should take generics of type Comparable (As you are using compareTo method), so you need to mandate that and it should be defined as
public class LList<T extends Comparable<T>> implements ListInterface<T>
public class LinkedList
{
private Node head;
private Node tail;
private int numberOfElements;
public LinkedList()
{
head = null;
tail = null;
this.numberOfElements = 0;
}
public int length()
{
return this.numberOfElements;
}
public void removeFront()
{
Node currNode = head;
head = head.getNextNode();
currNode.setNextNode(null);
this.numberOfElements--;
}
public void removeLast()
{
this.tail = this.tail.prev;
}
public void removeAtIndex(int index) throws AmishException
{
if (index == 0) {
Node q = head;
head = q.getNextNode();
}
else if ((index > numberOfElements - 1) || (index < 0))
System.out.println("Index out bounds.");
else {
Node currNode = head;
for (int i = 0; i < index; i++) {
currNode = currNode.getNextNode();
}
Node temp = currNode;
currNode = temp.getPrevNode();
currNode.setNextNode(temp.getNextNode());
temp = null;
numberOfElements--;
}
}
Node -
public class Node
{
private int payload;
private Node nextNode;
public Node prev;
public Node previous;
public Node next;
public Node(int payload)
{
this.payload = payload;
nextNode = null;
}
public Node getNextNode()
{
return this.nextNode;
}
public Node getPrevNode()
{
return this.getPrevNode();
}
public void setNextNode(Node n)
{
this.nextNode = n;
}
public void display()
{
System.out.print("(" + super.toString() + " : " + this.payload + ")");
if(this.nextNode != null)
{
System.out.print(" -> ");
this.nextNode.display();
}
else
{
System.out.println("");
}
}
public String toString()
{
return "" + super.toString() + " : " + this.payload;
}
public void setPrevNode(Node n)
{
previous = n;
}
}
Driver -
public class Driver
{
public static void main(String[] args) throws Exception
{
LinkedList ll = new LinkedList();
ll.addFront(7);
ll.addFront(5);
ll.addEnd(13);
ll.addEnd(27);
ll.addFront(2);
ll.addAtIndex(1, 0);
ll.addAtIndex(12, 6);
ll.addAtIndex(9, 2);
ll.addAtIndex(11, 2);
//ll.removeFront();
//ll.removeLast();
ll.removeAtIndex(1);
for(int i = 0; i < ll.length(); i++)
{
System.out.println(ll.get(i));
}
}
}
I got what I need to remove the head's index, but how to do anything else is beyond me.
I have the methods to remove the head and the tail now I just need to know how to remove at an index just Like if I were to add at an index.
Okay, completely editing this answer. I took your code and went from that. There were some issues with your Node class, check out mine. I created a barebones Node class, add the any other functionality you may need/want. For the LinkedList class, I created a simple add method that adds to the end of the list. Use this as a prototype for your other adds. Everything right now is working and I put some println's to help you see where the program is at. I highly recommend using a debugger. Also note that this is a doubly linked list.
Linked List
public class LinkedList {
private Node head;
private Node tail;
private int numberOfElements;
public LinkedList()
{
head = null;
tail = null;
numberOfElements = 0;
}
public int length()
{
return numberOfElements;
}
public void removeAtIndex(int index)
{
if (index == 0) {
Node q = head;
head = q.getNextNode();
numberOfElements--;
}
else if ((index > numberOfElements - 1) || (index < 0))
System.out.println("Index out of bounds.");
else {
Node currNode = head;
for (int i = 0; i < index; i++) {
//Node p = currNode;
System.out.println("At this payload " + currNode.getPayload());
currNode = currNode.getNextNode();
System.out.println("Now at this payload " + currNode.getPayload());
}
Node temp = currNode;
System.out.println("Removing the node with payload " + temp.getPayload());
currNode = temp.getPrevNode();
currNode.setNextNode(temp.getNextNode());
temp = null;
numberOfElements--;
}
}
public void add(int num) {
Node newNode = new Node(num);
newNode.setNextNode(null);
if (numberOfElements == 0) {
newNode.setPrevNode(null);
head = newNode;
tail = newNode;
}
else if (numberOfElements == 1) {
head.setNextNode(newNode);
tail = newNode;
tail.setPrevNode(head);
}
else {
newNode.setPrevNode(tail);
tail.setNextNode(newNode);
tail = newNode;
}
System.out.println("Inserted " + num + " into the linked list");
numberOfElements++;
}
public void printList() {
Node temp = head;
while (temp != null) {
System.out.println("Node with payload " + temp.getPayload());
temp = temp.getNextNode();
}
}
}
Node
public class Node {
private int payload;
private Node next;
private Node prev;
public Node(int payload) {
this.payload = payload;
prev = null;
next = null;
}
public Node getNextNode() {
return next;
}
public Node getPrevNode() {
return prev;
}
public void setNextNode(Node n) {
next = n;
}
public void setPrevNode(Node n) {
prev = n;
}
public int getPayload() {
return payload;
}
}
Driver
public class Driver {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add(7);
ll.add(5);
ll.add(13);
ll.add(27);
ll.add(2);
ll.printList();
ll.removeAtIndex(3);
ll.printList();
}
}
I have implemented a Linked List into Java. I have created everything, but I am having difficulty removing a specific node with specific data. It is throwing a NullPointerException. I believe, I am getting a NullPointerException because the next node is null. If someone could please point me in the right direction that would be great.
Input
anything
one
two
three
exception:
Exception in thread "main" java.lang.NullPointerException
at LinkedList.remove(LinkedList.java:28)
at Main.main(Main.java:29)
Classes:
Linked list class
public class LinkedList {
// fields
private Node head;
private Node last;
private int size = 0;
// constructor, used when the class is first called
public LinkedList() {
head = last = new Node(null);
}
// add method
public void add(String s) {
last.setNext(new Node(s));
last = last.getNext();
size++;
}
// remove method, if it returns false then the specified index element doens not exist
// otherwise will return true
public boolean remove(String data) {
Node current = head;
last = null;
while(current != null) {
if(current.getData().equals(data)) {
current = current.getNext();
if(last == null) {
last = current;
}else {
last.getNext().setNext(current);
size--;
return true;
}
}else {
last = current;
current = current.getNext();
}
}
return false;
}
//will return the size of the list - will return -1 if list is empty
public int size() {
return size;
}
// will check if the list is empty or not
public boolean isEmpty() {
return true;
}
// #param (index) will get the data at specified index
public String getData(int index) {
if(index <= 0) {
return null;
}
Node current = head.getNext();
for(int i = 1;i < index;i++) {
if(current.getNext() == null) {
return null;
}
current = current.getNext();
}
return current.getData();
}
//#param will check if the arguement passed is in the list
// will return true if the list contains arg otherwise false
public boolean contains(String s) {
for(int i = 1;i<=size();i++) {
if(getData(i).equals(s)) {
return true;
}
}
return false;
}
//#return contents of the list - recursively
public String toString() {
Node current = head.getNext();
String output = "[";
while(current != null) {
output += current.getData()+",";
current = current.getNext();
}
return output+"]";
}
//#return first node
public Node getHead() {
return head;
}
// #return (recursively) list
public void print(Node n) {
if(n == null) {
return;
}else {
System.out.println(n.getData());
print(n.getNext());
}
}
}
Main
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException{
LinkedList list = new LinkedList(); // declaring main linked list
LinkedList b_List = new LinkedList(); // declaring the backup list
String input = null;
// getting input from user, will stop when user has entered 'fin'
while(!(input = br.readLine()).equals("fin")) {
list.add(input); // adding to main list
b_List.add(input);
}
list.print(list.getHead().getNext());
System.out.println("Input Complete.");
if(list.size() == 1) {
System.out.println("You have entered only one name. He/She is the survior");
}else {
System.out.println("Enter the name(s) would like to remove: ");
while(b_List.size() != 1) {
String toRemove = br.readLine();
b_List.remove(toRemove);
}
}
System.out.println("The contestants were: ");
list.print(list.getHead().getNext());
}
}
node
public class Node {
// Fields
private String data;
private Node next;
// constructor
public Node(String data) {
this(data,null);
}
// constructor two with Node parameter
public Node(String data, Node node) {
this.data = data;
next = node;
}
/**
* Methods below return information about fields within class
* */
// #return the data
public String getData() {
return data;
}
// #param String data to this.data
public void setData(String data) {
this.data = data;
}
// #return next
public Node getNext() {
return next;
}
// #param Node next set to this.next
public void setNext(Node next) {
this.next = next;
}
}
First of all, your head is just a before-first marker so you shouldn't start the remove check from it.
Second, your remove method fails if node data is null
Third - your implementation is broken anyway because of last.getNext().setNext(current) - it won't link previous node with next, it will link current to next (i.e. will do nothing)
Fourth - it still fails to remove first element because of mysterious operations with last...
Correct implementation of remove would be something like this:
public boolean remove(String data){
Node previous = head;
Node current = head.getNext();
while (current != null) {
String dataOld = current.getData();
if ((dataOld == null && data == null) || (dataOld != null && dataOld.equals(data))) {
Node afterRemoved = current.getNext();
previous.setNext(afterRemoved);
if (afterRemoved == null) { // i.e. removing last element
last = previous;
}
size--;
return true;
} else {
previous = current;
current = current.getNext();
}
}
return false;
}
Here we can see the simple implementation of LinkedList with iterator
class LinkedList implements Iterable{
private Node node;
public void add(Object data){
if(!Optional.ofNullable(node).isPresent()){
node = new Node();
node.setData(data);
}else{
Node node = new Node();
node.setData(data);
Node lastNode = getLastNode(this.node);
lastNode.setNext(node);
}
}
private Node getLastNode(Node node){
if(node.getNext()==null){
return node;
}else{
return getLastNode(node.getNext());
}
}
class Node{
private Object data;
private Node next;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public Iterator iterator() {
return new NodeIterator();
}
class NodeIterator implements Iterator{
private Node current;
public boolean hasNext() {
if(current == null){
current = node;
return Optional.ofNullable(current).isPresent();
}else{
current = current.next;
return Optional.ofNullable(current).isPresent();
}
}
public Node next() {
return current;
}
}
}
public class LinkedListImpl {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add("data1");
linkedList.add("data2");
linkedList.add("data3");
for(LinkedList.Node node: linkedList){
System.out.println(node.getData());
}
}
}
Here is Full Implementaion of Linked List
including insertion,deletion,searching,reversing,swaping,size,display and various important operations of linked list
import java.util.NoSuchElementException;
import java.util.Scanner;
class Node<T> {
public Node<T> next;
public T data;
public Node() {
}
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
#Override
public String toString() {
return "Node [next=" + next + ", data=" + data + "]";
}
}
class LinkedList<T> {
Node<T> start = null;
Node<T> end = null;
public void insertAtStart(T data) {
Node<T> nptr = new Node<T>(data, null);
if (empty()) {
start = nptr;
end = start;
} else {
nptr.next = start;
start = nptr;
}
display();
}
public void insertAtEnd(T data) {
Node<T> nptr = new Node<T>(data, null);
if (empty()) {
insertAtStart(data);
return;
} else {
end.next = nptr;
end = nptr;
}
display();
}
public void insertAtPosition(int position, T data) {
if (position != 1 && empty())
throw new IllegalArgumentException("Empty");
if (position == 1) {
insertAtStart(data);
return;
}
Node<T> nptr = new Node<T>(data, null);
if (position == size()) {
Node<T> startPtr = start;
Node<T> endPtr = startPtr;
while (startPtr.next != null) {
endPtr = startPtr;
startPtr = startPtr.next;
}
endPtr.next = nptr;
nptr.next = end;
} else {
position -= 1;
Node<T> startPtr = start;
for (int i = 1; i < size(); i++) {
if (i == position) {
Node<T> temp = startPtr.next;
startPtr.next = nptr;
nptr.next = temp;
}
startPtr = startPtr.next;
}
}
display();
}
public void delete(int position) {
if (empty())
throw new IllegalArgumentException("Empty");
if (position == 1) {
start = start.next;
} else if (position == size()) {
Node<T> startPtr = start;
Node<T> endPtr = start;
while (startPtr.next != null) {
endPtr = startPtr;
startPtr = startPtr.next;
}
endPtr.next = null;
end = endPtr;
} else {
position -= 1;
Node<T> startPtr = start;
for (int i = 1; i <= position; i++) {
if (i == position) {
Node<T> temp = startPtr.next.next;
startPtr.next = temp;
}
startPtr = startPtr.next;
}
}
display();
}
public int index(T data) {
if (empty())
throw new IllegalArgumentException("Empty");
return index(start, data, 0);
}
private int index(Node<T> link, T data, int index) {
if (link != null) {
if (link.data == data) {
return index;
}
return index(link.next, data, ++index);
}
return -1;
}
public void replace(int position, T data) {
if (empty())
throw new IllegalArgumentException("Empty");
if (position == 1)
start.data = data;
else if (position == size())
end.data = data;
else {
Node<T> startPtr = start;
for (int i = 1; i <= position; i++) {
if (i == position)
startPtr.data = data;
startPtr = startPtr.next;
}
}
display();
}
public void replaceRecursively(int position, T data) {
replaceRecursively(start, position, data, 1);
display();
}
private void replaceRecursively(Node<T> link, int position, T data, int count) {
if (link != null) {
if (count == position) {
link.data = data;
return;
}
replaceRecursively(link.next, position, data, ++count);
}
}
public T middle() {
if (empty())
throw new NoSuchElementException("Empty");
Node<T> slowPtr = start;
Node<T> fastPtr = start;
while (fastPtr != null && fastPtr.next != null) {
slowPtr = slowPtr.next;
fastPtr = fastPtr.next.next;
}
return slowPtr.data;
}
public int occurence(T data) {
if (empty())
throw new NoSuchElementException("Empty");
return occurence(start, data, 0);
}
private int occurence(Node<T> link, T data, int occurence) {
if (link != null) {
if (link.data == data)
++occurence;
return occurence(link.next, data, occurence);
}
return occurence;
}
public void reverseRecusively() {
reverseRecusively(start);
swapLink();
display();
}
private Node<T> reverseRecusively(Node<T> link) {
if (link == null || link.next == null)
return link;
Node<T> nextLink = link.next;
link.next = null;
Node<T> revrseList = reverseRecusively(nextLink);
nextLink.next = link;
return revrseList;
}
public void reverse() {
if (empty())
throw new NoSuchElementException("Empty");
Node<T> prevLink = null;
Node<T> currentLink = start;
Node<T> nextLink = null;
while (currentLink != null) {
nextLink = currentLink.next;
currentLink.next = prevLink;
prevLink = currentLink;
currentLink = nextLink;
}
swapLink();
display();
}
private void swapLink() {
Node<T> temp = start;
start = end;
end = temp;
}
public void swapNode(T dataOne, T dataTwo) {
if (dataOne == dataTwo)
throw new IllegalArgumentException("Can't swap " + dataOne + " and " + dataTwo + " both are same");
boolean foundDataOne = false;
boolean foundDataTwo = false;
Node<T> dataOnePtr = start;
Node<T> dataOnePrevPtr = start;
while (dataOnePtr.next != null && dataOnePtr.data != dataOne) {
dataOnePrevPtr = dataOnePtr;
dataOnePtr = dataOnePtr.next;
}
Node<T> dataTwoPtr = start;
Node<T> dataTwoPrevPtr = start;
while (dataTwoPtr.next != null && dataTwoPtr.data != dataTwo) {
dataTwoPrevPtr = dataTwoPtr;
dataTwoPtr = dataTwoPtr.next;
}
if (dataOnePtr != null && dataOnePtr.data == dataOne)
foundDataOne = true;
if (dataTwoPtr != null && dataTwoPtr.data == dataTwo)
foundDataTwo = true;
if (foundDataOne && foundDataTwo) {
if (dataOnePtr == start)
start = dataTwoPtr;
else if (dataTwoPtr == start)
start = dataOnePtr;
if (dataTwoPtr == end)
end = dataOnePtr;
else if (dataOnePtr == end)
end = dataTwoPtr;
Node<T> tempDataOnePtr = dataOnePtr.next;
Node<T> tempDataTwoPtr = dataTwoPtr.next;
dataOnePrevPtr.next = dataTwoPtr;
dataTwoPtr.next = tempDataOnePtr;
dataTwoPrevPtr.next = dataOnePtr;
dataOnePtr.next = tempDataTwoPtr;
if (dataOnePtr == dataTwoPrevPtr) {
dataTwoPtr.next = dataOnePtr;
dataOnePtr.next = tempDataTwoPtr;
} else if (dataTwoPtr == dataOnePrevPtr) {
dataOnePtr.next = dataTwoPtr;
dataTwoPtr.next = tempDataOnePtr;
}
} else
throw new NoSuchElementException("Either " + dataOne + " or " + dataTwo + " not in the list");
display();
}
public int size() {
return size(start, 0);
}
private int size(Node<T> link, int i) {
if (link == null)
return 0;
else {
int count = 1;
count += size(link.next, 0);
return count;
}
}
public void printNthNodeFromLast(int n) {
if (empty())
throw new NoSuchElementException("Empty");
Node<T> main_ptr = start;
Node<T> ref_ptr = start;
int count = 0;
while (count < n) {
if (ref_ptr == null) {
System.out.println(n + " is greater than the no of nodes in the list");
return;
}
ref_ptr = ref_ptr.next;
count++;
}
while (ref_ptr != null) {
main_ptr = main_ptr.next;
ref_ptr = ref_ptr.next;
}
System.out.println("Node no " + n + " from the last is " + main_ptr.data);
}
public void display() {
if (empty())
throw new NoSuchElementException("Empty");
display(start);
}
private void display(Node<T> link) {
if (link != null) {
System.out.print(link.data + " ");
display(link.next);
}
}
public boolean empty() {
return start == null;
}
}
public class LinkedListTest {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<Integer>();
boolean yes = true;
Scanner scanner = new Scanner(System.in);
do {
System.out.println("\n1. Insert At Start");
System.out.println("2. Insert At End");
System.out.println("3. Insert at Position");
System.out.println("4. Delete");
System.out.println("5. Display");
System.out.println("6. Empty status");
System.out.println("7. Get Size");
System.out.println("8. Get Index of the Item");
System.out.println("9. Replace data at given position");
System.out.println("10. Replace data at given position recusively");
System.out.println("11. Get Middle Element");
System.out.println("12. Get Occurence");
System.out.println("13. Reverse Recusively");
System.out.println("14. Reverse");
System.out.println("15. Swap the nodes");
System.out.println("16. Nth Node from last");
System.out.println("\nEnter your choice");
int choice = scanner.nextInt();
switch (choice) {
case 1:
try {
System.out.println("Enter the item");
linkedList.insertAtStart(scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 2:
try {
System.out.println("Enter the item");
linkedList.insertAtEnd(scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 3:
try {
System.out.println("Enter the position");
int position = scanner.nextInt();
if (position < 1 || position > linkedList.size()) {
System.out.println("Invalid Position");
break;
}
System.out.println("Enter the Item");
linkedList.insertAtPosition(position, scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 4:
try {
System.out.println("Enter the position");
int position = scanner.nextInt();
if (position < 1 || position > linkedList.size()) {
System.out.println("Invalid Position");
break;
}
linkedList.delete(position);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 5:
try {
linkedList.display();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 6:
System.out.println(linkedList.empty());
break;
case 7:
try {
System.out.println(linkedList.size());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 8:
try {
System.out.println(linkedList.index(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 9:
try {
System.out.println("Enter the position");
int position = scanner.nextInt();
if (position < 1 || position > linkedList.size()) {
System.out.println("Invalid Position");
break;
}
linkedList.replace(position, scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 10:
try {
System.out.println("Enter the position");
int position = scanner.nextInt();
if (position < 1 || position > linkedList.size()) {
System.out.println("Invalid Position");
break;
}
System.out.println("Enter the item");
linkedList.replaceRecursively(position, scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 11:
try {
System.out.println(linkedList.middle());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 12:
try {
System.out.println("Enter the item");
System.out.println(linkedList.occurence(scanner.nextInt()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 13:
try {
linkedList.reverseRecusively();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 14:
try {
linkedList.reverse();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 15:
try {
System.out.println("Enter the nodes");
linkedList.swapNode(scanner.nextInt(), scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 16:
try {
System.out.println("Enter which node do you want from last");
linkedList.printNthNodeFromLast(scanner.nextInt());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
System.out.println("Invalid Choice");
break;
}
} while (yes);
scanner.close();
}
}
Consider another possible implementation of a working non-recursive Linked List with generic T placeholder. It works out of the box and the code is a more simple one:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList<T> implements Iterable<T> {
private Node first;
private Node last;
private int N;
public LinkedList() {
first = null;
last = null;
N = 0;
}
public void add(T item) {
if (item == null) { throw new NullPointerException("Null object!"); }
if (!isEmpty()) {
Node prev = last;
last = new Node(item, null);
prev.next = last;
}
else {
last = new Node(item, null);
first = last;
}
N++;
}
public boolean remove(T item) {
if (isEmpty()) { throw new IllegalStateException("Empty list!"); }
boolean result = false;
Node prev = first;
Node curr = first;
while (curr.next != null || curr == last) {
if (curr.data.equals(item)) {
// remove the last remaining element
if (N == 1) { first = null; last = null; }
// remove first element
else if (curr.equals(first)) { first = first.next; }
// remove last element
else if (curr.equals(last)) { last = prev; last.next = null; }
// remove element
else { prev.next = curr.next; }
N--;
result = true;
break;
}
prev = curr;
curr = prev.next;
}
return result;
}
public int size() {
return N;
}
public boolean isEmpty() {
return N == 0;
}
private class Node {
private T data;
private Node next;
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
public Iterator<T> iterator() { return new LinkedListIterator(); }
private class LinkedListIterator implements Iterator<T> {
private Node current = first;
public T next() {
if (!hasNext()) { throw new NoSuchElementException(); }
T item = current.data;
current = current.next;
return item;
}
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
}
#Override public String toString() {
StringBuilder s = new StringBuilder();
for (T item : this)
s.append(item + " ");
return s.toString();
}
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
while(!StdIn.isEmpty()) {
String input = StdIn.readString();
if (input.equals("print")) { StdOut.println(list.toString()); continue; }
if (input.charAt(0) == ('+')) { list.add(input.substring(1)); continue; }
if (input.charAt(0) == ('-')) { list.remove(input.substring(1)); continue; }
break;
}
}
}
For more LinkedList examples, your can check out the article.