Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
JavaScript Program for Quicksort On Singly Linked List
The singly-linked list is a linear data structure that consists of nodes. Each node contains data and a pointer to the next node, which holds the memory address of the next node since memory allocation for nodes is not continuous.
Sorting arranges elements of a data structure like linked lists or arrays in a specific order, typically ascending. In this article, we'll implement the quicksort algorithm on a singly linked list using JavaScript.
Introduction to Problem
QuickSort is a divide-and-conquer sorting algorithm that uses recursion. It has an average time complexity of O(N * log(N)), making it efficient for large datasets. The algorithm works by selecting a pivot element and partitioning the list around it.
Recursion is essential for quicksort implementation. It's a programming pattern where a function calls itself with modified parameters until reaching a base condition that stops the recursive calls.
Algorithm Steps
To implement QuickSort on a singly-linked list, we follow these steps:
Partition Function: Select the last element as the pivot and rearrange nodes so smaller values come before the pivot and larger values after it.
Recursive Sorting: Apply quicksort recursively to the left side (nodes before pivot) and right side (nodes after pivot).
Base Case: Stop recursion when the sublist has one or no elements.
Combine: The sorted sublists are automatically connected through the partition process.
Implementation
// Node class to create linked list nodes
class Node {
constructor(data) {
this.value = data;
this.next = null;
}
}
// Global head pointer
var head = null;
// Function to add a new node to the linked list
function addNode(value) {
var temp = new Node(value);
if (head == null) {
head = temp;
} else {
var current = head;
while (current.next != null) {
current = current.next;
}
current.next = temp;
}
}
// Function to print the linked list
function print(head) {
var temp = head;
var ll = "";
while (temp.next != null) {
ll += temp.value + " -> ";
temp = temp.next;
}
ll += temp.value + " -> null";
console.log(ll);
}
// Partition function - places pivot in correct position
function partitionLast(first, last) {
if (first == last || first == null || last == null) {
return first;
}
var prev_pivot = first;
var cur = first;
var pivot = last.value;
// Traverse until the last node (pivot)
while (first != last) {
if (first.value < pivot) {
prev_pivot = cur;
// Swap values
var temp = cur.value;
cur.value = first.value;
first.value = temp;
cur = cur.next;
}
first = first.next;
}
// Place pivot in correct position
var temp = cur.value;
cur.value = pivot;
last.value = temp;
return prev_pivot;
}
// Main quicksort function
function quickSort(first, last) {
// Base condition
if (first == null || first == last || first == last.next) {
return;
}
// Partition and get pivot position
var prev_pivot = partitionLast(first, last);
quickSort(first, prev_pivot);
// Sort right side of pivot
if (prev_pivot != null && prev_pivot == first) {
quickSort(prev_pivot.next, last);
} else if (prev_pivot != null && prev_pivot.next != null) {
quickSort(prev_pivot.next.next, last);
}
}
// Create and sort the linked list
addNode(30);
addNode(3);
addNode(4);
addNode(20);
addNode(5);
// Find the last node
var end = head;
while (end.next != null) {
end = end.next;
}
console.log("Linked List before sorting:");
print(head);
quickSort(head, end);
console.log("Linked List after sorting:");
print(head);
Linked List before sorting: 30 -> 3 -> 4 -> 20 -> 5 -> null Linked List after sorting: 3 -> 4 -> 5 -> 20 -> 30 -> null
How It Works
The algorithm partitions the linked list by comparing each node's value with the pivot (last element). Smaller values are moved to the left side, while larger values remain on the right. After partitioning, the pivot is in its final sorted position, and the process repeats recursively on both sides.
Time and Space Complexity
| Case | Time Complexity | Description |
|---|---|---|
| Best/Average | O(N log N) | Balanced partitions |
| Worst | O(N²) | Already sorted or reverse sorted |
The space complexity is O(log N) for the recursion stack in the average case, and O(N) in the worst case.
Conclusion
QuickSort on linked lists is an efficient sorting algorithm with O(N log N) average time complexity. The recursive approach with partitioning makes it suitable for large datasets, though care should be taken to avoid worst-case scenarios.
