Free unit-wise study notes on linked lists and their variants for Data Structures and Algorithms, Semester 3 of B.Tech — Computer Science & Engineering — key concepts, examples, important questions and a revision checklist for semester exams.
A comprehensive guide to Linked Lists, including Singly, Doubly, and Circular Linked Lists. Covers dynamic memory allocation, pointer manipulation, and standard linked list operations.
Notebook — 14 pages
Page 1
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
1. Introduction to Linked Lists
A Linked List is a linear data structure, but unlike arrays, its elements are not stored at contiguous memory locations. Instead, the elements (nodes) are linked using pointers.
⇒1.1 The Concept of a Node
Each element in a linked list is called a Node. A basic node consists of two parts:
Data Field: Stores the actual data/value.
Link/Next Field: A pointer that stores the memory address of the next node in the sequence.
A linked list is always accessed via a special pointer called `head`, which points to the very first node. If the list is empty, `head` is `NULL`. The last node in the list points to `NULL`, indicating the end of the list.
Page 2
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
2. Arrays vs Linked Lists
Understanding when to choose a linked list over an array is a fundamental concept in data structures.
Arrays
Memory is allocated in a contiguous block.
Size is fixed at compile-time (static).
Random access is possible (O(1)) using indices.
Insertion/Deletion is expensive (O(n)) because elements must be shifted.
Memory is often wasted if the array is not full.
Linked Lists
Memory is allocated dynamically across the heap.
Size can grow or shrink dynamically at runtime.
Only sequential access is possible (O(n)).
Insertion/Deletion is cheap (O(1) if the node pointer is known) as no shifting is required.
Extra memory is required for storing pointers.
Page 3
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
3. Dynamic Memory Allocation
Linked lists rely heavily on Dynamic Memory Allocation, which allows programs to request memory from the operating system (specifically from the Heap) at runtime.
⇒3.1 malloc()
`malloc` (memory allocation) allocates a single block of requested memory size. It returns a void pointer to the memory, which must be cast to the desired type. The memory contains garbage values initially.
`calloc` (contiguous allocation) allocates multiple blocks of memory, each of the same size, and initializes all bytes to zero.
⇒3.3 free()
Memory allocated in the heap is not automatically destroyed when a function ends. The programmer must explicitly release it using `free()` to avoid memory leaks.
```c free(ptr); ptr = NULL; // Good practice to avoid dangling pointers ```
Page 4
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
4. Singly Linked List
A Singly Linked List is the simplest type of linked list. Navigation is forward-only; you can traverse from the first node to the last, but you cannot move backward.
⇒4.1 Traversing a Singly Linked List
Traversal involves visiting every node exactly once to perform an operation (like printing data). We use a temporary pointer (`temp`) to walk the list so we don't lose the `head` pointer.
Traverse the list while keeping track of the `prev` node and `current` node.
Stop when `current->next == NULL`.
Set `prev->next = NULL`.
Free `current`.
⇒6.3 Deletion of a Specific Node (O(n) to find, O(1) to delete)
Traverse to find the node. Adjust `prev->next` to skip the node to be deleted, then free it.
Page 7
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
7. Reversing a Linked List
Reversing a linked list is a classic university and interview question. The goal is to change the direction of all pointers so the last node becomes the new head.
⇒7.1 Iterative Approach (O(n) Time, O(1) Space)
We use three pointers: `prev`, `current`, and `next`.
Initialize `prev` to `NULL` and `current` to `head`.
Loop while `current` is not `NULL`:
- Save the next node: `next = current->next`
- Reverse the link: `current->next = prev`
- Move `prev` forward: `prev = current`
- Move `current` forward: `current = next`
Update `head` to `prev`.
```c struct Node reverse(struct Node head) { struct Node prev = NULL, current = head, *next = NULL; while (current != NULL) { next = current->next; current->next = prev; prev = current; current = next; } return prev; } ```
Page 8
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
8. Doubly Linked List
A Doubly Linked List (DLL) contains nodes that have two link pointers: one pointing to the next node and one pointing to the previous node. This allows traversal in both forward and backward directions.
When deleting a node `del` from a DLL, we must connect its predecessor and successor directly.
```c if(head == NULL || del == NULL) return;
// If node to be deleted is head node if(head == del) head = del->next;
// Change next only if node to be deleted is NOT the last node if(del->next != NULL) del->next->prev = del->prev;
// Change prev only if node to be deleted is NOT the first node if(del->prev != NULL) del->prev->next = del->next;
free(del); ```
Page 10
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
10. Circular Linked List
A Circular Linked List is a variation where the last node points back to the first node instead of pointing to `NULL`. It can be singly circular or doubly circular.
⇒10.1 Characteristics
There is no `NULL` pointer in a standard circular linked list.
Any node can be a starting point for traversal.
Often used in OS scheduling (e.g., Round Robin) where the queue loops back to the start.
⇒10.2 The 'Tail' Pointer Variation
In many implementations, instead of keeping a `head` pointer, we keep a `tail` pointer (pointing to the last node). This provides a massive advantage:
`tail->next` immediately gives us the first node (head).
Insertion at the beginning takes O(1) time.
Insertion at the end also takes O(1) time.
Without a tail pointer, insertion at the end of a circular list requires O(n) traversal to find the last node.
Page 11
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
11. Polynomial Arithmetic
Linked lists are highly effective for representing sparse polynomials. Each node represents a non-zero term.
⇒11.1 Node Structure
```c struct Term { int coeff; int exp; struct Term* next; }; ```
⇒11.2 Polynomial Addition Algorithm
To add two polynomials (P1 and P2), we use two pointers to traverse them. Both lists must be sorted in descending order of exponents.
If `P1->exp > P2->exp`: Add P1 node to result, move P1 pointer.
If `P1->exp < P2->exp`: Add P2 node to result, move P2 pointer.
If `P1->exp == P2->exp`: Add coefficients. If sum =0, add to result. Move both pointers.
If one list is exhausted, append the remaining terms of the other list to the result.
Time Complexity: O(m+n), where m and n are the number of terms in P1 and P2.
Page 12
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
12. Floyd's Cycle-Finding Algorithm
Also known as the Tortoise and Hare Algorithm, this is a famous technique to detect if a linked list contains a cycle (loop).
⇒12.1 The Algorithm
Use two pointers: `slow` and `fast`.
Initialize both pointers to `head`.
Move `slow` by one step (`slow = slow->next`).
Move `fast` by two steps (`fast = fast->next->next`).
If there is a cycle, the `fast` pointer will eventually catch up and equal the `slow` pointer inside the loop.
If `fast` reaches `NULL`, there is no cycle.
⇒12.2 Why does it work?
Imagine two runners on a circular track, one running twice as fast as the other. They are guaranteed to meet. The distance between them decreases by one node per step, so they must eventually collide.
Time Complexity:O(n), Space Complexity:O(1).
Page 13
Wink Notes
B.Tech CSE — 3rd Semester
Data Structures and Algorithms
— Unit - 2 —
13. Finding the Middle of a Linked List
A very common interview question: How do you find the middle node of a singly linked list in a single pass?
⇒13.1 Two-Pointer Approach
We use a variation of the Tortoise and Hare method.
Initialize two pointers, `slow` and `fast`, to `head`.
Traverse the list. In each iteration:
Move `slow` by one step.
Move `fast` by two steps.
When `fast` reaches the end of the list (`fast == NULL` or `fast->next == NULL`), `slow` will be pointing exactly at the middle node.