Linked List and Its Operations

Linked List

In a game of Treasure Hunt, you start by looking for the first clue. When you find it, instead of having the treasure, it has the location of the next clue and so on. You keep following the clues until you get to the treasure.
A linked list is similar. It is a series of connected "nodes" that contains the "address" of the next node. Each node can store a data point which may be a number, a string or any other type of data.
Linked lists are the best and simplest example of a dynamic data structure that uses pointers for its implementation. However, understanding pointers is crucial to understanding how linked lists work and you must also be familiar with dynamic memory allocation and structures.
Essentially, linked lists function as an array that can grow and shrink as needed, from any point in the array.
Linked lists have a few advantages over arrays:
1.    Items can be added or removed from the middle of the list
2.    There is no need to define an initial size

However, linked lists also have a few disadvantages:
1.    There is no "random" access - it is impossible to reach the nth item in the array without first iterating over all items up until that item. This means we have to start from the beginning of the list and count how many times we advance in the list until we get to the desired item.
2.    Dynamic memory allocation and pointers are required, which complicates the code and increases the risk of memory leaks and segment faults.
3.    Linked lists have a much larger overhead over arrays, since linked list items are dynamically allocated (which is less efficient in memory usage) and each item in the list also must store an additional pointer.

Linked List Representation

You have to start somewhere, so we give the address of the first node a special name called HEAD.
Also, the last node in the linked list can be identified because its next portion points to NULL.
How another node is referenced?
Some pointer magic is involved. Let's think about what each node contains:
  • A data item
  • An address of another node

We wrap both the data item and the next node reference in a struct as:
struct node
{
  int data;
  struct node *next;
};

Understanding the structure of a linked list node is the key to having a grasp on it.
Each struct node has a data item and a pointer to another struct node. Let us create a simple Linked List with three items to understand how this works.

/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;

/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));

/* Assign data values */
one->data = 1;
two->data = 2;
three->data=3;

/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;

/* Save address of first node in head */
head = one;

If you didn't understand any of the lines above, all you need is a refresher on pointers and structs.
In just a few steps, we have created a simple linkedlist with three nodes.

The power of linked list comes from the ability to break the chain and rejoin it. E.g. if you wanted to put an element 4 between 1 and 2, the steps would be:
Create a new struct node and allocate memory to it.
Add its data value as 4
Point its next pointer to the struct node containing 2 as data value
Change next pointer of "1" to the node we just created.
Doing something similar in an array would have required shifting the positions of all the subsequent elements.
Utility of Linked List
Lists are one of the most popular and efficient data structures, with implementation in every programming language like C, C++, Python, Java and C#.
Apart from that, linked lists are a great way to learn how pointers work. By practicing how to manipulate linked lists, you can prepare yourself to learn more advanced data structures like graphs and trees.

Types of Linked List
There are three common types of Linked List.
·         Singly Linked List
·         Doubly Linked List
·         Circular Linked List

Singly Linked List
It is the most common. Each node has data and a pointer to the next node.

Node is represented as:
struct node {
    int data;
    struct node *next;
}

A three member singly linked list can be created as:
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;

/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));

/* Assign data values */
one->data = 1;
two->data = 2;
three->data = 3;

/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;

/* Save address of first node in head */
head = one;

Doubly Linked List
We add a pointer to the previous node in a doubly linked list. Thus, we can go in either direction: forward or backward.

A node is represented as
struct node {
    int data;
    struct node *next;
    struct node *prev;
}

A three member doubly linked list can be created as
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;

/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));

/* Assign data values */
one->data = 1;
two->data = 2;
three->data = 3;

/* Connect nodes */
one->next = two;
one->prev = NULL;

two->next = three;
two->prev = one;

three->next = NULL;
three->prev = two;

/* Save address of first node in head */
head = one;

Circular Linked List
A circular linked list is a variation of linked list in which the last element is linked to the first element. This forms a circular loop.

A circular linked list can be either singly linked or doubly linked.
·         for singly linked list, next pointer of last item points to the first item
·         In doubly linked list, prev pointer of first item points to last item as well.
A three member circular singly linked list can be created as:

/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;

/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));

/* Assign data values */
one->data = 1;
two->data = 2;
three->data = 3;

/* Connect nodes */
one->next = two;
two->next = three;
three->next = one;

/* Save address of first node in head */
head = one;

Linked List Operations
Now that you have got an understanding of the basic concepts behind linked list and their types, its time to dive into the common operations that can be performed.
Two important points to remember:
head points to the first node of the linked list
next pointer of last node is NULL, so if next of current node is NULL, we have reached end of linked list.
In all of the examples, we will assume that the linked list has three nodes 1 --->2 --->3with node structure as below:
struct node
{
  int data;
  struct node *next;
};
How to traverse a linked list
Displaying the contents of a linked list is very simple. We keep moving the temp node to the next one and display its contents.
When temp is NULL, we know that we have reached the end of linked list so we get out of the while loop.
struct node *temp = head;
printf("\n\nList elements are - \n");
while(temp != NULL)
{
     printf("%d --->",temp->data);
     temp = temp->next;
}
The output of this program will be:
List elements are -
1 --->2 --->3 --->

How to add elements to linked list
You can add elements to beginning, middle or end of linked list.
Add to beginning
·         Allocate memory for new node
·         Store data
·         Change next of new node to point to head
·         Change head to point to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = head;
head = newNode;
Add to end
·         Allocate memory for new node
·         Store data
·         Traverse to last node
·         Change next of last node to recently created node
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;
newNode->next = NULL;

struct node *temp = head;
while(temp->next != NULL){
  temp = temp->next;
}
temp->next = newNode;
Add to middle
·         Allocate memory and store data for new node
·         Traverse to node just before the required position of new node
·         Change next pointers to include new node in between

struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->data = 4;

struct node *temp = head;

for(int i=2; i < position; i++) {
    if(temp->next != NULL) {
        temp = temp->next;
    }
}
newNode->next = temp->next;
temp->next = newNode;
How to delete from a linked list
You can delete either from beginning, end or from a particular position.
Delete from beginning
Point head to the second node
head = head->next;
Delete from end
Traverse to second last element
Change its next pointer to null
struct node* temp = head;
while(temp->next->next!=NULL){
  temp = temp->next;
}
temp->next = NULL;
Delete from middle
Traverse to element before the element to be deleted
Change next pointers to exclude the node from the chain
for(int i=2; i< position; i++) {
    if(temp->next!=NULL) {
        temp = temp->next;
    }
}
temp->next = temp->next->next;


Comments

Popular posts from this blog

પટેલ સમાજનો ઈતિહાસ જાણો : કોણ અને ક્યાંથી આવ્યા હતા પાટીદારો

Python HTML Generator using Yattag Part 1

Java Event Delegation Model, Listener and Adapter Classes