You are on page 1of 47

DSA with Java/Unit-2

Unit 2: Linked List


An array is a very useful data structure provided in programming languages. However, it has at
least two limitations:
(1) changing the size of the array requires creating a new array and then copying all data
from the array with the old size to the array with the new size and
(2) the data in the array are next to each other sequentially in memory, which means that
inserting an item inside the array requires shifting some other data in this array.
This limitation can be overcome by using linked structures.
A linked structure is a collection of nodes storing data and links to other nodes. In this way, nodes
can be located anywhere in memory, and passing from one node of the linked structure to another
is accomplished by storing the reference(s) to other node(s) in the structure. Although linked
structures can be implemented in a variety of ways, the most flexible implementation is by using
a separate object for each node.

Figure 1: Linked List

 A linked list is a linear data structure where each element is a separate object. Each element
(we will call it a node) of a list is comprising of two items - the data and a reference to the
next node. The last node has a reference to null. The entry point into a linked list is called
the head of the list. It should be noted that head is not a separate node, but the reference to the
first node. If the list is empty then the head is a null reference.
 A linked list is a dynamic data structure. The number of nodes in a list is not fixed and can
grow and shrink on demand. Any application which has to deal with an unknown number of
objects will need to use a linked list.
 One disadvantage of a linked list against an array is that it does not allow direct access to the
individual elements. If you want to access a particular item then you have to start at the head
and follow the references until you get to that item.
 Another disadvantage is that a linked list uses more memory compare with an array

1
Collected by Bipin Timalsina
DSA with Java/Unit-2

 A linked list is a data structure used for storing collections of data. A linked list has the
following properties.
 Successive elements are connected by pointers
 The last element points to NULL
 Can grow or shrink in size during execution of a program
 Can be made just as long as required (until systems memory exhausts)

Singly Linked Lists


If a node contains a data field that is a reference to another node, then many nodes can be strung
together using only one variable to access the entire sequence of nodes. Such a sequence of nodes
is the most frequently used implementation of a linked list, which is a data structure composed of
nodes, each node holding some information and a reference to another node in the list. If a node
has a link only to its successor in this sequence, the list is called a singly linked list.

Figure 2: Singly Linked List


1. Singly Linked List is a linear data structure which consist of nodes, each node holds some
data and reference to another node and the link of a node is only to the successor in this
sequence.
 A singly linked list is a linked list where each node is an object that stores a reference to
an element and a reference, called next, to another node.
 The next reference inside a node can be viewed as a link or pointer to another node.
 The first and last node of a linked list usually are called the head and tail of the list,
respectively. The head is a reference to the first node. The tail node is a special node,
where the next pointer is always pointing or linking to a null reference, indicating the end
of the list.

2
Collected by Bipin Timalsina
DSA with Java/Unit-2

In Java, singly linked list can be represented as a class and a Node as a separate class. The
SingLinkedList class contains a reference of Node class type.
//node structure
class Node {
int data;
Node next;
}
class SingLinkedList {
Node head;
//constructor to create an empty SingLinkedList
SingLinkedList(){
head = null;
}
}

Insertion
Insertion into a singly linked list has three cases:
 Inserting a new node before the head (at the beginning)
 Inserting a new node after the tail (at the end of the list)
 Inserting a new node at the middle of the list (random location)
Note: To insert an element in the linked list at some position p, assume that after inserting the
element the position of this new node is p.

3
Collected by Bipin Timalsina
DSA with Java/Unit-2

Inserting a Node in Singly Linked List at the Beginning


In this case, a new node is inserted before the current head node. Only one next pointer needs to
be modified (new node’s next pointer) and it can be done in two steps:

1. Update the next pointer of new node, to point to the current head

2. Update head pointer to point to the new node.

Following method in Java can insert new node to beginning of Singly Linked List
void insertAtBegining(int newElement) {
//1. allocate a new node
Node newNode = new Node();
//2. assign data element
newNode.data = newElement;
//3. make next node of new node as head
newNode.next = head;
//4. make new node as head
head = newNode;
}

4
Collected by Bipin Timalsina
DSA with Java/Unit-2

Inserting a Node in Singly Linked List at the Ending


In this case, we need to modify two next pointers (last nodes next pointer and new nodes next
pointer).

1. New node’s next pointer points to NULL.

2. Last node’s next pointer points to the new node.

Following method in Java can insert a node at ending of Singly Linked List

void insertAtEnding(int newElement) {

//1. allocate node


Node newNode = new Node();
//2. assign data element
newNode.data = newElement;
//3. assign null to the next of new node
newNode.next = null;

5
Collected by Bipin Timalsina
DSA with Java/Unit-2

//4. Check the Linked List is empty or not,


// if empty make the new node as head
if(head == null) {
head = newNode;
} else {
//5. Else, traverse to the last node
Node temp = new Node();
temp = head;
while(temp.next != null)
temp = temp.next;
//6. Change the next of last node to new node
temp.next = newNode;
}
}
Inserting a Node in Singly Linked List at the Middle (given position)
Let us assume that we are given a position where we want to insert the new node. In this case
also, we need to modify two next pointers.
1. If we want to add an element at position 3 then we stop at position 2. That means we
traverse 2 nodes and insert the new node. For simplicity let us assume that the second node
is called position node. The new node points to the next node of the position where we
want to add this node.

2. Position node’s next pointer now points to the new node.


6
Collected by Bipin Timalsina
DSA with Java/Unit-2

Time Complexity: O(n), since, in the worst case, we may need to insert the node at the end of the
list.
Space Complexity: O(1), for creating one temporary variable.

Following method in Java can insert a node at given position in Singly Linked List
void insertAtPosition(int newElement, int position) {

//1. allocate node to new element


Node newNode = new Node();
newNode.data = newElement;
newNode.next = null;

//2. check if the position is > 0


if(position < 1) {
System.out.print("\nposition should be >= 1.");
} else if (position == 1) {

//3. if the position is 1, make next of the


// new node as head and new node as head
newNode.next = head;
head = newNode;
} else {

7
Collected by Bipin Timalsina
DSA with Java/Unit-2

//4. Else, make a temp node and traverse to the


// node previous to the position
Node temp = new Node();
temp = head;
for(int i = 1; i < position-1; i++) {
if(temp != null) {
temp = temp.next;
}
}
//5. If the previous node is not null, make
// newNode next as temp next and temp next
// as newNode.
if(temp != null) {
newNode.next = temp.next;
temp.next = newNode;
} else {

//6. When the previous node is null


System.out.print("\nThe previous node is null.");
}
}
}

8
Collected by Bipin Timalsina
DSA with Java/Unit-2

Deletion
Similar to insertion, here we also have three cases.
 Deleting the first node
 Deleting the last node
 Deleting an intermediate node.
Deleting the First Node in Singly Linked List
First node (current head node) is removed from the list. It can be done in two steps:
1. Create a temporary node which will point to the same node as that of head.

2. Now, move the head nodes pointer to the next node and dispose of the temporary node.

Following method in Java can delete the first node in Singly Linked List:
void delFirst() {
if(this.head != null) {

//1. if head is not null, create a


// temp node pointing to head
Node temp = this.head;

//2. move head to next of head


this.head = this.head.next;

9
Collected by Bipin Timalsina
DSA with Java/Unit-2

//3. delete temp node


temp = null;
}
}
Deleting the Last node in Singly Linked List
In this case, the last node is removed from the list. This operation is a bit trickier than removing
the first node, because the algorithm should find a node, which is previous to the tail. It can be
done in three steps:
1. Traverse the list and while traversing maintain the previous node address also. By the
time we reach the end of the list, we will have two pointers, one pointing to the tail
node and the other pointing to the node before the tail node.

2. Update previous node’s next pointer with NULL.

3. Dispose of the tail node.

10
Collected by Bipin Timalsina
DSA with Java/Unit-2

Following method in Java can delete the last node in singly Linked List
void delLast() {
if(this.head != null) {
//1. if head in not null and next of head
// is null, release the head
if(this.head.next == null) {
this.head = null;
} else {
//2. Else, traverse to the second last
// element of the list
Node temp = new Node();
temp = this.head;
while(temp.next.next != null)
temp = temp.next;

//3. Change the next of the second


// last node to null and delete the last node
Node secondLastNode=temp;
Node lastNode = secondLastNode.next;
secondLastNode.next = null;//secondLastNode is now last node
lastNode = null; //delete
}
}
}

11
Collected by Bipin Timalsina
DSA with Java/Unit-2

Deleting an Intermediate Node in Singly Linked List


In this case, the node to be removed is always located between two nodes. Head and tail links
are not updated in this case. Such a removal can be done in two steps:
1. Similar to the previous case, maintain the previous node while traversing the list. Once
we find the node to be deleted, change the previous node’s next pointer to the next
pointer of the node to be deleted.

2. Dispose of the current node to be deleted.

Time Complexity: O(n). In the worst case, we may need to delete the node at the end of the list.
Space Complexity: O(1). Since, we are creating only one temporary variable.

Following method in Java can delete the node at given position in Singly Linked List:

12
Collected by Bipin Timalsina
DSA with Java/Unit-2

void delAtPosition(int position) {


//1. check if the position is > 0
if(position < 1) {
System.out.print("\nposition should be >= 1.");
} else if (position == 1 && head != null) {
//2. if the position is 1 and head is not null, make
// head next as head and delete previous head
Node nodeToDelete = head;
head = head.next;
nodeToDelete = null;
} else {
//3. Else, make a temp node and traverse to the
// node previous to the position
Node temp = new Node();
temp = head;
for(int i = 1; i < position-1; i++) {
if(temp != null) {
temp = temp.next;
}
}
//4. If the previous node and next of the previous
// is not null, adjust links
if(temp != null && temp.next != null) {
Node nodeToDelete = temp.next;
temp.next = temp.next.next;
nodeToDelete = null;
} else {
//5. Else the given node will be empty.
System.out.print("\nThe node is already null.");
}
}
}

13
Collected by Bipin Timalsina
DSA with Java/Unit-2

Search
The insertion and deletion operations modify linked lists. The searching operation scans an
existing list to learn whether an element is in it. To search any value in the singly linked list, we
can traverse the linked list and compares the value present in the node.
boolean searchSLL(Node head, int val)
{
// creating a temp variable pointing to the head of the linked list
Node temp = head
while( temp != NULL) // traversing the list
{
if( temp.data == val )
return true
temp = temp.next
}
return false
}

Doubly Linked List


The linked list which a node contains data item and two pointers pointing to next and previous
nodes is called Doubly Linked list.

Figure 3: Doubly Linked List

The advantage of a doubly linked list (also called two – way linked list) is that given a node in
the list, we can navigate in both directions. A node in a singly linked list cannot be removed unless
we have the pointer to its predecessor. But in a doubly linked list, we can delete a node even if we

14
Collected by Bipin Timalsina
DSA with Java/Unit-2

don’t have the previous node’s address (since each node has a left pointer pointing to the previous
node and can move backward).
The primary disadvantages of doubly linked lists are:
o Each node requires an extra pointer, requiring more space.
o The insertion or deletion of a node takes a bit longer (more pointer operations).

In Java, doubly linked list can be represented as a class and a Node as a separate class. The
DoubLinkedList class contains a reference of Node class type.
//node structure
class Node {
int data;
Node next;
Node prev;
}

class DoubLinkedList {
Node head;
//constructor to create an empty DoubLinkedList
DoubLinkedList(){
head = null;
}
}
Doubly Linked List Insertion
Insertion into a doubly-linked list has three cases (same as a singly linked list).
 Inserting a new node before the head.
 Inserting a new node after the tail (at the end of the list).
 Inserting a new node at the middle of the list.
Inserting a Node in Doubly Linked List at the Beginning
In this case, new node is inserted before the head node. Previous and next pointers need to be
modified and it can be done in two steps:

15
Collected by Bipin Timalsina
DSA with Java/Unit-2

1. Update the right pointer of the new node to point to the current head node (dotted link
in below figure) and also make left pointer of new node as NULL.

2. Update head node’s left pointer to point to the new node and make new node as head.

Note: Left pointer = Prev and Right Pointer = Next)

Following method in Java can insert new node to beginning of Doubly Linked List

void insertAtBegining(int newElement) {

//1. allocate node


Node newNode = new Node();

//2. assign data element


newNode.data = newElement;

//3. assign null to the next and prev


// of the new node
newNode.next = null;
newNode.prev = null;

16
Collected by Bipin Timalsina
DSA with Java/Unit-2

//4. Check the list is empty or not,


// if empty make the new node as head
if(head == null) {
head = newNode;
} else {

//5. Adjust the links and make the new


// node as head
head.prev = newNode;
newNode.next = head;
head = newNode;
}
}

Inserting a Node in Doubly Linked List at the Ending


In this case, traverse the list till the end and insert the new node.
1. New node’s right pointer points to NULL and left pointer points to the end of the list.

2. Update right pointer of last node to point to new node.

17
Collected by Bipin Timalsina
DSA with Java/Unit-2

Following method in Java can insert a node at ending of Doubly Linked List
void insertAtEnding(int newElement) {

//1. allocate node


Node newNode = new Node();

//2. assign data element


newNode.data = newElement;

//3. assign null to the next and prev


// of the new node
newNode.next = null;
newNode.prev = null;

//4. Check the list is empty or not,


// if empty make the new node as head
if(head == null) {
head = newNode;
} else {

//5. Else, traverse to the last node


Node temp = new Node();
temp = head;
while(temp.next != null)
temp = temp.next;

//6. Adjust the links


temp.next = newNode;
newNode.prev = temp;
}
}

18
Collected by Bipin Timalsina
DSA with Java/Unit-2

Inserting a Node in Doubly Linked List in the Middle( given position)


As discussed in singly linked lists, traverse the list to the position node and insert the new node.
1. New node right pointer points to the next node of the position node where we want to insert
the new node. Also, new node left pointer points to the position node.

2. Position node right pointer points to the new node and the next node of position node left
pointer points to new node.

Time Complexity: O(n). In the worst case, we may need to insert the node at the end of the list.
Space Complexity: O(1), for creating one temporary variable.

19
Collected by Bipin Timalsina
DSA with Java/Unit-2

Following method in Java can insert a node at given position in Doubly Linked List
void insertAtPosition(int newElement, int position) {

//1. allocate node to new element


Node newNode = new Node();
newNode.data = newElement;
newNode.next = null;
newNode.prev = null;

//2. check if the position is > 0


if(position < 1) {
System.out.print("\nposition should be >= 1.");
} else if (position == 1) {

//3. if the position is 1, make new node as head


newNode.next = head;
head.prev = newNode;
head = newNode;
} else {

//4. Else, make a temp node and traverse to the


// node previous to the position
Node temp = new Node();
temp = head;
for(int i = 1; i < position-1; i++) {
if(temp != null) {
temp = temp.next;
}
}

//5. If the previous node is not null, adjust


// the links

20
Collected by Bipin Timalsina
DSA with Java/Unit-2

if(temp != null) {
newNode.next = temp.next;
newNode.prev = temp;
temp.next = newNode;
if(newNode.next != null)
newNode.next.prev = newNode;
} else {

//6. When the previous node is null


System.out.print("\nThe previous node is null.");
}
}
}
Doubly Linked List Deletion
Similar to singly linked list deletion, here we have three cases:
1. Deleting the first node
2. Deleting the last node
3. Deleting an intermediate node
Deleting the First Node in Doubly Linked List
In this case, the first node (current head node) is removed from the list. It can be done in two
steps:
1. Create a temporary node which will point to the same node as that of head.

2. Now, move the head nodes pointer to the next node and change the heads left pointer to
NULL and dispose of the temporary node.

21
Collected by Bipin Timalsina
DSA with Java/Unit-2

Following method in Java can delete the first node in Doubly Linked List:

void delFirst() {
if(this.head != null) {

//1. if head is not null, create a


// temp node pointing to head
Node temp = this.head;

//2. move head to next of head


this.head = this.head.next;

//3. delete temp node


temp = null;

//4. If the new head is not null, then


// make prev of the new head as null
if(this.head != null)
this.head.prev = null;
}
}

22
Collected by Bipin Timalsina
DSA with Java/Unit-2

Deleting the Last Node in Doubly Linked List


This operation is a bit trickier than removing the first node, because the algorithm should find a
node, which is previous to the tail first. This can be done in three steps:
1. Traverse the list and while traversing maintain the previous node address also. By the time
we reach the end of the list, we will have two pointers, one pointing to the tail and the other
pointing to the node before the tail.

2. Update the next pointer of previous node to the tail node with NULL.

3. Dispose of the tail node.

23
Collected by Bipin Timalsina
DSA with Java/Unit-2

Following method in Java can delete the last node in Doubly Linked List

void delLast() {
if(this.head != null) {

//1. if head in not null and next of head


// is null, release the head
if(this.head.next == null) {
this.head = null;
} else {

//2. Else, traverse to the second last


// element of the list
Node temp = new Node();
temp = this.head;
while(temp.next.next != null)
temp = temp.next;

//3. Change the next of the second


// last node to null and delete the
// last node
Node lastNode = temp.next;
temp.next = null;
lastNode = null;
}
}
}

24
Collected by Bipin Timalsina
DSA with Java/Unit-2

Deleting an Intermediate Node in Doubly Linked List


In this case, the node to be removed is always located between two nodes, and the head and tail
links are not updated. The removal can be done in two steps:
1. Similar to the previous case, maintain the previous node while also traversing the list. Upon
locating the node to be deleted, change the previous node’s next pointer to the next node
of the node to be deleted.

2. Dispose of the current node to be deleted.

Time Complexity: O(n), for scanning the complete list of size n.


Space Complexity: O(1), for creating one temporary variable.

Following method in Java can delete the node at given position in Doubly Linked List:

25
Collected by Bipin Timalsina
DSA with Java/Unit-2

void delAtPosition(int position) {

//1. check if the position is > 0


if(position < 1) {
System.out.print("\nposition should be >= 1.");
} else if (position == 1 && head != null) {

//2. if the position is 1 and head is not null, make


// head next as head and delete previous head
Node nodeToDelete = head;
head = head.next;
nodeToDelete = null;
if (head != null)
head.prev = null;
} else {

//3. Else, make a temp node and traverse to the


// node previous to the position
Node temp = new Node();
temp = head;
for(int i = 1; i < position-1; i++) {
if(temp != null) {
temp = temp.next;
}
}

//4. If the previous node and next of the previous


// is not null, adjust links
if(temp != null && temp.next != null) {
Node nodeToDelete = temp.next;
Node nextNodeFromNodeToDelete = NodeToDelete.next
temp.next = nextNodeFromNodeToDelete;

26
Collected by Bipin Timalsina
DSA with Java/Unit-2

nodeToDelete = null;
nextNodeFromNodeToDelete.prev = temp;
} else {

//5. Else the given node will be empty.


System.out.print("\nThe node is already null.");
}
}
}

Circular Lists
 A circular singly linked list can be visualized as a chain of nodes, where every node points
to the next node. Along with this, next of the last node is linked to the head node.

Figure 4: Circular Linked List

.
 In a circular linked list, we access the elements using the head node (similar to head node
in singly linked list and doubly linked lists).
 In singly linked lists and doubly linked lists, the end of lists are indicated with NULL value.
But circular linked lists do not have ends.
 While traversing the circular linked lists we should be careful; otherwise we will be
traversing the list infinitely.
 In circular linked lists, each node has a successor. Note that unlike singly linked lists, there
is no node with NULL pointer in a circularly linked list.

27
Collected by Bipin Timalsina
DSA with Java/Unit-2

 In some situations, circular linked lists are useful. For example, when several processes are
using the same computer resource (CPU) for the same amount of time, we have to assure
that no process accesses the resource before all other processes do (round robin algorithm).

In Java, circular linked list can be represented as a class and a Node as a separate class. The
CircLinkedList class contains a reference of Node class type.
//node structure
class Node {
int data;
Node next;
}

class CircLinkedList {
Node head;
//constructor to create an empty CircLinkedList
CircLinkedList(){
head = null;
}
}
Counting nodes in a Circular Linked List
The circular list is accessible through the node marked head. (also called tail). To count the nodes,
the list has to be traversed from the node marked head, with the help of a dummy node current,
and stop the counting when current reaches the starting node head. If the list is empty, head will
be NULL, and in that case set count = 0. Otherwise, set the current pointer to the first node, and
keep on counting till the current pointer reaches the starting node.

28
Collected by Bipin Timalsina
DSA with Java/Unit-2

//method to count number of Nodes in Circular Linked List

public int getLength(Node tail) {


int length=0;
if(tail!=null) {
length++;
}
Node currentNode= tail.next;
while(currentNode!=tail) {
currentNode = currentNode.next;
length++;
}
return length;
}

Inserting a Node at the End of a Circular Linked List


Let us add a node containing data, at the end of a list (circular list) headed by head. The new node
will be placed just after the tail node (which is the last node of the list), which means it will have
to be inserted in between the tail node and the first node.
1. Create a new node and initially keep its next pointer pointing to itself.

2. Update the next pointer of the new node with the head node and also traverse the list to the
tail. That means in a circular list we should stop at the node whose next node is head.

29
Collected by Bipin Timalsina
DSA with Java/Unit-2

3. Update the next pointer of the previous node to point to the new node and we get the list
as shown below.

Time Complexity: O(n), for scanning the complete list of size n.


Space Complexity: O(1), for temporary variable.

Following method in Java can insert a node at ending of Circular Linked List

30
Collected by Bipin Timalsina
DSA with Java/Unit-2

void inserAtEnding(int newElement) {

//1. allocate node


Node newNode = new Node();

//2. assign data element


newNode.data = newElement;

//3. assign null to the next of new node


newNode.next = null;

//4. Check the list is empty or not,


// if empty make the new node as head
if(head == null) {
head = newNode;
newNode.next = head;
} else {

//5. Else, traverse to the last node


Node temp = new Node();
temp = head;
while(temp.next != head)
temp = temp.next;

//6. Adjust the links


temp.next = newNode;
newNode.next = head;
}
}

31
Collected by Bipin Timalsina
DSA with Java/Unit-2

Inserting a Node at the front of a Circular Linked List


The only difference between inserting a node at the beginning and at the end is that, after inserting
the new node, we just need to update the pointer. The steps for doing this are given below:
 Create a new node and initially keep its next pointer pointing to itself.

 Update the next pointer of the new node with the head node and also traverse the list until the
tail. That means in a circular list we should stop at the node which is its previous node in the
list.

 Make the new node as the head.

32
Collected by Bipin Timalsina
DSA with Java/Unit-2

Time Complexity: O(n), for scanning the complete list of size n. Space Complexity: O(1), for
temporary variable.

Following method in Java can insert a node at beginning of Circular Linked List

void insertAtBegining(int newElement) {

//1. allocate node


Node newNode = new Node();

//2. assign data element


newNode.data = newElement;

//3. assign null to the next of new node


newNode.next = null;

//4. Check the list is empty or not,


// if empty make the new node as head
if(head == null) {
head = newNode;
newNode.next = head;
} else {

//5. Else, traverse to the last node


Node temp = new Node();
temp = head;
while(temp.next != head)
temp = temp.next;

//6. Adjust the links


temp.next = newNode;
newNode.next = head;
33
Collected by Bipin Timalsina
DSA with Java/Unit-2

head = newNode;
}
}

Deleting the last node in a Circular List


The list has to be traversed to reach the last but one node. This has to be named as the tail node,
and its next field has to point to the first node. Consider the following list. To delete the last node
40, the list has to be traversed till you reach 7. The next field of 7 has to be changed to point to
60, and this node must be renamed pTail.
1. Traverse the list and find the tail node and its previous node.

2. Update the tail node’s previous node pointer to point to head.

34
Collected by Bipin Timalsina
DSA with Java/Unit-2

3. Dispose of the tail node.

Time Complexity: O(n), for scanning the complete list of size n.


Space Complexity: O(1), for a temporary variable.
Java Method to delete last node in circular linked list:
void delLast() {
if(this.head != null) {

//1. if head in not null and next of head


// is head, release the head
if(this.head.next == this.head) {
this.head = null;
} else {

//2. Else, traverse to the second last


// element of the list
Node temp = new Node();
temp = this.head;
while(temp.next.next != this.head)
temp = temp.next;

//3. Change the next of the second


// last node to head and delete the
// last node

35
Collected by Bipin Timalsina
DSA with Java/Unit-2

Node lastNode = temp.next;


temp.next = this.head;
lastNode = null;
}
}
}

Deleting the First Node in a Circular List


The first node can be deleted by simply replacing the next field of the tail node with the next field
of the first node.
 Find the tail node of the linked list by traversing the list. Tail node is the previous node to
the head node which we want to delete.

 Create a temporary node which will point to the head. Also, update the tail nodes next
pointer to point to next node of head (as shown below).

36
Collected by Bipin Timalsina
DSA with Java/Unit-2

 Now, move the head pointer to next node. Create a temporary node which will point to
head. Also, update the tail nodes next pointer to point to next node of head (as shown
below).

Time Complexity: O(n), for scanning the complete list of size n.


Space Complexity: O(1), for a temporary variable.

Java method:
void delFirst() {
if(this.head != null) {

//1. the list contains one node, delete


// make the head null
if(this.head.next == this.head) {
this.head = null;
} else {

//2. if the list contains more than one node,


// create two nodes - temp and firstNode, both
// pointing to head node
Node temp = this.head;
Node firstNode = this.head;

//3. using temp node, traverse to the last node


while(temp.next != this.head) {

37
Collected by Bipin Timalsina
DSA with Java/Unit-2

temp = temp.next;
}

//4. Make head as next of head,


// Make next of last node as head,
// delete the firstNode
this.head = this.head.next;
temp.next = this.head;
firstNode = null;
}
}
}

Circular Doubly Linked List


Circular doubly linked list is a more complex type of data structure in which a node contain
pointers to its previous node as well as the next node. The last node of the list contains the address
of the first node of the list. The first node of the list also contain address of the last node in its
previous pointer. Circular doubly linked list doesn't contain NULL in any of the node.

Figure 5: Circular Doubly Linked List

The first node also known as HEAD is always used as a reference to traverse the list. Last element
contains link to the first element as next and the first element contains link of the last element as

38
Collected by Bipin Timalsina
DSA with Java/Unit-2

previous. A circular doubly linked can be visualized as a chain of nodes, where every node points
to previous and next node.

Skip Lists
Linked lists have one serious drawback: They require sequential scanning to locate a searched-
for element. The search starts from the beginning of the list and stops when either a searched-for
element is found or the end of the list is reached without finding this element. Ordering elements
on the list can speed up searching, but a sequential search is still required. Therefore, we may think
about lists that allow for skipping certain nodes to avoid sequential processing. A skip list is an
interesting variant of the ordered linked list that makes such a nonsequential search possible.

In an ordinary sorted linked list, search, insert, and delete are in O(n) because the list must be
scanned node-by-node from the head to find the relevant node. If somehow we could scan down
the list in bigger steps (skip down, as it were), we would reduce the cost of scanning. This is the
fundamental idea behind Skip Lists.
 A skip list is a data structure that is used for storing a sorted list of items with a help of hierarchy
of linked lists that connect increasingly sparse subsequences of the items. A skip list allows
the process of item look up in efficient manner. The skip list data structure skips over many of
the items of the full list in one step, that’s why it is known as skip list.

Figure 6: Skip List

 A skip list is built up of layers. The lowest layer (i.e. bottom layer) is an ordinary ordered
linked list. The higher layers are like ‘express lane’ where the nodes are skipped

NOTE: A skip list is a probabilistic data structure. A skip list is built in layers. The bottom layer is
an ordinary ordered linked list. Each higher layer acts as an "express lane" for the lists below,
where an element in layer i appears in layer i+1 with some fixed probability p (two commonly
used values for pare 1/2 or 1/4)

39
Collected by Bipin Timalsina
DSA with Java/Unit-2

 In a skip list of n nodes, for each k and i such that 1 ≤ k ≤ ⎣lg n⎦ and 1 ≤ i ≤ ⎣ n/2k–1 ⎦ – 1, the
node in position 2k–1 · i points to the node in position 2k–1 · (i + 1).
 This means that every second node points to the node two positions ahead, every fourth node
points to the node four positions ahead, and so on.
 This is accomplished by having different numbers of reference fields in nodes on the list:
 Half of the nodes have just one reference field,
 one-fourth of the nodes have two reference fields,
 one-eighth of the nodes have three reference fields,
 and so on.
 The number of reference fields indicates the level of each node, and the number of levels is
maxLevel = ⎣lg n⎦ + 1

Figure 7: Skipped List with evenly spaced nodes of different levels

Figure 8: Skipped List with unevenly spaced nodes of different levels

Searching for an element el consists of following the references on the highest level until an
element is found that finishes the search successfully. In the case of reaching the end of the list or
encountering an element key that is greater than el, the search is restarted from the node preceding
the one containing key, but this time starting from a reference on a lower level than before. The
search continues until el is found, or the first-level references are followed to reach the end of the
list or to find an element greater than el. Here is a pseudocode for this algorithm:

40
Collected by Bipin Timalsina
DSA with Java/Unit-2

 When search for el:


→ If el = key, done!
→ If el < key, go down a level
→ If el > key, go right
 For example, if we look for number 16 in the list in Figure 8, then level four is tried first,
which is unsuccessful because the first node on this level has 28.
 Next, we try the third-level sublist starting from the root: It first leads to 8 and then to 17.
 Hence, we try the second-level sublist that originates in the node holding 8: It leads to 10
and then again to 17.
 The last try is by starting the first-level sublist, which originates in the node holding 10: It
leads to 12 and then again to 17, and because there is no lower level, the search is
pronounced unsuccessful.

Another Example: Searching 7 in following skip list (figure 9):

Figure 9: Another example of skip list

41
Collected by Bipin Timalsina
DSA with Java/Unit-2

 Starting at the 3rd level list which contains only “9”


 “7” < “9” ⇒ we moved too far, move down to the lower list
 Now we are on the 2nd level sublist (contains [“6”,”9” and “17”])
 “7” > “6” ⇒ check to the right
 “7” < “9” ⇒ we moved too far, move down to the lower list
 Now we are on the 1st level sublist (contains [“6”,”7”,”9” ,“12”,”17”and “19”])
 “7” > “6” ⇒ check to the right
 “7” = “7” ⇒ the element is found

Self-Organizing Lists
The introduction of skip lists was motivated by the need to speed up the searching process.
Although singly and doubly linked lists require sequential search to locate an element or to see
that it is not in the list, we can improve the efficiency of the search by dynamically organizing
the list in a certain manner. This organization depends on the configuration of data; thus, the
stream of data requires reorganizing the nodes already on the list.
A self-organizing list is a list that reorders its elements based on some self-organizing heuristic to
improve average access time. The aim of a self-organizing list is to improve efficiency of linear
search by moving more frequently accessed items towards the head of the list. A self-organizing
list achieves near constant time for element access in the best case. A self-organizing list uses a
reorganizing algorithm to adapt to various query distributions at runtime.
 A self-organizing list reorders its nodes based on searches which are done. The idea is to use
locality of reference (In a typical database, 80% of the access are to 20% of the items)

There are many different ways to organize the lists. Followings are some of the techniques used
by self-organizing lists:

42
Collected by Bipin Timalsina
DSA with Java/Unit-2

1. Move-to-front (MTF) method.


 After the desired element is located, put it at the beginning of the list.
 Any node searched is moved to the front. This strategy is easy to implement, but it may
over reward infrequently accessed items as it always move the item to front.

Figure 10: Move to Front Method

If the 5th node is selected, it is moved to the front

43
Collected by Bipin Timalsina
DSA with Java/Unit-2

2. Transpose method
 After the desired element is located, swap it with its predecessor unless it is at the head
of the list
 Any node searched is swapped with the preceding node. Unlike Move-to-front, this
method does not adapt quickly to changing access patterns.

Figure 11: Transpose Method

If the 5th node in the list is selected, it will be swapped with the 4th

44
Collected by Bipin Timalsina
DSA with Java/Unit-2

3. Count method.
 Order the list by the number of times elements are being accessed.
 Each node stores count of the number of times it was searched. Nodes are ordered by
decreasing count. This strategy requires extra space for storing count.

If 5 is accessed twice, count


becomes 46

Figure 12: Count Method

If the 5th node in the list is searched for twice, it will be swapped with the 4th

4. Ordering method.
 Order the list using certain criteria natural for the information under scrutiny.
 In the first three methods, new information is stored in a node added to the end of the
list but in the Ordering method, new information is stored in a node inserted
somewhere in the list to maintain the order of the list.
 The ordering method already uses some properties inherent to the information stored
in the list. For example, if we are storing nodes pertaining to people, then the list can
be organized alphabetically by the name of the person or the city or in ascending or
descending order using, say, birthday or salary.

45
Collected by Bipin Timalsina
DSA with Java/Unit-2

Figure 13: Accessing an element on a linked list and changes on the list depending
on the self-organization technique applied: (a) move-to-front method, (b) transpose
method, (c) count method, and (d) ordering method, in particular, alphabetical
ordering, which leads to no change. In the case when the desired element is not in
the list, (e) the first three methods add a new node with this element at the end of
the list and (f) the ordering method maintains an order on the list.

46
Collected by Bipin Timalsina
DSA with Java/Unit-2

Sparse Tables
In many applications, the choice of a table seems to be the most natural one, but space
considerations may preclude this choice. This is particularly true if only a small fraction of the
table is actually used. A table of this type is called a sparse table.
 A sparse table refers to a table that is populated sparsely by data and most of its cells
are empty
 With a sparse table, the table can be replaced by a system of linked lists
 Array of linked list can be used to represent sparse table.

(Go through text book for detail explanation with examples)

Case Study
LinkedList class of java.util package
Explore the LinkedList class present in java.util package. Discuss how linked list is implemented.
List the important constructors and methods present in the class with signatures and usages. Write
some Java programs to illustrate different operations like search, insertion, and deletion using the
constructors and methods present in the class.

47
Collected by Bipin Timalsina

You might also like