Data Structures using C

Linked Lists


Module II: Linked Lists. Linked Lists are dynamic data structures where elements are stored as nodes connected through pointers. Unlike arrays, elements do not need to be stored in contiguous memory locations.


Introduction to Linked Lists

A linked list is a linear data structure made up of nodes. Each node contains data and a pointer that connects it to another node. Linked lists allow dynamic memory allocation and can grow or shrink during program execution.

  • Dynamic size
  • Nodes connected using pointers
  • Efficient insertion and deletion
  • Memory allocated at runtime

Node Structure

Code Example
struct Node{
   int data;
   struct Node* next;
};

Components of a Linked List

  • Node → Basic unit of linked list
  • Data Field → Stores information
  • Pointer Field → Stores next node address
  • Head → Starting node
  • Tail → Last node

Memory Representation

Unlike arrays, linked list nodes are stored in different memory locations and connected through pointers.

Address     Data     Next
1000         10       2000
2000         20       3000
3000         30       NULL

Need for Linked Lists

Arrays have a fixed size and require contiguous memory locations. If more elements need to be stored than initially allocated, resizing becomes difficult and expensive.

Linked lists solve these problems by allowing memory allocation during runtime. New nodes can easily be inserted or deleted without shifting all existing elements.

  • Dynamic memory allocation
  • Flexible size
  • Efficient insertion and deletion
  • Better memory utilization

Creating a Node

Nodes are usually created dynamically using malloc().

struct Node* newNode;

newNode=(struct Node*)
malloc(sizeof(struct Node));

newNode->data=10;
newNode->next=NULL;

Types of Linked Lists

  • Singly Linked List
  • Doubly Linked List
  • Circular Linked List

Singly Linked List

A Singly Linked List is the simplest type of linked list where each node contains data and a pointer to the next node only. Traversal is possible only in the forward direction because there is no link to previous nodes.

Singly linked lists are commonly used when memory efficiency is important because only one pointer field is stored per node.

10 -> 20 -> 30 -> NULL

Doubly Linked List

A Doubly Linked List stores two pointers in each node: one pointer stores the address of the next node and another stores the address of the previous node.

Since nodes can be traversed in both forward and backward directions, insertion and deletion operations become easier. However, additional memory is required because of the extra pointer.

NULL <- 10 <-> 20 <-> 30 -> NULL

Circular Linked List

In a Circular Linked List, the last node does not contain NULL. Instead, the last node points back to the first node, forming a circular chain structure.

Circular linked lists are useful in applications involving cyclic processing such as CPU scheduling, multiplayer games, and round-robin algorithms.

10 -> 20 -> 30
^            |
|____________|

Complexity Analysis

Operation        Complexity

Access            O(n)
Search            O(n)
Insertion         O(1)
Deletion          O(1)

Basic Operations on Linked Lists

Various operations can be performed on linked lists for storing, accessing, and modifying data. These operations are essential for maintaining the linked list structure.

  • Creation of nodes
  • Insertion of nodes
  • Deletion of nodes
  • Traversal of nodes
  • Searching for elements
  • Updating node values
  • Sorting linked lists

The basic operations such as traversal, insertion, deletion, searching, and updating are common for all linked list types. However, the implementation of these operations differs depending on whether the linked list is singly, doubly, or circular.

The examples below mainly use a Singly Linked List because it is the simplest and most commonly used implementation for understanding linked list concepts.

Traversal

Traversal means visiting each node one by one from the head node until the end of the linked list is reached.

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

Time Complexity: O(n)

Searching

Searching is used to locate a particular element in a linked list. Since direct indexing is not available, nodes must be checked one by one.

while(temp!=NULL){

   if(temp->data==key)
      printf("Found");

   temp=temp->next;
}

Time Complexity: O(n)

Insertion

Insertion adds a new node into the linked list. It can be performed at the beginning, end, or any specified position.

newNode->next=head;
head=newNode;

Time Complexity: O(1)

Deletion

Deletion removes a node from the linked list by changing pointer connections between nodes.

head=head->next;

Time Complexity: O(1)

Updating

Updating changes the value stored in an existing node.

temp->data=50;

Arrays vs Linked Lists

  • Arrays use contiguous memory
  • Linked lists use non-contiguous memory
  • Arrays have fixed size
  • Linked lists are dynamic
  • Arrays provide direct access
  • Linked lists require traversal

Applications of Linked Lists

  • Stacks and queues
  • Browser navigation systems
  • Music playlists
  • Graph representation
  • Dynamic memory allocation

Advantages of Linked Lists

  • Dynamic memory allocation
  • Efficient insertion and deletion
  • No fixed size limitation

Limitations of Linked Lists

  • No direct access by index
  • Extra memory required for pointers
  • Traversal is slower than arrays