0% found this document useful (0 votes)
7 views

Linked List in C1

This document provides a comprehensive guide on linked lists in C, covering their structure, types (singly, doubly, and circular), and various operations such as creation, insertion, deletion, and searching. It includes detailed explanations and code examples for each operation, as well as advanced topics like cycle detection, palindrome checking, and merging sorted lists. The guide emphasizes the dynamic nature of linked lists compared to arrays, highlighting their advantages and disadvantages.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Linked List in C1

This document provides a comprehensive guide on linked lists in C, covering their structure, types (singly, doubly, and circular), and various operations such as creation, insertion, deletion, and searching. It includes detailed explanations and code examples for each operation, as well as advanced topics like cycle detection, palindrome checking, and merging sorted lists. The guide emphasizes the dynamic nature of linked lists compared to arrays, highlighting their advantages and disadvantages.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Linked List in C

A linked list is a fundamental data structure where elements (nodes) are linked together
using pointers. Unlike arrays, linked lists are dynamic, meaning memory is allocated as
needed.

This guide will take you from basic to advanced concepts with step-by-step explanations,
examples, and C code.

🔹 1. What is a Linked List?

A linked list consists of nodes, where each node contains:

1. Data (stores value)

2. Pointer (stores the address of the next node)

🛠 Structure of a Node in C

struct Node {

int data;

struct Node* next; // Pointer to the next node

};

Comparison: Linked List vs. Array

Feature Array Linked List

Memory Allocation Fixed (static) Dynamic (grows/shrinks)

Insertion/Deletion Expensive (shifting required) Efficient (no shifting)

Random Access Fast (O(1)) Slow (O(n), needs traversal)

2. Types of Linked Lists

1️. Singly Linked List

Each node contains data and a pointer to the next node.

Example Representation:

Head -> [10 | *] -> [20 | *] -> [30 | NULL]

✔️Advantages: Simple structure, efficient insertion/deletion at the beginning.


❌ Disadvantages: Cannot traverse backward.
2️. Doubly Linked List

Each node has two pointers:

 next → Points to the next node

 prev → Points to the previous node

struct Node {

int data;

struct Node* prev;

struct Node* next;

};

Example Representation:

NULL <- [10 | * | *] <-> [20 | * | *] <-> [30 | NULL]

✔️Advantages: Can traverse both directions.


❌ Disadvantages: Extra memory for prev pointer.

3️. Circular Linked List

 Singly Circular Linked List → Last node’s next points to the first node.

 Doubly Circular Linked List → Last node’s next points to the first, and first’s prev
points to the last.

Example (Circular Singly Linked List):

Head -> [10 | *] -> [20 | *] -> [30 | Head]

✔️Advantages: No NULL, continuous traversal.


❌ Disadvantages: More complex implementation.

3. Operations on Linked Lists

✅ (A) Creating and Printing a Linked List

Steps:
1. Create a structure Node with data and next.

2. Allocate memory dynamically using malloc().

3. Store values in nodes and link them.

Code:

#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
void printList(struct Node* head) {
while (head != NULL) {
printf("%d -> ", head->data);
head = head->next;
}
printf("NULL\n");
}
int main() {
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 10;
head->next = second;
second->data = 20;
second->next = third;
third->data = 30;
third->next = NULL;
printList(head);
return 0;
}
Output:

10 -> 20 -> 30 -> NULL

✅ (B) Find Length of Linked List

Steps:

1. Start from head and initialize count = 0.


2. Traverse till NULL and increase count.

3. Return count.

Code:

int getLength(struct Node* head) {


int count = 0;
while (head) {
count++;
head = head->next;
}
return count;
}
Output (for 10 -> 20 -> 30 -> NULL):

Length: 3

✅ (C) Insert a Node

1️. Insert at the Beginning

Steps:

1. Create a new node.

2. Point new node’s next to head.

3. Update head.

struct Node* insertAtBeginning(struct Node* head, int data) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = head;
return newNode;
}
✔️New Node becomes head.

2️. Insert at the End

Steps:

1. Create a new node.

2. Traverse till last node.


3. Update last node’s next to new node.

void insertAtEnd(struct Node** head, int data) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
struct Node* temp = *head;
newNode->data = data;
newNode->next = NULL;
if (*head == NULL) {
*head = newNode;
return;
}
while (temp->next) temp = temp->next;
temp->next = newNode;
}

✅ (D) Search in a Linked List

Steps:

1. Start from head.

2. Compare each node’s data with key.

3. Return position if found, else return -1.

int search(struct Node* head, int key) {


int pos = 1;
while (head) {
if (head->data == key) return pos;
head = head->next;
pos++;
}
return -1;
}
📝 Output (for 10 -> 20 -> 30, key = 20):

Found at position 2

✅ (E) Delete a Node by Key

Steps:

1. If head contains key, update head.

2. Else, traverse to find key & update previous node’s next.

void deleteByKey(struct Node** head, int key) {


struct Node *temp = *head, *prev = NULL;
if (temp && temp->data == key) {
*head = temp->next;
free(temp);
return;
}
while (temp && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (!temp) return;
prev->next = temp->next;
free(temp);
}

✅ (F) Reverse a Linked List

Steps:

1. Use three pointers: prev, current, next.

2. Traverse and reverse next pointer.

struct Node* reverse(struct Node* head) {


struct Node *prev = NULL, *curr = head, *next = NULL;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
🔹 1. Detect a Loop in a Linked List (Floyd’s Cycle Detection)

Problem: Given a linked list, check if there exists a cycle (loop).

Approach: Use the Floyd’s Cycle Detection Algorithm (Tortoise and Hare).

 Use two pointers: slow moves one step, fast moves two steps.

 If they meet, a cycle exists.

Code:

#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
int detectCycle(struct Node* head) {
struct Node *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return 1; // Cycle detected
}
return 0; // No cycle
}

struct Node* createNode(int data) {


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
int main() {
struct Node* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(3);
head->next->next->next = createNode(4);
head->next->next->next->next = head->next;
if (detectCycle(head))
printf("Cycle detected in the linked list\n");
else
printf("No cycle detected\n");
return 0;
}
Output:
Cycle detected in the linked list

2. Check if a Linked List is a Palindrome

Problem: Given a linked list, check if it reads the same forwards and backwards.
Approach:

1. Find the middle of the list.

2. Reverse the second half.

3. Compare the first half with the reversed half.

4. Restore the original list.

Code:

#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* reverse(struct Node* head) {
struct Node *prev = NULL, *curr = head, *next = NULL;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
int isPalindrome(struct Node* head) {
if (!head || !head->next) return 1;
struct Node *slow = head, *fast = head, *prev = NULL;
while (fast && fast->next) {
prev = slow;
slow = slow->next;
fast = fast->next->next;
}
prev->next = NULL; // Split the list
struct Node* secondHalf = reverse(slow);
struct Node* firstHalf = head;
while (firstHalf && secondHalf) {
if (firstHalf->data != secondHalf->data) return 0;
firstHalf = firstHalf->next;
secondHalf = secondHalf->next;
}
return 1;
}
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}

int main() {
struct Node* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(2);
head->next->next->next = createNode(1);
if (isPalindrome(head))
printf("The linked list is a palindrome\n");
else
printf("The linked list is NOT a palindrome\n");
return 0;
}
Output:
The linked list is a palindrome

3. Merge K Sorted Linked Lists (LeetCode #23)

Problem: Merge K sorted linked lists into one sorted linked list.

Approach:

 Use a Min Heap (Priority Queue) to always extract the smallest node.

 Insert the next node of the extracted node back into the heap.

Code (Using Min Heap)

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};
// Merge two sorted lists

struct Node* mergeTwoLists(struct Node* l1, struct Node* l2) {

if (!l1) return l2;

if (!l2) return l1;

if (l1->data < l2->data) {

l1->next = mergeTwoLists(l1->next, l2);

return l1;

} else {

l2->next = mergeTwoLists(l1, l2->next);

return l2;

struct Node* mergeKLists(struct Node** lists, int k) {

if (k == 0) return NULL;

while (k > 1) {

for (int i = 0; i < k / 2; i++)

lists[i] = mergeTwoLists(lists[i], lists[k - 1 - i]);

k = (k + 1) / 2;

return lists[0];

struct Node* createNode(int data) {

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

newNode->data = data;

newNode->next = NULL;

return newNode;
}

void printList(struct Node* head) {

while (head) {

printf("%d -> ", head->data);

head = head->next;

printf("NULL\n");

int main() {

int k = 3;

struct Node* lists[k];

lists[0] = createNode(1);

lists[0]->next = createNode(4);

lists[0]->next->next = createNode(7);

lists[1] = createNode(2);

lists[1]->next = createNode(5);

lists[1]->next->next = createNode(8);

lists[2] = createNode(3);

lists[2]->next = createNode(6);

lists[2]->next->next = createNode(9);

struct Node* mergedHead = mergeKLists(lists, k);

printList(mergedHead);

return 0;

}
Output:

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> NULL

1. Reverse Nodes in K-Groups (LeetCode #25)

2. Sort a Linked List (LeetCode #148)

3. Copy List with Random Pointer (LeetCode #138)

4. Swap Nodes in Pairs (LeetCode #24)

5. Partition List (LeetCode #86)

1. Reverse Nodes in K-Groups (LeetCode #25)

Problem: Given a linked list, reverse every K nodes in a group. If the number of remaining
nodes is less than K, leave them as they are.

Approach:

1. Count K nodes in the list.

2. Reverse the first K nodes.

3. Recursively call the function for the remaining part of the list.

Code:

#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};

struct Node* reverseKGroup(struct Node* head, int k) {


struct Node *prev = NULL, *curr = head, *next = NULL;
int count = 0;
struct Node* temp = head;
for (int i = 0; i < k && temp; i++)
temp = temp->next;
if (!temp && count < k) return head;
while (curr && count < k) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
count++;
}
if (next) head->next = reverseKGroup(next, k);
return prev;
}
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void printList(struct Node* head) {
while (head) {
printf("%d -> ", head->data);
head = head->next;
}
printf("NULL\n");
}
int main() {
struct Node* head = createNode(1);
head->next = createNode(2);
head->next->next = createNode(3);
head->next->next->next = createNode(4);
head->next->next->next->next = createNode(5);
int k = 2;
printf("Original List: ");
printList(head);
head = reverseKGroup(head, k);
printf("Reversed in K-Groups: ");
printList(head);
return 0;
}
Output:

Original List: 1 -> 2 -> 3 -> 4 -> 5 -> NULL

Reversed in K-Groups: 2 -> 1 -> 4 -> 3 -> 5 -> NULL

🔹 2. Sort a Linked List (LeetCode #148)

📌 Problem: Sort a linked list in ascending order using Merge Sort.

💡 Approach:

1. Find the middle of the list.

2. Recursively sort both halves.


3. Merge the two sorted halves.

✅ Code:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};

// Function to merge two sorted lists

struct Node* merge(struct Node* l1, struct Node* l2) {

if (!l1) return l2;

if (!l2) return l1;

if (l1->data < l2->data) {

l1->next = merge(l1->next, l2);

return l1;

} else {

l2->next = merge(l1, l2->next);

return l2;

// Function to find middle node

struct Node* findMiddle(struct Node* head) {

struct Node *slow = head, *fast = head->next;

while (fast && fast->next) {


slow = slow->next;

fast = fast->next->next;

return slow;

// Merge Sort for Linked List

struct Node* sortList(struct Node* head) {

if (!head || !head->next) return head;

struct Node* middle = findMiddle(head);

struct Node* right = middle->next;

middle->next = NULL;

struct Node* leftSorted = sortList(head);

struct Node* rightSorted = sortList(right);

return merge(leftSorted, rightSorted);

// Create node

struct Node* createNode(int data) {

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

newNode->data = data;

newNode->next = NULL;

return newNode;

}
// Print function

void printList(struct Node* head) {

while (head) {

printf("%d -> ", head->data);

head = head->next;

printf("NULL\n");

int main() {

struct Node* head = createNode(4);

head->next = createNode(2);

head->next->next = createNode(1);

head->next->next->next = createNode(3);

printf("Original List: ");

printList(head);

head = sortList(head);

printf("Sorted List: ");

printList(head);

return 0;

📝 Output:

Original List: 4 -> 2 -> 1 -> 3 -> NULL

Sorted List: 1 -> 2 -> 3 -> 4 -> NULL


🔹 3. Copy List with Random Pointer (LeetCode #138)

📌 Problem: Given a linked list where each node has a random pointer that points to another
node in the list, create a deep copy.

💡 Approach:

1. Create duplicate nodes next to original nodes.

2. Assign random pointers to duplicate nodes.

3. Separate the copied list from the original.

✅ Code:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

struct Node* random;

};

// Function to copy the list

struct Node* copyRandomList(struct Node* head) {

if (!head) return NULL;

struct Node* curr = head;

while (curr) {

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

copy->data = curr->data;

copy->next = curr->next;

curr->next = copy;

curr = copy->next;
}

curr = head;

while (curr) {

if (curr->random)

curr->next->random = curr->random->next;

curr = curr->next->next;

struct Node* newHead = head->next;

struct Node* copy = newHead;

curr = head;

while (curr) {

curr->next = curr->next->next;

if (copy->next)

copy->next = copy->next->next;

curr = curr->next;

copy = copy->next;

return newHead;

🚀 More Problems Coming Next

4. Swap Nodes in Pairs (LeetCode #24)

5. Partition List (LeetCode #86)

6. Convert Sorted List to BST (LeetCode #109)


Would you like me to continue with the remaining problems? 😊

Let's go step by step and cover each of these advanced linked list problems in C with
detailed explanations, approaches, and working code.

🔹 1. Reverse Nodes in K-Groups (LeetCode #25)

📌 Problem: Given a linked list, reverse every K nodes in a group. If the number of remaining
nodes is less than K, leave them as they are.

💡 Approach:

1. Count K nodes in the list.

2. Reverse the first K nodes.

3. Recursively call the function for the remaining part of the list.

✅ Code:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};

// Function to reverse K nodes in a group

struct Node* reverseKGroup(struct Node* head, int k) {

struct Node *prev = NULL, *curr = head, *next = NULL;

int count = 0;

// Count K nodes

struct Node* temp = head;

for (int i = 0; i < k && temp; i++)


temp = temp->next;

if (!temp && count < k) return head;

// Reverse first K nodes

while (curr && count < k) {

next = curr->next;

curr->next = prev;

prev = curr;

curr = next;

count++;

// Recursively reverse next part

if (next) head->next = reverseKGroup(next, k);

return prev;

// Function to create a node

struct Node* createNode(int data) {

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

newNode->data = data;

newNode->next = NULL;

return newNode;

// Function to print the linked list

void printList(struct Node* head) {


while (head) {

printf("%d -> ", head->data);

head = head->next;

printf("NULL\n");

int main() {

struct Node* head = createNode(1);

head->next = createNode(2);

head->next->next = createNode(3);

head->next->next->next = createNode(4);

head->next->next->next->next = createNode(5);

int k = 2;

printf("Original List: ");

printList(head);

head = reverseKGroup(head, k);

printf("Reversed in K-Groups: ");

printList(head);

return 0;

📝 Output:

Original List: 1 -> 2 -> 3 -> 4 -> 5 -> NULL

Reversed in K-Groups: 2 -> 1 -> 4 -> 3 -> 5 -> NULL


🔹 2. Sort a Linked List (LeetCode #148)

📌 Problem: Sort a linked list in ascending order using Merge Sort.

💡 Approach:

1. Find the middle of the list.

2. Recursively sort both halves.

3. Merge the two sorted halves.

✅ Code:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

};

// Function to merge two sorted lists

struct Node* merge(struct Node* l1, struct Node* l2) {

if (!l1) return l2;

if (!l2) return l1;

if (l1->data < l2->data) {

l1->next = merge(l1->next, l2);

return l1;

} else {

l2->next = merge(l1, l2->next);

return l2;

}
// Function to find middle node

struct Node* findMiddle(struct Node* head) {

struct Node *slow = head, *fast = head->next;

while (fast && fast->next) {

slow = slow->next;

fast = fast->next->next;

return slow;

// Merge Sort for Linked List

struct Node* sortList(struct Node* head) {

if (!head || !head->next) return head;

struct Node* middle = findMiddle(head);

struct Node* right = middle->next;

middle->next = NULL;

struct Node* leftSorted = sortList(head);

struct Node* rightSorted = sortList(right);

return merge(leftSorted, rightSorted);

// Create node

struct Node* createNode(int data) {

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


newNode->data = data;

newNode->next = NULL;

return newNode;

// Print function

void printList(struct Node* head) {

while (head) {

printf("%d -> ", head->data);

head = head->next;

printf("NULL\n");

int main() {

struct Node* head = createNode(4);

head->next = createNode(2);

head->next->next = createNode(1);

head->next->next->next = createNode(3);

printf("Original List: ");

printList(head);

head = sortList(head);

printf("Sorted List: ");

printList(head);

return 0;
}

📝 Output:

Original List: 4 -> 2 -> 1 -> 3 -> NULL

Sorted List: 1 -> 2 -> 3 -> 4 -> NULL

🔹 3. Copy List with Random Pointer (LeetCode #138)

📌 Problem: Given a linked list where each node has a random pointer that points to another
node in the list, create a deep copy.

💡 Approach:

1. Create duplicate nodes next to original nodes.

2. Assign random pointers to duplicate nodes.

3. Separate the copied list from the original.

✅ Code:

#include <stdio.h>

#include <stdlib.h>

struct Node {

int data;

struct Node* next;

struct Node* random;

};

// Function to copy the list

struct Node* copyRandomList(struct Node* head) {

if (!head) return NULL;

struct Node* curr = head;

while (curr) {
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));

copy->data = curr->data;

copy->next = curr->next;

curr->next = copy;

curr = copy->next;

curr = head;

while (curr) {

if (curr->random)

curr->next->random = curr->random->next;

curr = curr->next->next;

struct Node* newHead = head->next;

struct Node* copy = newHead;

curr = head;

while (curr) {

curr->next = curr->next->next;

if (copy->next)

copy->next = copy->next->next;

curr = curr->next;

copy = copy->next;

return newHead;

}
🚀 More Problems Coming Next

4. Swap Nodes in Pairs (LeetCode #24)

5. Partition List (LeetCode #86)

6. Convert Sorted List to BST (LeetCode #109)

Would you like me to continue with the remaining problems? 😊

You might also like