All about Linked Lists in C++
By: Aman Kumar Goyal
Tags: Computer Science, Data Structures, Competitive Programming, Cpp, Linked Lists

Linked lists are very important, useful and powerful data structures and are used for many purposes in C++. In this blog I am going to cover as much as possible from a beginner’s point, so let’s get started.

Linked list is a linear data structure in which data is stored in a contiguous manner, each element is stored in the form of a node, a node is created dynamically on run-time and these nodes are connected using pointers.

Linked lists are of many times

Singly Linked List.

Doubly Linked List.

Circular Linked List.

Circular Doubly Linked List.

Below is an image of a singular linked list to give you a glimpse of haw data is arranged in a singly linked list. Ignore the details we will cover them later.

Linked Lists v/s array

Yes, in some operations linked lists comes out to perform better than arrays. I am covering this because you should be aware of merits and demerits of linked lists over arrays, only then you would understand the necessity of linked lists.

Merits

Elements are added dynamically.

There is no need for continuous block of memory nodes are present at different memory locations which are connected by pointers.

Insertion and deletion operations are more efficient than array.

Demerits:

Node of Singly Linked List

Node of Doubly linked list

Linked Lists take more memory as it is required more memory for pointer block i.e. to store an element you need twice the memory for two blocks one for element itself and other for the address of next node.

In case of doubly linked list there are two extra blocks one for address of next node and one for previous block.

In linked list one can’t randomly access data element which is really easy in case of array.

Singly Linked Lists

In Singly linked lists nodes have only one pointer i.e. to the address of next node and due to having only one connected they are called so.

You use an analogy to visualize better, compare it to a train where engine is the head and every coach represents a block each block is connected to next block by a link.

Photo by Denis Chick on Unsplash

Now we will see how we can build a linked list in cpp all its basic operations then we will see some some inbuilt functions and modules to make which are very powerful and makes our work much easier.But first let’s how the node of a singly linked list is created.

Node

Well a node can be built using a structure as in C but in my opinion it is better to use the power and capabilities of classes in C++, hence I will show you how to create a node in C++ using class.

class node{

public:

int data;

node* next; node(int d){

data = d;

next = NULL;

}

};

So you can see we have got a class named node, there are two variable one is of type int for element of integer type(you can store any type of data in your list by changing the type here, you can also make a templated list and define the type later in main() ), and the other is of type node as you are aware of fact that a pointer to anything should be of data type same as that of the element which the pointer is pointing.

Now, in the constructor named node we have got an input and we have specified the input to data variable and set the address of next node to be null.

As you go on to functionalities of linked lists you will get a better understanding as then you will be able to see the bigger picture.

Insertion

Moving on to our next topic i.e. insertion in linked list, insertion operation can be done at head, at the end or at any other position. One important thing before moving on, we store the address of first node in a pointer named head to refer the list it is very important variable and at any point if you mess up with the head it might happen that your whole list might get lost.

So coming back to insertion I will show insertion at head, end and at any other position but it is advised to insert an element at head as it would take constant time and it is the easiest. Let’s dive right in to code.

Insertion at Tail

It requires to traverse over the whole linked list to insert at tail, we first declare a new node and put the input data in the data block using the constructor we have made it is most common step and you have to create a node every time so it will itself comes in handy.

First we check if the list is empty because if it is so then we have to just add new node as first element, if this is not the case then we will traverse by running loop till we reach the end of list and then add node.

End condition is checked by while(temp->next !- NULL), where NULL denote that end is reached and one more thing to consider is to use a different variable each time so that you wouldn’t mess up with the head node. Also notice that we have passed the head node as reference that’s why we don’t need to return the node.

void insertAtTail(node* &head ,int d){

node* n = new node(d);

if(head == NULL){

head = n;

} else{

node* temp = head;

while(temp->next != NULL){

temp = temp->next;

}

temp->next = n;

}

return;

}

Insertion at Head

It is pretty simply, we first create a new node which is same as done before then we check if the list is empty if it is then just add it as first element, if it is not then put the address of head in the next of new node and the address of new node in head.

void insertAtHead(node* &head ,int d){

node* n = new node(d);

if(head == NULL){

head = n;

}



else{

n->next = head;

head = n;

}

return;

}

Insertion at any position given

We create a node same as in above cases then we iterate to reach at position one less than given we do so because if it is needed to add a new node at fourth position then we need to be on third position then we connect new node using this node.

void insertAtOther(node* &head, int d, int position){

node* n = new node(d);

if(postion == 1){

n->next = head;

head = n;

}

else{

node* temp = head;

position = position-1;

while(position--){

temp = temp->next;

}



n->next = temp->next;

temp->next = n;

}

return;

}

Above is a figure showing insertion at third position. While working with liked lists it is often better to visualize everything in your mind beforehand it will make your work more easier.

Now you try to visualize insertion a head and tail and see how easy it becomes to understand the code.

Printing List

Traversing and printing list is pretty simple we create a temp variable store head in it and traverse using this temp variable.



void printList(node* &head){

node*temp=head;

while(temp!=NULL){

cout<<temp->data<<" ";

temp = temp->next;

}

return;

}

Deletion

Deletion operation is one of primary operations of linked list and are important in understanding linked lists better. Deletion can our at head, tail and at any given position. We will see code one by one but I am not going to explain everything as I have already done before and it would be better if you yourself try to understand you code to improve to understanding. Let’s get started

Deletion at Head

void deletionAtHead(node* &head){



if(head == NULL){

cout<<"List is empty"<<endl;

}



else{

node* temp = head;

head = temp->next;

free(temp);

}

return;

}

Deletion at Tail

void deletionAtTail(node* &head){



if(head == NULL){

cout<<"List is empty"<<endl;

}

if(head->next == NULL){

delete head;

head= NULL;

}

else{

node* temp = head;

while((temp->next)->next != NULL){

temp= temp->next;

}

delete(temp->next);

temp->next = NULL;

}

return;

}

Deletion at any other position

void deletionAtOther(node* &head, int position){ if(head == NULL){

cout<<"List is empty"<<endl;

}

if(postion == 1){

delete head;

head = NULL;

}

else{

node* t1 = head, t2;

position--;

while(position--){

t1 = t1->next;

}

t2 = t1->next->next;

free(t1->net);

t1->next = NULL;

}

return;

}

Doubly Linked List

Doubly linked list is very similar to singly linked list , instead of just one pointer it has got two pointers one for previous block and one for next block and we use a head and a tail pointer variable to point the head and tail of list use of two pointers makes it much easier to perform operations but it also costs us more memory.

class node{

public:

int data;

node* next, *prev; node(int d){

data = d;

prev = NULL;

next = NULL;

}

};

As you can see the node is very similar to singly linked list and the coding part is also very similar just you have to deal with another previous pointer. You can code it up yourself from the concepts you have and that’s I am not going to show you the code for operations in doubly linked list.

Circular Linked Lists & Doubly Circular Linked List

Circular and doubly circular linked linked are just singly and doubly linked list with its last element pointing to first node. It makes our work even more easier.

Above images will give you an insight about how they work and the coding part is similar to those discussed above just you have to point the last node to first node.

List STL

C++ STL is a powerful library which provides us many inbuilt functions and methods which makes our work much more easier. You can use the list STL by including “list”.

#include<list>

list<int> l;

We will see briefly the basic functions and methods available in C++.

Iterators:

begin → Return iterator pointing to beginning of the list.

Return iterator pointing to beginning of the list. end → Return iterator pointing to end pointof the list.

Return iterator pointing to end pointof the list. rbegin → Return reverse iterator pointing to reverse beginning of the list.

Return reverse iterator pointing to reverse beginning of the list. rend → Return reverse iterator pointing to reverse end of the list.

Return reverse iterator pointing to reverse end of the list. cbegin → Return const_iterator pointing to beginning of the list.

Return const_iterator pointing to beginning of the list. cend → Return const_iterator pointing to end of the list.

Return const_iterator pointing to end of the list. crbegin → Return const_reverse_iterator pointing to reverse beginning of the list.

Return const_reverse_iterator pointing to reverse beginning of the list. crend →Return const_reverse_iterator pointing to reverse end of the list.

Capacity:

empty → Test whether container is empty.

Test whether container is empty. size → Returns the size of the storage space currently allocated to the list.

Returns the size of the storage space currently allocated to the list. max_size →Return maximum size of the list.

Element access:

front → Access first element of the list.

Access first element of the list. back →Access last element of the list.

Modifiers:

assign → Assign new content to container of the list.

Assign new content to container of the list. emplace_front → Construct and insert element at beginning of the list.

Construct and insert element at beginning of the list. push_front → Insert element at beginning of the list.

Insert element at beginning of the list. pop_front → Delete first element of the list.

Delete first element of the list. emplace_back → Construct and insert element at the end of the list.

Construct and insert element at the end of the list. push_back → Add element at the end of the list.

Add element at the end of the list. pop_back → Delete last element of the list.

Delete last element of the list. emplace → Construct and insert element of the list.

Construct and insert element of the list. insert → Insert elements in the list.

Insert elements in the list. erase → Erase elements of the list.

Erase elements of the list. swap → Swap content of the list.

Swap content of the list. resize → Change size of the list.

Change size of the list. clear →Clear content of the list.

Operations:

splice → Transfer elements from list to list .

Transfer elements from list to list . remove → Remove elements with specific value .

Remove elements with specific value . remove_if → Remove elements fulfilling condition .

Remove elements fulfilling condition . unique → Remove duplicate values from the list.

Remove duplicate values from the list. merge → Merge sorted lists .

Merge sorted lists . sort → Sort elements in container .

Sort elements in container . reverse →Reverse the order of elements .

That’s all…..

That’s all, I hope you have learnt a lot linked list and I would suggest to try whatever you have learnt do try to code everything from scratch for a better understanding if you feel like that you are comfortable then you can shift to code entirely using STL otherwise you wouldn’t be able to understand what’s happening under the hood.

Go get you hands dirty by code it up and try something new, try to code in your own style.

Have Fun, Keep coding and Happy Programming : — )