HOME
ABOUT

Linked Lists - Data Structure

Introduction to Linked Lists

A Linked List is a linear data structure where elements are stored in nodes, and each node points to the next node in the sequence. Unlike arrays, linked lists can grow or shrink in size during execution.

Types of Linked Lists

  1. Singly Linked List: Each node contains data and a reference to the next node
  2. Doubly Linked List: Each node contains data and references to both next and previous nodes
  3. Circular Linked List: Last node points back to the first node

Time Complexity

Operation Time Complexity
Access O(n)
Search O(n)
Insertion O(1)
Deletion O(1)

Implementation Examples

  1. Go Implementation
package main

import "fmt"

// Node structure
type Node struct {
    data int
    next *Node
}

// LinkedList structure
type LinkedList struct {
    head *Node
}

// Insert at beginning
func (list *LinkedList) insertFront(data int) {
    newNode := &Node{data: data}
    newNode.next = list.head
    list.head = newNode
}

// Print list
func (list *LinkedList) printList() {
    current := list.head
    for current != nil {
        fmt.Printf("%d -> ", current.data)
        current = current.next
    }
    fmt.Println("nil")
}

func main() {
    list := LinkedList{}
    
    // Insert elements
    list.insertFront(3)
    list.insertFront(2)
    list.insertFront(1)
    
    // Print list
    fmt.Println("Linked List:")
    list.printList()
}
  1. Java Implementation
public class LinkedList {
    // Node class
    static class Node {
        int data;
        Node next;
        
        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }
    
    Node head;
    
    // Insert at beginning
    public void insertFront(int data) {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
    }
    
    // Print list
    public void printList() {
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " -> ");
            current = current.next;
        }
        System.out.println("null");
    }
    
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        
        // Insert elements
        list.insertFront(3);
        list.insertFront(2);
        list.insertFront(1);
        
        // Print list
        System.out.println("Linked List:");
        list.printList();
    }
}
  1. Python Implementation
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None
    
    def insert_front(self, data):
        new_node = Node(data)
        new_node.next = self.head
        self.head = new_node
    
    def print_list(self):
        current = self.head
        while current:
            print(f"{current.data} -> ", end="")
            current = current.next
        print("None")

# Example usage
if __name__ == "__main__":
    # Create a linked list
    llist = LinkedList()
    
    # Insert elements
    llist.insert_front(3)
    llist.insert_front(2)
    llist.insert_front(1)
    
    # Print the linked list
    print("Linked List:")
    llist.print_list()

Common Linked List Operations

  1. Insertion

    • At the beginning (head)
    • At the end (tail)
    • At a specific position
  2. Deletion

    • From the beginning
    • From the end
    • From a specific position
  3. Traversal

    • Forward traversal
    • Reverse traversal (in doubly linked list)
  4. Searching

    • Finding a specific element
    • Finding position of an element

Advantages and Disadvantages

Advantages:

  • Dynamic size
  • Efficient insertion and deletion
  • No memory wastage
  • Implementation of other data structures

Disadvantages:

  • Extra memory for pointers
  • No random access
  • Not cache friendly
  • Complex implementation

Applications

  1. Implementation of stacks and queues
  2. Symbol table management in compilers
  3. Undo functionality in software
  4. Memory allocation and management
  5. Music playlist management

Best Practices

  1. Use linked lists when:

    • Size is dynamic
    • Frequent insertions/deletions are required
    • Random access is not primary
    • Memory is not a constraint
  2. Avoid linked lists when:

    • Random access is frequently required
    • Memory is limited
    • Cache performance is critical

Common Problems and Solutions

  1. Detecting Cycles

    • Floyd's Cycle-Finding Algorithm
    • Hash Table Method
  2. Reversing a Linked List

    • Iterative Method
    • Recursive Method
  3. Finding Middle Element

    • Two Pointer Method
    • Counter Method

Linked Lists are essential data structures that provide flexibility in managing dynamic data. Understanding linked lists is crucial for developing efficient algorithms and solving complex programming problems.

Related Articles

  • Introduction to the Data Structures
  • Arrays - Data Structure
  • Linked Lists - Data Structure
  • Stacks - Data Structure
  • Queues - Data Structure
  • Trees - Data Structure
  • Graphs - Data Structure