Tutorial
Linked List Data Structure

Linked List in C/C++/java/Python

Linked List Introduction

1

Comparison & Time Complexity

2

Visual Representation

3

LinkedList in Collection Framework(Java)

Linked List is a part of the Collection framework present in java.util package. This class is an implementation of the LinkedList data structure which is a linear data structure where the elements are not stored in contiguous locations and every element is a separate object with a data part and address part. The elements are linked using pointers and addresses. Each element is known as a node.

Constructors in the LinkedList:

In order to create a LinkedList, we need to create an object of the LinkedList class. The LinkedList class consists of various constructors that allow the possible creation of the list. The following are the constructors available in this class:

  • 1. LinkedList(): This constructor is used to create an empty list.
LinkedList<String> list = new LinkedList<String>();
  • 2. LinkedList(Collection C): - This constructor is used to create an ordered list that contains all the elements of a specified collection, as returned by the collection’s iterator. If we wish to create a LinkedList with the name ll, then, it can be created as:
    LinkedList<String> ll = new LinkedList<String>(Collection C);

Methods for Java LinkedList:

MethodsDescription
add(int index, E element)Inserts the specified element at the specified position in this list.
addAll(int index, Collection<E> c)Inserts all of the elements in the specified collection into this list, starting at the specified position.
addAll(collection<E> c)Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator.
addFirst(E e)Inserts the specified element at the beginning of this list.
addLast(E e)Appends the specified element to the end of this list.
clear()Removes all of the elements from this list.
clone()Returns a shallow copy of this LinkedList.
contains(Object o)Returns true if this list contains the specified element.
descendingIterator()Returns an iterator over the elements in this deque in reverse sequential order.
element()Retrieves, but does not remove, the head (first element) of this list.
get(int index)Returns the element at the specified position in this list.
getFirst()Returns the first element in this list.
getLast()Returns the last element in this list.
indexOf(Object o)Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
lastIndexOf(Object o)Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
listIterator(int index)Returns a list-iterator of the elements in this list (in proper sequence), starting at the specified position in the list.
offer(E e)Inserts the specified element at the end of this list.
offerFirst(E e)Inserts the specified element at the front of this list.
offerLast(E e)Inserts the specified element at the end of this list.
peek()Retrieves, but does not remove, the head (first element) of this list.
peekFirst()Retrieves, but does not remove, the first element of this list, or returns null if this list is empty.
peekLast()Retrieves, but does not remove, the last element of this list, or returns null if this list is empty.
poll()Retrieves and removes the head (first element) of this list.
pollFirst()Retrieves and removes the first element of this list, or returns null if this list is empty.
pollLast()Retrieves and removes the last element of this list, or returns null if this list is empty.
pop()Pops an element from the stack represented by this list.
push(E e)Pushes an element onto the stack represented by this list.
remove(int index)Removes the element at the specified position in this list.
remove(Object o)Removes the first occurrence of the specified element from this list, if it is present.
removeFirst()Removes and returns the first element from this list.
removeFirstOccurrence(Object o)Removes the first occurrence of the specified element in this list (when traversing the list from head to tail).
removeLast()Removes and returns the last element from this list.
removeLastOccurrence(Object o)Removes the last occurrence of the specified element in this list (when traversing the list from head to tail).
set(int index, E element)Replaces the element at the specified position in this list with the specified element.
size()Returns the number of elements in this list.
toArray()Returns an array containing all of the elements in this list in proper sequence (from first to last element).
toArray(T[] a)Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array.
toString()Returns a string representation of this collection. The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to strings as by String.valueOf(Object).

AbstractList:

This class is used to implement an unmodifiable list, for which one needs to only extend this AbstractList Class and implement only the get() and the size() methods.

CopyOnWriteArrayList:

This class implements the list interface. It is an enhanced version of ArrayList in which all the modifications(add, set, remove, etc.) are implemented by making a fresh copy of the list.

List in C++ Standard Template Library (STL)

List are sequence containers that allow non-contiguous memory allocation. As compared to vector, list has slow traversal, but once a position has been found, insertion and deletion are quick.

Functions Used with List

FunctionsDescription
front()Returns a reference to the first element in the list container.
back()Returns a reference to the last element in the list container.
push_front(g)Adds a new element ‘g’ at the beginning of the list, like stack.
push_back(g)Adds a new element ‘g’ at the end of the list, like queue.
pop_front()Removes the first element in the list, and reduces size of the list by 1.
pop_back()Removes the last element in the list, and reduces size of the list by 1.
list::begin()Returns an iterator pointing to the first element in the list.
list::end()Returns an iterator pointing to the theoretical last element which follows the last element.
list rbegin() and rend()Returns a reverse iterator pointing to the last element in the list (reverse beginning). It moves from last to first element.
list cbegin() and cend()Returns a constant iterator pointing to the first element in the list.
list crbegin() and crend()Returns a constant reverse iterator pointing to the last element in the list (reverse beginning). It moves from last to first element.
list::empty()Returns whether the list is empty(1) or not(0).
list::size()Returns the number of elements in the list.
insert()Inserts new elements in the list before the element at a specified position.
erase()Removes a single element or a range of elements from the list.
list::assign()Assigns new elements to list by replacing current elements and resizes the list.
list::remove()Removes all the elements from the list, which are equal to given element.
list::remove_if()Removes all the elements satisfying specific criteria.
lisr::reverse()Reverses the list.
reverse()Reverses the order of the elements in the list container.
list resize()Resizes the container so that it contains ‘g’ elements.
sort()Sorts the list in ascending order.
list max_size()Returns the maximum number of elements that the list container can hold.
list unique()Removes all duplicate consecutive elements from the list.
list::emplace_front() and list::emplace_back()The function extends the container by inserting new element at position.
list::clear()Removes all the elements of the list container, thus making it size 0.
list::operator=Assigns new contents to the container, replacing its current contents, and modifying its size accordingly.
list::swap()Exchanges the content of the container by the content of ‘x’, which is another list object of the same type. Sizes may differ.
list splice()Transfers elements from list to list.
list merge()Merges two sorted lists into one.
list emplace()The function extends the container by inserting new element at position.
list::emplace_back()The function extends the container by inserting new element at position.
list::emplace_front()The function extends the container by inserting new element at position.

Operations

Traversal

Traversal is the process of visiting each node in a linked list.

Approach
  • The main Approach to traverse a linked list is to start from the head node and keep on visiting the next node until the last node is reached which points to NULL.

link14

pseudocode
temp = head;
        while (temp!=NULL)
            {
                temp = temp -> next;
            }
Code Explanation

Untitled-2022-11-04-0050 excalidraw

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
    Node(int d)
    {
        data=d;
        next=NULL;
    }
};
 
void insert(Node **head,int data)
{
    Node *node=new Node(data);
    node->next=NULL;
    if(*head==NULL)
    {
        *head=node;
    }
    else
    {
        Node *temp=*head;
        while(temp->next!=NULL)
        {
            temp=temp->next;
        }
        temp->next=node;
    }
}
 
void traverse(Node *head)
{
    Node *temp=head;
    while(temp!=NULL)
    {
        cout<<temp->data<<endl;
        temp=temp->next;
    }
}
 
int main()
{
    Node *head=NULL;
    insert(&head,10);
    insert(&head,20);
    insert(&head,30);
    insert(&head,40);
    insert(&head,50);
    traverse(head);
    return 0;
}

output

10
20
30
40
50
Time Complexity

The time complexity of traversing a linked list is O(n) where n is the number of nodes in the linked list because we have to visit each node once to print its data.

Space Complexity

The space complexity of traversing a linked list is O(1) because we are not using any extra space.

Insertion

Insertion from the front end

Approach

4

5

image

pseudocode
NODE *FrontInsertion(int data, NODE *head){
	NODE *newnode = createNode(data);
	if(head == NULL){
		head = newnode;
	}
	else{
		newnode->next = head;
		head = newnode;
	}
	return head;
}
Code Explanation

6

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
};
void insertFirst (Node **head, int data)
{
    Node *newnode = new Node();
    newnode->data = data;
    newnode->next = *head;
    *head = newnode;
}
void printList(Node *head)
{
    while(head != NULL)
    {
        cout<<head->data<<" ";
        head = head->next;
    }
}
int main()
{
    Node *head = NULL;
    insertFirst(&head, 1);
    insertFirst(&head, 2);
    insertFirst(&head, 3);
    insertFirst(&head, 4);
    insertFirst(&head, 5);
    printList(head);
    return 0;
}

output

5 4 3 2 1
Time Complexity

The time complexity of insert at the front is O(1) because we are inserting the element at the beginning of the list and we don’t need to traverse the list to find the last element.

Space Complexity

The space complexity of insert at the front is O(1) because we are not using any extra space.

Insertion from the back end

Approach

7

8

image

pseudocode
NODE *InsertatIndex(int data, NODE *head, int index){
	NODE *newnode = createNode(data);
	NODE *temp = head;
	int count=0;
	while(count != index-1){
		temp = temp->next;
		count++;
	}
	//temp reaches the index before the target index
	newnode->next = temp->next;
	temp->next = newnode;
 
	return head;
}
Code Explanation

9

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
};
void insertLast(Node **head, int data)
{
    Node *newnode = new Node();
    newnode->data = data;
    newnode->next = NULL;
    if (*head == NULL) {
        *head = newnode;
    } else {
        Node *temp = *head;
        while (temp->next != NULL) {
            temp = temp->next;
        }
        temp->next = newnode;
    }
}
void printList(Node *head)
{
    Node *tnode = head;
    while (tnode != NULL) {
        cout << tnode->data << " ";
        tnode = tnode->next;
    }
}
int main()
{
    Node *head = NULL;
    insertLast(&head, 1);
    insertLast(&head, 2);
    insertLast(&head, 3);
    insertLast(&head, 4);
    insertLast(&head, 5);
    printList(head);
    return 0;
}

output

1 2 3 4 5
Time Complexity

The time complexity at the end of the linked list is O(n) because we have to traverse the entire linked list to reach the end here n is the number of nodes in the linked list.

Space Complexity

The space complexity is O(1) because we are not using any extra space here.

Insertion at Specific Index

Approach

197429850-34f79fcd-c129-4a78-acb5-67233c8b600a

11

image

pseudocode
NODE *InsertatIndex(int data, NODE *head, int index){
	NODE *newnode = createNode(data);
	NODE *temp = head;
	int count=0;
	while(count != index-1){
		temp = temp->next;
		count++;
	}
	//temp reaches the index before the target index
	newnode->next = temp->next;
	temp->next = newnode;
 
	return head;
}
Code Explanation

12

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
public:
    int data;
    Node *next;
    Node(int data)
    {
        this->data = data;
        this->next = NULL;
    }
};
class LLLast
{
public:
    Node *head;
    LLLast()
    {
        head = NULL;
    }
    void insert(int data)
    {
        Node *newNode = new Node(data);
        if (head == NULL)
        {
            head = newNode;
        }
        else
        {
            Node *last = head;
            while (last->next != NULL)
            {
                last = last->next;
            }
            last->next = newNode;
        }
    }
    void insertAt(int data, int index)
    {
        Node *newNode = new Node(data);
        Node *temp = head;
        int count = 0;
        while (count != index - 1)
        {
            temp = temp->next;
            count++;
        }
        newNode->next = temp->next;
        temp->next = newNode;
    }
    void print()
    {
        Node *current = head;
        while (current != NULL)
        {
            cout << current->data << " ";
            current = current->next;
        }
    }
};
int main()
{
    LLLast list;
    list.insert(1);
    list.insert(2);
    list.insert(3);
    list.insertAt(6, 2);
    list.print();
    return 0;
}

output

1 2 6 3
Time Complexity

The time complexity of the insert a node at a given position in a linked list is O(n) because we have to traverse the linked list to reach the position where we want to insert the node.

Space Complexity

The space complexity of the insert a node at a given position in a linked list is O(1) because we are not using any extra space.

Insertion using Functions

first , end & given position

CodeXam.cpp
#include<iostream>
#include<list>
using namespace std;
int main()
{
    // Declaring list
    list<string> list;
    list.push_back("CodeXam");
    list.push_back("is");
    list.push_back("Best");
 
    // Displaying the list
    cout << "List: ";
 
 
    for (auto it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
    cout << endl;
 
    // Adding an element to the first position
    list.push_front("Hello");
    //Displaying the list after adding the element
    cout << "List after adding the element at the first position: ";
 
 
    for (auto it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
 
 
    cout << endl;
 
    // Adding an element to the last position
 
    list.push_back("Java");
    //Displaying the list after adding the element
    cout << "List after adding the element at the last position: ";
 
    for (auto it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
 
    cout << endl;
 
 
    // Adding an element to the specified position
 
    auto it = list.begin();
    advance(it, 2);
 
    list.insert(it, "Programming");
    //Displaying the list after adding the element
    cout << "List after adding the element at the specified position: ";
 
 
    for (auto it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
 
    cout << endl;
 
    return 0;
 
 
}
 

output

Linked list: [CodeXam, is, Best]
Linked list after adding the element at the first position: [Hello, CodeXam, is, Best]
Linked list after adding the element at the last position: [Hello, CodeXam, is, Best, Java]
Linked list after adding the element at the specified position: [Hello, CodeXam, Programming, is, Best, Java]

Deletion

Deletion from the front end

Approach

ezgif-1-baa776cdac

  1. Check if the head is NULL, if it is then return.
  2. Make the head point to the next node of the head.
️⚠️

Note that we are not deleting the node, we are just making the head point to the next node of the head. In java & python garbage collector will delete the node automatically. In C we have to use free() function to delete the node. In C++ we have to use delete keyword to delete the node.

pseudocode
 
if(head == NULL)
    return;
 
head = head->next;
 
Code Explanation

Untitled-2022-11-04-0050 excalidraw

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
    Node(int d)
    {
        data=d;
        next=NULL;
    }
};
 
void removeFirstNode(Node *&head)
{
    if(head==NULL)
    {
        return;
    }
    Node *temp=head;
    head=head->next;
    delete temp;
}
 
void traverse(Node *head)
{
    while(head!=NULL)
    {
        cout<<head->data<<" ";
        head=head->next;
    }
}
 
int main()
{
    Node *head=new Node(1);
    head->next=new Node(2);
    head->next->next=new Node(3);
    head->next->next->next=new Node(4);
    head->next->next->next->next=new Node(5);
    head->next->next->next->next->next=new Node(6);
    removeFirstNode(head);
    traverse(head);
    return 0;
}

output

2
3
4
5
6
Time Complexity

Deletion of first node takes constant time O(1) because we are not traversing the list. We are just changing the head pointer to the next node.

Space Complexity

Space complexity is O(1) because we are not using any extra space.

Deletion from the back end

Approach

ezgif-1-41ece641e8

  1. Traverse the list till the last node.
  2. Change the next pointer of the second last node to NULL.
  3. Delete the last node.
pseudocode
removeLast() {
    if (head == null) {
        return;
    }
    if (head.next == null) {
        head = null;
        return;
    }
    Node temp = head;
    while (temp.next.next != null) {
        temp = temp.next;
    }
    temp.next = null;
}
Code Explanation

Untitled-2022-11-04-0050 excalidraw

Untitled-2022-10-17-1607

Code Implementation
CodeXam.cpp
 
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
    Node(int d)
    {
        data=d;
        next=NULL;
    }
};
 
void removeLastNode(Node *head)
{
    Node *temp=head;
    while(temp->next->next!=NULL)
    {
        temp=temp->next;
    }
    temp->next=NULL;
}
 
 
 
void push(Node **head,int new_data)
{
    Node *new_node=new Node(new_data);
    new_node->next=*head;
    *head=new_node;
}
 
void printList(Node *head)
{
    Node *tnode=head;
    while(tnode!=NULL)
    {
        cout<<tnode->data<<" ";
        tnode=tnode->next;
    }
    cout<<endl;
}
 
int main()
{
    Node *head=NULL;
    push(&head,1);
    push(&head,2);
    push(&head,3);
    push(&head,4);
    push(&head,5);
 
    cout<<"Created Linked list is: ";
    printList(head);
 
    removeLastNode(head);
 
    cout<<"Linked List after deletion of last node: ";
    printList(head);
 
    return 0;
}
 
 

output

Created Linked list is: 5 4 3 2 1
Linked List after deletion of last node: 5 4 3 2
Time Complexity

The time complexity of deletion last node is O(n) where n is the number of nodes in the linked list because we need to traverse the list to find the second last node.

Space Complexity

The space complexity of deletion last node is O(1) because we are not using any extra space.

Deletion at Specific Index

Approach

The main idea of the algo is to traverse the list till the index and delete the node at that index. We need to keep track of the previous node of the node to be deleted. We can use two pointers to keep track of the previous and current node. We can also use a single pointer to keep track of the current node and use the previous node of the current node to delete the node at the given index.

ezgif-5-b100459c99

  1. Create a temp node and initialize it with head node.
  2. Create a prev node and initialize it with null.
  3. If index is 0 and temp is not null, then make head as temp.next and return.
  4. Create a counter and initialize it with 0.
  5. Traverse the list till temp is not null.
  6. If counter is equal to index, then make prev.next as temp.next and break the loop.
  7. Else, make prev as temp and temp as temp.next and increment counter by 1.
  8. If temp is null, then print "Index not found".
pseudocode
removeAtSpecificIndex(index)
    temp = head
    prev = null
    if index == 0 and temp != null
        head = temp.next
        return
    counter = 0
    while temp != null
        if counter == index
            prev.next = temp.next
            break
        else
            prev = temp
            temp = temp.next
            counter++
    if temp == null
        print "Index not found"
 
Code Explanation

1 2 3 5 6 7 8 9 10 11 12

4 13

Code Implementation
CodeXam.cpp
#include<iostream>
using namespace std;
class Node
{
    public:
    int data;
    Node *next;
    Node(int d)
    {
        data=d;
        next=NULL;
    }
};
 
void removeAtSpecificIndex(Node *head,int index)
{
    Node *temp=head;
    Node *prev=NULL;
    int count=0;
    while(temp!=NULL)
    {
        if(count==index)
        {
            prev->next=temp->next;
            delete temp;
            return;
        }
        prev=temp;
        temp=temp->next;
        count++;
    }
}
 
void push(Node **head,int new_data)
{
    Node *new_node=new Node(new_data);
    new_node->next=*head;
    *head=new_node;
}
 
void printList(Node *head)
{
    Node *tnode=head;
    while(tnode!=NULL)
    {
        cout<<tnode->data<<" ";
        tnode=tnode->next;
    }
    cout<<endl;
}
 
int main()
{
    Node *head=NULL;
    push(&head,1);
    push(&head,2);
    push(&head,3);
    cout<<"Created Linked list is: ";
    printList(head);
    removeAtSpecificIndex(head,1);
    cout<<"Linked List after Deletion at index 1: ";
    printList(head);
    return 0;
}
 
 

output

Created Linked list is:
3 2 1
Linked List after Deletion at index 1:
2 1
Time Complexity

Deletion at a given index is an operation that takes O(n) time. This is because in the worst case, we might have to travel all the way from the head of the list to the tail to find the node at the given index.

Space Complexity

The space complexity of the above algorithm is O(1) as we do not use any extra space.

Deletion using Functions

first , end & given position

CodeXam.cpp
#include<iostream>
#include<list>
using namespace std;
int main()
{
    // Add elements to the linked list
 
    list<string> list;
    list.push_back("CodeXam");
    list.push_back("is");
    list.push_back("Best");
    list.push_back("for");
    list.push_back("Developers");
 
    // Displaying the linked list
    cout << "Linked list: ";
    for (auto it = list.begin(); it != list.end(); it++)
        cout << *it << " ";
 
    // Removing an element at first position
    list.pop_front();
 
    // Displaying the linked list
    cout << " "
 
         << "Linked list after removing first element: ";
    for (auto it = list.begin(); it != list.end(); it++)
 
        cout << *it << " ";
 
    // Removing an element at last position
 
    list.pop_back();
 
    // Displaying the linked list
    cout << " "
 
         << "Linked list after removing last element: ";
    for (auto it = list.begin(); it != list.end(); it++)
 
        cout << *it << " ";
 
    // Removing an element at specified position
 
    list.remove("Best");
 
    // Displaying the linked list
    cout << " "
 
         << "Linked list after removing 3rd element: ";
    for (auto it = list.begin(); it != list.end(); it++)
 
        cout << *it << " ";
 
    return 0;
 
}
 

output

Linked list: [CodeXam, is, Best, for, Developers]
Linked list after removing first element: [is, Best, for, Developers]
Linked list after removing last element: [is, Best, for]
Linked list after removing 3rd element: [is, Best]