Linked List

The linked list is a linear data structure where each node has two parts.

1. Data

2. Reference to the next node




Data

In this section, we can store the required information. It can be any data type.

Example

int age;
char name[20];



Reference to the next node

It will hold the next nodes address.


Head Node - Starting node of a linked list.

Last Node   - Node with reference pointer as NULL.




Selecting a data type for the linked list

As we discussed earlier, each node in a linked list has two parts.

Data - it can be any data type. int,char,float,double etc.

Reference Part - It will hold the address of the next node. So, it is a type pointer.


Here, we need to group two different data types (heterogeneous).


Which data type is used to group the different data types?

That is a structure. So, every node in a linked list is a structure data type.




Sample Linked List Node

struct node
{
    int data;
    struct node *next;
};

where,

data - used to store the integer information.

struct node *next - It is used to refer to the next node. It will hold the address of the next node.


Linked List Node



Let's create and allocate memory for 3 nodes

struct node
{
    int data;
    struct node *next;
};

struct node *head,*middle,*last;

head   = malloc(sizeof(struct node));
middle = malloc(sizeof(struct node));
last   = malloc(sizeof(struct node));



Assign values to each node

head->data   = 10;
middle->data = 20;
last->data   = 30;
linked list node with data

1. Stack memory stores all the local variables and function calls (static memory).

Example: int a = 10;

2. Heap memory stores all the dynamically allocated variables.

Example: int *ptr = malloc(sizeof(int)); Here, memory will be allocated in the heap section. And the ptr resides in the stack section and receives the heap section memory address on successful memory allocation.

3. Address of the dynamic memory which will be assigned to the corresponding variable.




Linking each nodes

headnode middlenode lastnode NULL

head->next   = middle;
middle->next = last;
last->next   = NULL;     //NULL indicates the end of the linked list
Sample Linked List

1. head => next = middle. Hence head => next holds the memory address of the middle node (2024).

2. middle => next = last. Hence middle => next holds the memory address of the last node (3024).

3. last => next = NULL which indicates it is the last node in the linked list.

4. The simplified version of the heap memory section.




Let's print each node data in a linked list

To print each node's data, we have to traverse the linked list till the end.

Algorithm

1. Create a temporary node(temp) and assign the head node's address.

2. Print the data which present in the temp node.

3. After printing the data, move the temp pointer to the next node.

4. Do the above process until we reach the end.


Visual Representation

Printing linked list step 1

1. temp points to the head node. temp => data = 10 will be printed. temp will point to the next node (Middle Node).

2. temp != NULL. temp => data = 20 will be printed. Again temp will point to the next node (Last Node).

3. temp != NULL. temp => data = 30 will be printed. Again temp will point to the next node which is NULL.

4. temp == NULL. Stop the process we have printed the whole linked list.


Code

struct node *temp = head;

while(temp != NULL)
{
    printf("%d ",temp->data);
    temp = temp->next;
}

Why do we need to use the temp node instead head?

If we use the head pointer instead of the temp while printing the linked list, we will miss the track of the starting node. (After printing the data head node will point the NULL).

To avoid that, we should not change the head node's address while processing the linked list. We should always use a temporary node to manipulate the linked list.




Sample Linked List Implementation

Example

#include<stdio.h>
#include<stdlib.h>

int main()
{
  //node structure
  struct node
  {
      int data;
      struct node *next;
  };

  //declaring nodes
  struct node *head,*middle,*last;

  //allocating memory for each node
  head   = malloc(sizeof(struct node));
  middle = malloc(sizeof(struct node));
  last   = malloc(sizeof(struct node));

  //assigning values to each node
  head->data   = 10;
  middle->data = 20;
  last->data   = 30;

  //connecting each nodes. head->middle->last
  head->next   = middle;
  middle->next = last;
  last->next   = NULL;

  //temp is a reference for head pointer.
  struct node *temp = head;

  //till the node becomes null, printing each nodes data
  while(temp != NULL)
  {
      printf("%d->",temp->data);
      temp = temp->next;
  }
  printf("NULL");

  return 0;
}