Quicksort On Singly Linked List In C++

Sorting is a fundamental operation in computer science and finds its epitome in QuickSort. Quicksort is a divide-and-conquer algorithm renowned for its efficiency. Extending QuickSort to linked lists is a valuable skill, though it is conventionally applied to arrays. In this article, we delve into the implementation of QuickSort on singly linked lists in C++, providing a comprehensive guide with code, examples, and outputs.

What is a QuickSort?

QuickSort's essence lies in dividing the dataset and recursively sorting subsets. The algorithm designates a 'pivot' element, partitioning the other elements into sub-arrays based on their relation to the pivot. QuickSort's efficiency emanates from its in-place sorting and the ability to sort elements concurrently during partitioning.

Implementing QuickSort on Singly Linked Lists

To adapt QuickSort to singly linked lists, crucial functions need definition: one for partitioning the list, another for selecting a pivot, and the primary QuickSort function for recursive sorting. Let's explore the C++ code:

Code:

Example

#include <iostream>
 
// Node structure for the singly linked list
struct Node {
    int data;
    Node* next;
    
    Node(int value) : data(value), next(nullptr) {}
};
 
// Function to find the last node of the linked list
Node* getTail(Node* head) {
    while (head != nullptr && head->next != nullptr) {
        head = head->next;
    }
    return head;
}
 
// Function to partition the linked list and return the pivot node
Node* partition(Node* head, Node* end, Node** newHead, Node** newEnd) {
    Node* pivot = end;
    Node* prev = nullptr, *cur = head, *tail = pivot;
 
    while (cur != pivot) {
        if (cur->data < pivot->data) {
            if (*newHead == nullptr)
                *newHead = cur;
 
            prev = cur;
            cur = cur->next;
        } else {
            if (prev)
                prev->next = cur->next;
            Node* temp = cur->next;
            cur->next = nullptr;
            tail->next = cur;
            tail = cur;
            cur = temp;
        }
    }
 
    if (*newHead == nullptr)
        *newHead = pivot;
 
    *newEnd = tail;
 
    return pivot;
}
 
// Recursive function to perform QuickSort on the linked list
Node* quickSortRecur(Node* head, Node* end) {
    if (!head || head == end)
        return head;
 
    Node* newHead = nullptr, *newEnd = nullptr;
 
    Node* pivot = partition(head, end, &newHead, &newEnd);
 
    if (newHead != pivot) {
        Node* temp = newHead;
        while (temp->next != pivot)
            temp = temp->next;
        temp->next = nullptr;
 
        newHead = quickSortRecur(newHead, temp);
 
        temp = getTail(newHead);
        temp->next = pivot;
    }
 
    pivot->next = quickSortRecur(pivot->next, newEnd);
 
    return newHead;
}
 
// Wrapper function for QuickSort on a linked list
void quickSort(Node** headRef) {
    *headRef = quickSortRecur(*headRef, getTail(*headRef));
}
 
// Function to print the linked list
void printList(Node* node) {
    while (node != nullptr) {
        std::cout << node->data << " ";
        node = node->next;
    }
    std::cout << std::endl;
}
 
// Function to add a new node to the linked list
void push(Node** headRef, int newData) {
    Node* newNode = new Node(newData);
    newNode->next = *headRef;
    *headRef = newNode;
}
 
// Driver code
int main() {
    Node* head = nullptr;
 
    // Adding elements to the linked list
    push(&head, 12);
    push(&head, 9);
    push(&head, 15);
    push(&head, 5);
    push(&head, 6);
 
    std::cout << "Linked List before sorting: ";
    printList(head);
 
    quickSort(&head);
 
    std::cout << "Linked List after sorting: ";
    printList(head);
 
    return 0;
}

Output:

Output

Linked List before sorting: 12 9 15 5 6
Linked List after sorting: 5 6 9 12 15

Conclusion:

In conclusion, the incorporation of QuickSort into singly linked lists using C++ enriches one's comprehension of sorting algorithms. In the provided code, the complex evidence involving meticulous handling of pointers and recursive calls highlights QuickSort's adaptability to various data structures. QuickSort emerges as a potent solution for efficiently sorting extensive datasets with an average-case time complexity of O(n log n).

The exemplified scenario and resultant output vividly demonstrate the algorithm's capability to seamlessly transform an unorganized linked list into a sorted one. Proficiency in such adaptations signifies a robust understanding of algorithmic principles, equipping developers with versatile tools for effective data manipulation.

In the realm of computer science, QuickSort maintains its prominence, and its extension to linked lists showcases the flexibility essential for addressing diverse computational challenges. By delving into the understanding and implementation of such algorithms, developers not only enhance their proficiency in algorithms but also underscore the sophistication and efficacy inherent in streamlined sorting strategies. The exploration of QuickSort on linked lists not only refines algorithmic skills but also accentuates the grace and potency embedded in adept sorting methodologies.

Input Required

This code uses input(). Please provide values below: