Linked List In C

Linked List In C

INTRODUCTION

A linked list is a linear data structure that includes a series of connected nodes, each node stores the data and address of the next node. While arrays can prove to be useful in computing, they still have some disadvantages when it comes to expanding arrays and memory arrays which is what linked list solves. The major difference between a linked list and an array is that data items are not stored in a contiguous location.

A linked list must always have a HEAD pointer. The head pointer points to the first node of the linked list, this pointer is used to access the data in the linked and further transverse in the linked list.

To represent a linked list, we use another data structure called Structures which is a user-defined data structure in C.

TYPES OF LINKED LIST

There are 4 types of linked lists, these linked lists can be modified to suit the project or the way data is to be structured by the developer.

  1. Singly Linked List

  2. Doubly Linked List

  3. Circular Linked List

  4. Doubly-Circular Linked List

Singly Linked List

Singly Linked List is the most common type of linked list, each node contains 2 parts; the data part and the address part. The data part contains the data stored in the node and the address part is a link to the next node. The last node of the linked list will point to NULL i.e. the last node doesn't point to any memory address.

The address of the first node is stored as the head pointer. The name singly linked list is because the nodes are having a single link to each other. This data structure cannot be transverse backward because it allows only forward sequential movement.

Representing a singly-linked list in C

struct node
{
    int data;
    struct node * next; /*the pointer to next node*/
}

Doubly Linked List

Doubly Linked List is a list that has two pointers to two different nodes, each node is made up of three parts i.e. two pointer parts and the data part. The first pointer points to the previous node and the second pointer points to the next node in the sequence. The pointers can also be known as forward and backward links.

Representing a doubly-linked list in C

struct node
{
    int data;
    struct node *prev; /*pointer to previous node*/
    struct node *next; /*pointer to next node*/
}

In a doubly linked list, the first node's previous pointer *prev is set to NULL because it doesn't point to any node since it is the first node of the list. The last node's next pointer *next is set to NULL to indicate the end of the list.

Circular Linked List

Just as the name implies, this list is in a circular direction. It is a variation of a singly linked list, the difference is that the last node's address part *next is set to store the address of the first node so that link between each node continues like a cycle.

Doubly-Circular Linked List

The doubly-circular linked list combines both the features of a circular linked list and a doubly linked list. In this type of list, the first node's previous pointer *prev stores the address to the last node and the last node's next pointer *next stores the address of the first node. Other node contains a link to the previous node, the next node and the data stored in the node.

DIFFERENCES BETWEEN AN ARRAY AND LINKED LIST

CASE STUDYARRAYLINKED LIST
Cost of accessing elementsAn array allows random access to elements, once the base address is known e.g. arr[3] will access the fourth element of an array.Random Access is not allowed, only sequential access is possible.
Memory UtilizationMemory utilization is not efficient i.e. some memory allocated to an array may not be used.It is very efficient. Memory is not wasted.
Memory RequirementThe memory requirement of an array is less. e.g. storing 4 int elements in an array will cost 16bytesThe memory requirement is great. e.g. storing 4 int elements in a singly linked list may cost 36bytes.

IMPLEMENTATION OF LINKED LIST

Let's write a simple program that takes four integer elements and stores them in a singly linked list.

  1. Create 5 files; a header file main.h , our main function and 3 other C files to handle how functions. The header file will contain our function prototype.

     /* This is the header file*/
     #ifndef LIST_H
     #define LIST_H
     #include <stddef.h>
     #include <stdio.h>
    
     /**
     * struct listint_s - singly linked list
     * @n: integer
     * @next: points to the next node
     *
     * Description: singly linked list node structure
     *
     */
    
     typedef struct listint_s
     {
             int n;
             struct listint_s *next;
     } listint_t;
    
     size_t print_list(const listint_t *h);
     listint_t *add_node_end(listint_t **head, const int n);
     void free_list(listint_t *head);
    
     #endif /*LIST_H*/
    
  2. The first C file print.c will handle the printing of the data of each node in our linked list.

     #include "lists.h"
     /**
     * print_list - prints all the elements of a list_t.
     * @h: pointer to list.
     *
     * Return: the number of nodes.
     */
    
     size_t print_list(const listint_t *h)
     {
             int count;
    
             count = 0;
             while (h != NULL)
             {
                     printf("%d\n", h->n);
                     h = h->next;
                     count++;
             }
             return (count);
     }
    
    1. The next C file add_node_end will handle the node, that is it will add any new node to the end of the previous node.

       #include "lists.h"
       #include <stdlib.h>
      
       /**
       * add_node_end - adds new node to end of list
       * @head: pointer to linked list
       * @n: number to bestored in linked list
       * Return: returns pointer to linked list
       */
      
       listint_t *add_node_end(listint_t **head, const int n)
       {
               listint_t *newnode;
               listint_t *temp;
      
               temp = newnode = malloc(sizeof(listint_t));
               if (newnode == NULL || temp == NULL)
               {
                       return (NULL);
               }
               newnode->n = n;
               if (*head == NULL)
                       *head = newnode;
               else
               {
                       temp = *head;
                       while (temp->next != NULL)
                               temp = temp->next;
                       temp->next = newnode;
               }
               return (newnode);
       }
      
      1. This function will free the memory used by our function in creating the linked list, after the execution of the code.

         #include "lists.h"
         #include <stdlib.h>
        
         /**
         * free_list - free the memory
         * @head: head pointer of linked list
         * Return: void
         */
        
         void free_list(listint_t *head)
         {
                 listint_t *temp;
        
                 while (head != NULL)
                 {
                         temp = head;
                         head = head->next;
                         free(temp);
                 }
         }
        
        1. Now, the main function

           #include "lists.h"
          
           /**
            * main - check the code
            *
            * Return: Always 0.
            */
           int main(void)
           {
               listint_t *head;
          
               head = NULL;
               add_node_end(&head, 0);
               add_node_end(&head, 1);
               add_node_end(&head, 2);
               add_node_end(&head, 3);
               add_node_end(&head, 4);
               add_node_end(&head, 98);
               add_node_end(&head, 402);
               add_node_end(&head, 1024);
               print_list(head);
               free_list(head);
               head = NULL;
               return (0);
           }
          
  3. Compile files in terminal

LINKED LIST IN THE REAL WORLD

Linked lists can also be used in the real world for:

  • Image viewer – Previous and next images are linked and can be accessed by the next and previous buttons. Previous and next page in a web browser – We can access the previous and next URL searched in a web browser by pressing the back and next buttons since they are linked as a linked list.

  • Music Player – Songs in the music player are linked to the previous and next songs. So you can play songs either from starting or ending of the list.

  • GPS navigation systems - Linked lists can be used to store and manage a list of locations and routes, allowing users to easily navigate to their desired destination.

  • Robotics - Linked lists can be used to implement control systems for robots, allowing them to navigate and interact with their environment.

  • Task Scheduling - Operating systems use linked lists to manage task scheduling, where each process waiting to be executed is represented as a node in the list.

  • Image Processing - Linked lists can be used to represent images, where each pixel is represented as a node in the list.

  • File Systems - File systems use linked lists to represent the hierarchical structure of directories, where each directory or file is represented as a node in the list.

  • Symbol Table - Compilers use linked lists to build a symbol table, which is a data structure that stores information about identifiers used in a program.

  • Undo/Redo Functionality - Many software applications implement undo/redo functionality using linked lists, where each action that can be undone is represented as a node in a doubly linked list.

  • Speech Recognition - Speech recognition software uses linked lists to represent the possible phonetic pronunciations of a word, where each possible pronunciation is represented as a node in the list.

  • Polynomial Representation - Polynomials can be represented using linked lists, where each term in the polynomial is represented as a node in the list.