Linked List and Double Linked List? - linked-list

I have been given a university assignment to adjust a single linked list to create a double linked list.
I am having trouble understanding a part of the code.
The bit I am having problems with is the method "insert(object o, int index)"
My problem is related to:
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
I dont understand how it knows what nodePointer.next is in the line "nodePointer = nodePointer.next;
I cant see any point where it defines how to handle the .next bit.
How does it know what this is?
I do undestand that it is referencing the next node, but am not clear exactly what this line is saying
The whole code is posted below
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
/**
* <dl>
* <dt>Purpose: Implementation of Sequence ADT.
* <dd>
*
* <dt>Description:
* <dd>This class is an implementation of the Sequence using an linked list as
* the underlying data structure. The capacity is therefore unlimited and
* overflow does not need to be checked.
* </dl>
*
* #author Danny Alexander
* #version $Date: 2000/01/08
*/
public class SequenceList {
/**
* Member class Node encapsulates the nodes of the linked list in
* which the stack is stored. Each node contains a data item and a
* reference to another node - the next in the linked list.
*/
protected class Node {
public Node(Object o) {
this(o, null);
}
public Node(Object o, Node n) {
datum = o;
next = n;
}
//The Node data structure consists of two object references.
//One for the datum contained in the node and the other for
//the next node in the list.
protected Object datum;
protected Node next;
}
//We use object references to the head and tail of the list (the head
//and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
//Only require a single constructor, which sets both object
//references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList() {
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
if (index == 0) {
listHead = new Node(o, listHead);
listTail = listHead;
} else {
throw new SequenceListException("Indexed element is out of range");
}
}
//There is another special case for insertion at the head of
//the sequence.
else if (index == 0) {
listHead = new Node(o, listHead);
}
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
//Finally we need to check that the tail pointer is
//correct. Another special case occurs if the new
//node was inserted at the end, in which case, we need
//to update the tail pointer.
if (nodePointer == listTail) {
listTail = listTail.next;
}
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we just unlink the first node of the
//list.
else {
listHead = listHead.next;
}
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we need to chain all the way down the
//list in order to reset the link of the second to last
//element to null.
else {
Node nodePointer = listHead;
while (nodePointer.next != listTail) {
nodePointer = nodePointer.next;
}
//Unlink the last node and reset the tail pointer.
nodePointer.next = null;
listTail = nodePointer;
}
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
if (index == 0) {
listHead = null;
listTail = null;
} else {
throw new SequenceListException("Indexed element is out of range.");
}
}
//There is also a special case when the first element has to
//be removed.
else if (index == 0) {
deleteFirst();
}
//In the general case, we need to chain down the list to find
//the node in the indexed position.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Unlink the node and reset the tail pointer if that
//node was the last one.
if (nodePointer.next == listTail) {
listTail = nodePointer;
}
nodePointer.next = nodePointer.next.next;
}
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException {
if (listHead != null) {
return listHead.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException {
if (listTail != null) {
return listTail.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//We need to chain down the list until we reach the indexed
//position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
} else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty() {
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size() {
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while (nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear() {
listHead = null;
listTail = null;
}
}

The code you posted lays out several different methods for making insertions into the linked-list.
protected class Node {
public Node(Object o) {
this(o, null);
}
public Node(Object o, Node n) {
datum = o;
next = n; // when creating a Node you have a next attribute associated with each one
}
If this were a double linked list there would be a prev attribute also associated with every Node object. I believe you're saying you are clear on this part.
When just starting out constructing the linked-list, there are two Nodes here that are added by default:
public SequenceList() {
listHead = null;
listTail = null;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
This is the starting point that is needed, so when one of the insert methods are called:
public void insertLast(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
Here you are going to pass insertLast a Node object. If this Node isn't Null in this method, it will create a new tail by adding the new Node as listTail's next member. Then assigning listTails next as the new "Tail".
In this way you're keeping track of the head and the tail. Everytime a new Node is wanted to be added, it becomes the new tail.
You could then go through your list by passing in your head and in either a while-loop or a recursive function that keeps calling on the Nodes next attribute referencing the next item in the list, until you come to Null or you find what it is you were looking for.

Related

I'm getting into infinite while loop (linked lists c)

I'm stuck in a while loop (the one that prints "no" ):
#include<stdlib.h>
#include<stdio.h>
typedef struct bill {
int value;
struct bill *next;
} list;
void printlist(list *head) {
list *temp = head;
while (temp != NULL)
printf("%d ",temp->value), temp = temp->next;
}
void insert_at_end(list *head, int value) {
list *current, *first;
first = malloc(sizeof(list));
if (head == NULL)
head = first;
else {
current = head;
while (current->next != NULL) {
current = current->next;
printf("no");
}
}
}
void main() {
list *head = NULL;
head = malloc(sizeof(list));
for (int i = 0; i < 10; i++)
insert_at_end(head, i);
printlist(head);
}
I'm not sure why, but current never gets to NULL. I watched numerous videos and they all do the same:
while (current != NULL)
current = current->next
...which should just get to NULL at one point, but it doesn't in my case.
There are these issues:
When you do head = malloc(sizeof(list)), the members of that node are still undefined, including its next member. As a consequence, when you get into the else block in the insert_at_end function, the loop will access this undefined next pointer and bring about undefined behaviour.
Similar to the previous problem, also first does not get initialised with a value and a next member.
In the else block in the insert_at_end function there is no code that attaches the new node to the list.
In the if block in the insert_at_end function, the value of head is altered. But this just changes the value of a local variable -- the caller will not see this change. For that to happen you should alter the function parameter so that it is a pointer to the head pointer.
The creation of a head node in the main program seems unwaranted -- you should start with an empty list, i.e. with head equal to NULL.
void main is not correct. It should be int main, and the appropriate value should be returned by it.
Here is the correction to the two functions that have issues:
// This function accepts a pointer to a head-pointer, so the head-pointer
// can be changed and the caller will receive that change.
void insert_at_end(list **head, int value){
list *current, *first;
first = malloc(sizeof(list));
first->value = value; // This was missing
first->next = NULL; // This was missing
if (*head == NULL) {
*head = first;
} else {
current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = first; // This was missing
}
}
// The main method has an int return type
int main() {
list *head = NULL;
// Do not create a node here.
for (int i = 0; i < 10; i++) {
insert_at_end(&head, i); // pass pointer to head-pointer
}
printlist(head);
return 0;
}

Java - Writing method for public int indexOf(T element) in a double linked list

Below I have the int indexOf(T element) method for a double linked list. I need help with the code to make sure it functions properly. The method should return the first occurence of the element in the list or -1 if element is not in the list. Below is the node class it uses. The IUDoubleLinkedList.java class implements IndexedUnsortedList.java which is where the indexOf method comes from. I tried using my indexOf method from my single linked list class but it's not the same so I hope to understand why it would be different and what code is used that is different between the the single and double linked list.
public class IUDoubleLinkedList<T> implements IndexedUnsortedList<T> {
private Node<T> head, tail;
private int size;
private int modCount;
public IUDoubleLinkedList() {
head = tail = null;
size = 0;
modCount = 0;
This is the indexOf(T element) method
#Override
public int indexOf(T element) {
// TODO Auto-generated method stub
return 0;
}
Below is the Node.java class it uses
public class Node<T> {
private Node<T> nextNode;
private T element;
private Node<T> prevNode;
/**
* Creates an empty node.
*/
public Node() {
nextNode = null;
element = null;
}
/**
* Creates a node storing the specified element.
*
* #param elem
* the element to be stored within the new node
*/
public Node(T element) {
nextNode = null;
this.element = element;
setPrevNode(null);
}
/**
* Returns the node that follows this one.
*
* #return the node that follows the current one
*/
public Node<T> getNextNode() {
return nextNode;
}
/**
* Sets the node that follows this one.
*
* #param node
* the node to be set to follow the current one
*/
public void setNextNode(Node<T> nextNode) {
this.nextNode = nextNode;
}
/**
* Returns the element stored in this node.
*
* #return the element stored in this node
*/
public T getElement() {
return element;
}
/**
* Sets the element stored in this node.
*
* #param elem
* the element to be stored in this node
*/
public void setElement(T element) {
this.element = element;
}
#Override
public String toString() {
return "Element: " + element.toString() + " Has next: " + (nextNode != null);
}
public Node<T> getPrevNode() {
return prevNode;
}
public void setPrevNode(Node<T> prevNode) {
this.prevNode = prevNode;
}
}
Check the following code, hope I helped you!
Insert item at head as well as tail end
public void insertItem(T elem) {
/* if head and tail both are null*/
if(head == null || tail == null) {
head = new Node<T>(elem);
tail = new Node<T>(elem);
}else {
Node<T> tempItem = new Node<T>();
tempItem.setElement(elem);
/* insert at head end /*
tempItem.setNextNode(head);
head.setPrevNode(tempItem);
head = tempItem;
Node<T> tempItem1 = new Node<T>();
tempItem1.setElement(elem);
/* append at tail end */
tail.setNextNode(tempItem1);
tempItem1.setPrevNode(tail);
tail = tempItem1;
}
size += 1;
}
Print item from head end
public void printItemsFromHead() {
while(head != null) {
System.out.print(head.getElement()+" --> ");
head = head.getNextNode();
}
}
Print item from tail end
public void printItemsFromTail() {
Node<T> temp = null;
while(tail != null) {
temp = tail;
System.out.print(tail.getElement()+" --> ");
tail = tail.getPrevNode();
}
/*System.out.println();
while(temp != null) {
System.out.print(temp.getElement()+" --> ");
temp = temp.getNextNode();
}*/
}
Implemention of indexOf function
#Override
public int indexOf(T element) {
int result = -1;
int headIndex = 0;
int tailIndex = size;
while(head != null && tail != null) {
if(head.getElement().equals(element)) {
result = headIndex;
break;
}
/*
if(tail.getElement().equals(element)) {
result = tailIndex;
break;
} */
head = head.getNextNode();
tail = tail.getPrevNode();
headIndex += 1;
tailIndex -= 1;
}
return result;
}
Driver class
public class Driver {
#SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> void main(String[] args) {
UDoubleLinkedList uDoubleLinkedList = new UDoubleLinkedList();
uDoubleLinkedList.insertItem(1);
uDoubleLinkedList.insertItem(2);
uDoubleLinkedList.insertItem(3);
uDoubleLinkedList.insertItem(4);
uDoubleLinkedList.insertItem(5);
System.out.println(uDoubleLinkedList.indexOf(1));
}
}

I have no idea why i have error Exception in thread "main" java.lang.NullPointerException

I tried to use reverseBystack, reverseBylink and remove.. but I don't know why when i use these functions, it has error like this.
Exception in thread "main" java.lang.NullPointerException
at LinkedQueue$Node.access$200(LinkedQueue.java:44)
at LinkedQueue.reverseBylink(LinkedQueue.java:185)
at LinkedQueue.main(LinkedQueue.java:238)
void reverseByStack() - This method reverses the order of the items in the linked list (first
becomes last and last becomes first) using a stack data strucenter code hereture`
• void reverseByLinks() - This method also reverses the order of the items in the linked list.
It should not create a new list or use a stack. It should only reverse the order of the nodes by
modifying the next values for each node in the list.
• int remove(Item item) - This method scans the queue for occurrences of item and removes
them from the queue. It returns the number of items deleted from the queue.
these are what i want to make.
enter code here public class LinkedQueue<Item> implements Iterable<Item> {
private int N; // number of elements on queue
private Node first; // beginning of queue
private Node last; // end of queue
// helper linked list class
private class Node {
private Item item;
private Node next;
}
public LinkedQueue() {
first = null;
last = null;
N = 0;
assert check();
}
public boolean isEmpty() {
return first == null;
}
public int size() {
return N;
}
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue
underflow");
return first.item;
}
public void enqueue(Item item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
N++;
assert check();
}
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue
underflow");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null; // to avoid loitering
assert check();
return item;
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
private boolean check() {
if (N == 0) {
if (first != null) return false;
if (last != null) return false;
}
else if (N == 1) {
if (first == null || last == null) return false;
if (first != last) return false;
if (first.next != null) return false;
}
else {
if (first == last) return false;
if (first.next == null) return false;
if (last.next != null) return false;
// check internal consistency of instance variable N
int numberOfNodes = 0;
for (Node x = first; x != null; x = x.next) {
numberOfNodes++;
}
if (numberOfNodes != N) return false;
// check internal consistency of instance variable last
Node lastNode = first;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
if (last != lastNode) return false;
}
return true;
}
void reverseBystack(){
Stack<Item> s = new Stack<>();
Item item;
while (s.isEmpty() != true){
item = dequeue();
s.push(item);
}
while(s.isEmpty() != true){
item = s.pop();
enqueue(item);
}
}
void reverseBylink() {
Node prev = null;
Node current = this.first;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
prev.next = current.next;
}
int remove(Item item){
Node cur = first;
Node prev = last;
while(cur != null) {
if(cur.item.equals(item))
System.out.println(cur.item);
}
cur = cur.next;
prev = cur.next;
return 0;
}
public Iterator<Item> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() { return current != null;
}
public void remove() { throw new
UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
/**
* Unit tests the <tt>LinkedQueue</tt> data type.
*/
public static void main(String[] args) {
LinkedQueue<String> q = new LinkedQueue<String>();
while (!StdIn.isEmpty()) {
String item = StdIn.readString();
if (!item.equals("-")) q.reverseBylink();
else if (!q.isEmpty()) StdOut.print(q.dequeue() + " ");
}
StdOut.println("(" + q.size() + " left on queue)");
}
}

Doubly linked list java remove

I have a problem when deleting many nodes.
I can delete them if I select nodes like this:
But if I do something like this, I cannot delete them:
My Code:
public boolean remove(ProductNode<E> data) {
if (isEmpty()) {
throw new NoSuchElementException();
}
for (ProductNode<E> current = this.head; current != null; current = current.next) {
ProductNode<E> pre = current.prev;
ProductNode<E> next = current.next;
if (data != null) {
if (current.data.equals(data.data)) {
if (pre == null) {
head = next;
current.next = null;
} else {
if (next != null) {
next.prev = pre;
}
}
if (next == null) {
pre.next = null;
current.prev = null;
tail = pre;
} else {
if (pre != null) {
pre.next = next;
}
}
}
}
}
size--;
return false;
}
Search node
public ProductNode<E> search(E data) {
for (ProductNode<E> current = this.head; current != null; current = current.next) {
if (current.data.equals(data)) {
return current;
}
}
return null;
}
Remove
public void remove(E e) {
remove(search(e));
}
Delete:
for(Tab_Product p : remove_list){
List_Products.list_products.remove(p);
}
Your remove function (ProductNode data), is a bit complicated and may be affecting your code's ability to delete multiple nodes. In the case of this remove function you do not need traverse the whole data set. If you already have a reference to the node you can just directly modify the list with it.
public boolean remove(ProductNode<E> data) {
if (isEmpty()) {
throw new NoSuchElementException();
}
ProductNode<E> pre = data.prev;
ProductNode<E> next = data.next;
//First remove the nodes references to its neighbors.
data.prev = null;
data.next = null;
// Now check the neighbors and update their references
// to remove all references to the deleted node.
if (pre != null) pre.next = next;
if (next != null) next.prev = pre;
if (data == head) { //This checks the actual memory address.
head = next;
}
size--;
}
Since you already have the ProductNode, you do not need to search the list. your search() function is already doing that for you. since you already have the node you just need to make its references to its neighbors null then you just have to access the neighbors (if there are any) and make their old references skip over the deleted node.
I noticed a few reference errors where a deleted node was not getting completely removed from the list but i will not mention them because this delete function is rather complicated. Try simplifying the delete function and then see what your results are.
It also might be helpful if you show us the structure of the List_Products object.
Additionally you should verify that the data you select in the UI is getting passed correctly. This could be a UI bug.

Linked List and Double Linked List

As part of my university work I need to understand the linked list code I have been given.
I am having problems with the insert method-the part that deals with the general case-as with the code below:
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
The problem I am having is that I can see the method inserts the node and makes it point to the next node, but what about the node it replaced. As far as I can see there has been no change to the node it replaced, meaning that there are now 2 nodes pointing to the same next.node.
Am I mis understanding this, or is this what happens? If so, this does not seem logical to me as there ae now 2 nodes pointing to a single node.
If this is not the case, at what point in the code does it change the pointer for the previous node
The whole code is below:
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
/**
* <dl>
* <dt>Purpose: Implementation of Sequence ADT.
* <dd>
*
* <dt>Description:
* <dd>This class is an implementation of the Sequence using an linked list as
* the underlying data structure. The capacity is therefore unlimited and
* overflow does not need to be checked.
* </dl>
*
* #author Danny Alexander
* #version $Date: 2000/01/08
*/
public class SequenceList {
/**
* Member class Node encapsulates the nodes of the linked list in
* which the stack is stored. Each node contains a data item and a
* reference to another node - the next in the linked list.
*/
protected class Node {
public Node(Object o) {
this(o, null);
}
public Node(Object o, Node n) {
datum = o;
next = n;
}
//The Node data structure consists of two object references.
//One for the datum contained in the node and the other for
//the next node in the list.
protected Object datum;
protected Node next;
}
//We use object references to the head and tail of the list (the head
//and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
//Only require a single constructor, which sets both object
//references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList() {
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o) {
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if (listHead == null) {
if (index == 0) {
listHead = new Node(o, listHead);
listTail = listHead;
} else {
throw new SequenceListException("Indexed element is out of range");
}
}
//There is another special case for insertion at the head of
//the sequence.
else if (index == 0) {
listHead = new Node(o, listHead);
}
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
//Finally we need to check that the tail pointer is
//correct. Another special case occurs if the new
//node was inserted at the end, in which case, we need
//to update the tail pointer.
if (nodePointer == listTail) {
listTail = listTail.next;
}
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we just unlink the first node of the
//list.
else {
listHead = listHead.next;
}
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we need to chain all the way down the
//list in order to reset the link of the second to last
//element to null.
else {
Node nodePointer = listHead;
while (nodePointer.next != listTail) {
nodePointer = nodePointer.next;
}
//Unlink the last node and reset the tail pointer.
nodePointer.next = null;
listTail = nodePointer;
}
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException {
//Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
if (index == 0) {
listHead = null;
listTail = null;
} else {
throw new SequenceListException("Indexed element is out of range.");
}
}
//There is also a special case when the first element has to
//be removed.
else if (index == 0) {
deleteFirst();
}
//In the general case, we need to chain down the list to find
//the node in the indexed position.
else {
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Unlink the node and reset the tail pointer if that
//node was the last one.
if (nodePointer.next == listTail) {
listTail = nodePointer;
}
nodePointer.next = nodePointer.next.next;
}
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException {
if (listHead != null) {
return listHead.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException {
if (listTail != null) {
return listTail.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException {
//Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//We need to chain down the list until we reach the indexed
//position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
} else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty() {
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size() {
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while (nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear() {
listHead = null;
listTail = null;
}
}
This line of code takes care of both creating the new node, pointing it to the next link, and making the previous node point to the new node:
nodePointer.next = new Node(o, nodePointer.next);
First, new Node(o, nodePointer.next) creates a new node and point it to the next node in line. The reference to the newly created node is then assigned to nodePointer.next.
To clarify, you asked:
"As far as I can see there has been no change to the node it replaced"
nodePointer is a reference to the node directly before the index, so nodePointer.next is the node that is being "replaced".

Resources