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

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;
}

Related

Iterating through a linked list using recursion gives me a run time error (stack overflow) on LeetCode

I am new to programming and today I wanted to try out the LeetCode problem 234. Palindrome Linked List:
Given the head of a singly linked list, return true if it is a palindrome or false otherwise.
Example 1:
Input: head = [1,2,2,1]
Output: true
but I couldn't even manage the first problem.
I first tried to convert the linked list to a string and compare like:
String[i] == String[length-i-1]
which worked for small lists but not for the gigantic test list where I got:
Time Limit Exceeded
In my second attempt I used recursion like this:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode? next;
* ListNode([this.val = 0, this.next]);
* }
*/
class Solution {
bool isPalindrome(ListNode? head) {
ListNode? current = head;
while(current?.next != null)
current = current?.next;
if (current?.val != head?.val)
return false;
else{
current = null;
isPalindrome(head?.next);
}
return true;
}
}
This also works with small lists, but for the test list I get a run time error:
Stack overflow
I wonder where this issue comes from.
Is it due to the maximum number of nested calls? And where can I find the recursion depth of Dart?
Or is there just a way simpler solution for this?
There are several issues with your attempt:
current = null will only set that variable to null. It does not affect the list. If you want to remove the last element from the list, you'll need access to the node that precedes it, and set its next property to null.
The boolean that the recursive call returns is always ignore. Instead execution continues with the return true statement, which will lead to incorrect results (when false was expected).
Before mentioning another problem, here is the correction for your algorithm:
bool isPalindrome(ListNode? head) {
ListNode? current = head;
ListNode? prev = null;
while(current?.next != null) {
prev = current; // follow behind current
current = current?.next;
}
if (current?.val != head?.val)
return false;
else if (prev == null)
return true; // List has only one node
else {
prev?.next = null; // Detach the tail node
return isPalindrome(head?.next); // Return the recursive result!
}
}
This will do the job correctly, but it is too slow. At every level of recursion almost all of the same nodes are iterated again (with that while loop), so for a list with 100 nodes, there are 100+98+96+94+...+2 iterations. In other words, the time complexity of this algorithm is quadratic. You'll need a different idea for the algorithm.
One idea for an efficient algorithm that doesn't require extra O(n) space, is to:
find the middle node of the list. You can for instance first determine the length of the list with a first iteration, and then in a second iteration you can stop half way.
reverse the second half of the list, giving you two shorter lists. Here you could use recursion if you wanted to.
and then compare those two lists node by node.
There are several Q&A on this algorithm, also on this site, so I'll leave that for your further research.
If you cannot make it work, here is a solution (spoiler!):
class Solution {
int listSize(ListNode? head) {
int size = 0;
while(head?.next != null) {
head = head?.next;
size++;
}
return size;
}
ListNode? nodeAt(ListNode? head, int index) {
while(head?.next != null && index > 0) {
head = head?.next;
index--;
}
return index == 0 ? head : null;
}
ListNode? reverse(ListNode? head) {
ListNode? prev = null;
ListNode? next;
while (head != null) {
next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
bool isEqual(ListNode? head1, ListNode? head2) {
// Only compares the nodes that both lists have:
while (head1 != null && head2 != null) {
if (head1.val != head2.val) return false;
head1 = head1.next;
head2 = head2.next;
}
return true;
}
bool isPalindrome(ListNode? head) {
return isEqual(head, reverse(nodeAt(head, listSize(head) >> 1)));
}
}
I can't quite understand your recursion solution without pointers. I solved it using a list. It is not the best solution but is simple.
// Definition for singly-linked list.
// class ListNode {
// int val;
// ListNode? next;
// ListNode([this.val = 0, this.next]);
// }
class Solution {
bool isPalindrome(ListNode? head) {
List<int> stack = [];
ListNode? p = head;
while (p != null) {
stack.add(p.val);
p = p.next;
}
print(stack);
bool isP = true;
while(head!.next!=null&&isP){
var a = stack.removeLast();
print('removed $a');
print('head val ${head.val}');
isP = head.val==a;
head=head.next!;
}
return isP;
}
}
The problem with your solution is
After a while loop current is rightmost node in the list
while (current?.next != null) {
current = current?.next;
}
comparing leftmost and rightmost node of LinkedList
if (current?.val != head?.val)
return false;
Start over with head shifted one place to the right
else {
current = null;
isPalindrome(head?.next);
}
But current is still rightmost node after a while loop
while (current?.next != null) {
current = current?.next;
}
And this will return false
if (current?.val != head?.val)
{
return false;
}
After second recursion program exits returning true

Facing a problem while reversing a linked list

I am trying to reverse linked list using java and written below code.
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur=head,prev=null,newHead=null;
while(cur!=null)
{
newHead=cur;
newHead.next=prev;
prev=newHead;
System.out.println(1);
cur=cur.next;
}
return newHead;
}
}
I am not understanding why the loop is executed only once here. Am i doing something wrong?
This happens because you have altered cur.next with the assignment newHead.next=prev;, making it null. Realise that newHead references the same object as cur at that moment.
You should save the original value of cur.next before this change happens:
ListNode cur = head, prev = null, newHead = null, next;
while (cur != null)
{
newHead = cur;
next = cur.next; // <--- save original value of `cur.next`
newHead.next = prev;
prev = newHead;
cur = next; // <--- use that original value here
}

Adding a node to linked list

I have written my first datastructures code in C and I am baffled as to what I am doing wrong. I am just trying to add a node to the front of the linked list or to an empty linked list and print the list at the end and it is resulting in segmentation fault.
#include<stdio.h>
#include<stddef.h>
#include<cstdlib>
/* Node representing each node of the linked list */
struct Node {
int data;
struct Node *next;
};
/* Fist node is always null as there are no nodes in the linked list to begin with */
struct Node *first = NULL;
void add_node(int data) {
struct Node *newptr = (Node *)malloc(sizeof(Node));
// Check if the list is empty
if (first == NULL){
printf("The list is empty\n");
newptr->data = data;
newptr->next = NULL;
first = newptr;
}
else {
printf("Adding to the existing list\n");
printf("Data in the first node is %d",first->data);
}
}
void display() {
struct Node *ptr;
printf("In the display function\n");
ptr = first;
do {
printf("Printing the data in the node %d",ptr->data);
ptr= ptr->next;
}while(ptr->next != NULL);
}
int main() {
/*
* Just try and add one node
*/
int y = 100;
printf("Adding a node \n");
add_node(y);
display();
return 1;
}
I messed up the display function, I changed it a bit to have the correct output.
The following is the new display function:
void display(struct Node *first) {
struct Node *ptr;
printf("In the display function\n");
ptr = first;
do {
printf("Printing the data in the node %d",ptr->data);
ptr= ptr->next;
}while(ptr != NULL);
}

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".

Linked List and Double 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.

Resources