QuickSort on Doubly Linked List Last Updated : 17 Sep, 2024 Comments Improve Suggest changes Like Article Like Report Try it on GfG Practice Given a doubly linked list, the task is to sort the doubly linked list in non-decreasing order using the quicksort.Examples:Input: head: 5<->3<->4<->1<->2Output: 1<->2<->3<->4<->5Explanation: Doubly Linked List after sorting using quicksort technique is 1<->2<->3<->4<->5Input: head: 1<->5<->2<->3Output: 1<->2<->3<->5Explanation: Doubly Linked List after sorting using quicksort technique is 1<->2<->3<->5Approach:The quicksort algorithm for a doubly linked list sorts the list by selecting a pivot node and partitioning the list into two segments, nodes less than the pivot and nodes greater than or equal to the pivot. The pivot is placed in its correct position, and then the algorithm recursively sorts the segments on either side of the pivot. This partitioning and recursive sorting continue until the entire list is sorted. The process efficiently handles the doubly linked list by adjusting pointers to maintain the list structure throughout the sorting operation.Below is the implementation of the above approach: C++ // C++ program to sort a doubly linked list // using quicksort #include <iostream> using namespace std; class Node { public: int data; Node* next; Node* prev; Node(int x) { data = x; next = nullptr; prev = nullptr; } }; // Function to swap the data of two nodes void swap(Node* a, Node* b) { // Swap the data in the nodes int temp = a->data; a->data = b->data; b->data = temp; } // Function to partition the list and find pivot Node* partition(Node* low, Node* high) { // Set pivot to the high node int pivot = high->data; // Pointer to place smaller elements Node* i = low->prev; // Traverse the list to rearrange nodes for (Node* j = low; j != high; j = j->next) { // If current node's data is less than or // equal to the pivot if (j->data <= pivot) { // Move i forward and swap with j i = (i == nullptr) ? low : i->next; swap(i, j); } } // Move i to the correct pivot position i = (i == nullptr) ? low : i->next; // Swap pivot with i's data swap(i, high); return i; } // Recursive function to apply quicksort void quickSort(Node* low, Node* high) { // Base case: if the list has one element or // invalid range if (low != nullptr && high != nullptr && low != high && low != high->next) { // Find the partition node (pivot) Node* pivot = partition(low, high); // Recursively sort the left half quickSort(low, pivot->prev); // Recursively sort the right half quickSort(pivot->next, high); } } // Function to get the last node of the list Node* getLastNode(Node* head) { // Traverse to the end of the list while (head != nullptr && head->next != nullptr) { head = head->next; } return head; } void printList(Node* node) { Node* curr = node; while (curr != nullptr) { cout << " " << curr->data; curr = curr->next; } } int main() { // Create a hard-coded doubly linked list: // 5 <-> 3 <-> 4 <-> 1 <-> 2 Node* head = new Node(5); head->next = new Node(3); head->next->prev = head; head->next->next = new Node(4); head->next->next->prev = head->next; head->next->next->next = new Node(1); head->next->next->next->prev = head->next->next; head->next->next->next->next = new Node(2); head->next->next->next->next->prev = head->next->next->next; Node* last = getLastNode(head); quickSort(head, last); printList(head); return 0; } C // C program to sort a doubly linked list // using quicksort #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; struct Node* prev; }; // Function to swap the data of two nodes void swap(struct Node* a, struct Node* b) { // Swap the data in the nodes int temp = a->data; a->data = b->data; b->data = temp; } // Function to partition the list and find pivot struct Node* partition(struct Node* low, struct Node* high) { // Set pivot to the high node int pivot = high->data; // Pointer to place smaller elements struct Node* i = low->prev; // Traverse the list to rearrange nodes for (struct Node* j = low; j != high; j = j->next) { // If current node's data is less than // or equal to the pivot if (j->data <= pivot) { // Move `i` forward and swap with `j` i = (i == NULL) ? low : i->next; swap(i, j); } } // Move `i` to the correct pivot position i = (i == NULL) ? low : i->next; // Swap pivot with `i`'s data swap(i, high); return i; } // Recursive function to apply quicksort void quickSort(struct Node* low, struct Node* high) { // Base case: if the list has one element or // invalid range if (low != NULL && high != NULL && low != high && low != high->next) { // Find the partition node (pivot) struct Node* pivot = partition(low, high); // Recursively sort the left half quickSort(low, pivot->prev); // Recursively sort the right half quickSort(pivot->next, high); } } // Function to get the last node of the list struct Node* getLastNode(struct Node* head) { // Traverse to the end of the list while (head != NULL && head->next != NULL) { head = head->next; } return head; } void printList(struct Node* node) { struct Node* curr = node; while (curr != NULL) { printf("%d ", curr->data); curr = curr->next; } } struct Node* createNode(int new_data) { struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); new_node->data = new_data; new_node->next = NULL; new_node->prev = NULL; return new_node; } int main() { // Create a hard-coded doubly linked list: // 5 <-> 3 <-> 4 <-> 1 <-> 2 struct Node* head = createNode(5); head->next = createNode(3); head->next->prev = head; head->next->next = createNode(4); head->next->next->prev = head->next; head->next->next->next = createNode(1); head->next->next->next->prev = head->next->next; head->next->next->next->next = createNode(2); head->next->next->next->next->prev = head->next->next->next; struct Node* last = getLastNode(head); quickSort(head, last); printList(head); return 0; } Java // Java program to sort a doubly linked list // using quicksort class Node { int data; Node next, prev; Node(int x) { data = x; next = null; prev = null; } } public class GfG { // Function to swap data of two nodes static void swap(Node a, Node b) { // Swap data between `a` and `b` int temp = a.data; a.data = b.data; b.data = temp; } // Function to partition the list around pivot static Node partition(Node low, Node high) { // Set pivot to the data of `high` node int pivot = high.data; // Pointer to place smaller elements Node i = low.prev; // Traverse list from `low` to `high` for (Node j = low; j != high; j = j.next) { // If current data is <= pivot if (j.data <= pivot) { // Move `i` forward and swap with `j` i = (i == null) ? low : i.next; swap(i, j); } } // Move `i` to correct pivot position i = (i == null) ? low : i.next; // Swap pivot data with `i`'s data swap(i, high); return i; } // Recursive quicksort function static void quickSort(Node low, Node high) { // Base case: stop recursion when invalid range if (low != null && high != null && low != high && low != high.next) { // Partition the list and get the pivot node Node pivot = partition(low, high); // Recursively sort the left half quickSort(low, pivot.prev); // Recursively sort the right half quickSort(pivot.next, high); } } // Function to get the last node of the list static Node getLastNode(Node head) { // Traverse to the end of the list while (head != null && head.next != null) { head = head.next; } return head; } static void printList(Node node) { Node curr = node; while (curr != null) { System.out.print(" " + curr.data); curr = curr.next; } } public static void main(String[] args) { // Create a hard-coded doubly linked list: // 5 <-> 3 <-> 4 <-> 1 <-> 2 Node head = new Node(5); head.next = new Node(3); head.next.prev = head; head.next.next = new Node(4); head.next.next.prev = head.next; head.next.next.next = new Node(1); head.next.next.next.prev = head.next.next; head.next.next.next.next = new Node(2); head.next.next.next.next.prev = head.next.next.next; Node last = getLastNode(head); quickSort(head, last); printList(head); } } Python # Python program to sort a doubly linked list # using quicksort class Node: def __init__(self, data): self.data = data self.next = None self.prev = None # Function to swap data between two nodes def swap(a, b): # Swap the data between node `a` and node `b` a.data, b.data = b.data, a.data # Partition function for quicksort def partition(low, high): # Set pivot as the data of `high` node pivot = high.data # Pointer to place smaller elements i = low.prev # Traverse from `low` to `high` curr = low while curr != high: # If current node's data is <= pivot if curr.data <= pivot: # Move `i` forward and swap with `curr` i = low if i is None else i.next swap(i, curr) curr = curr.next # Move `i` to the correct pivot position i = low if i is None else i.next # Swap pivot data with `i`'s data swap(i, high) return i # Recursive quicksort function def quick_sort(low, high): # Base case: stop when invalid range if low and high and low != high and low != high.next: # Partition the list and get the pivot node pivot = partition(low, high) # Recursively sort the left half quick_sort(low, pivot.prev) # Recursively sort the right half quick_sort(pivot.next, high) # Function to get the last node of the list def get_last_node(head): # Traverse to the last node while head and head.next: head = head.next return head def print_list(node): curr = node while curr: print(curr.data, end=" ") curr = curr.next if __name__ == '__main__': # Create a hard-coded doubly linked list: # 5 <-> 3 <-> 4 <-> 1 <-> 2 head = Node(5) head.next = Node(3) head.next.prev = head head.next.next = Node(4) head.next.next.prev = head.next head.next.next.next = Node(1) head.next.next.next.prev = head.next.next head.next.next.next.next = Node(2) head.next.next.next.next.prev = head.next.next.next last_node = get_last_node(head) quick_sort(head, last_node) print_list(head) C# // C# program to sort a singly linked list // using quicksort using System; public class Node { public int data; public Node next; public Node(int new_data) { data = new_data; next = null; } } class GfG { // Function to swap data between two nodes static void Swap(Node a, Node b) { // Swap data between node `a` and node `b` int temp = a.data; a.data = b.data; b.data = temp; } // Partition function for quicksort static Node Partition(Node low, Node high) { // Set pivot as the data of `high` node int pivot = high.data; // Pointer to place smaller elements Node i = low; // Traverse from `low` to `high` Node curr = low; while (curr != high) { // If current node's data is <= pivot if (curr.data <= pivot) { // Swap data between `i` and `curr` Swap(i, curr); // Move `i` forward i = i.next; } curr = curr.next; } // Swap pivot data with `i`'s data Swap(i, high); return i; } // Recursive quicksort function static void QuickSort(Node low, Node high) { // Base case: stop when invalid range if (low != high && low != null && high != null) { // Partition the list and get the pivot node Node pivot = Partition(low, high); // Recursively sort the left half Node beforePivot = low; while (beforePivot != null && beforePivot.next != pivot) { beforePivot = beforePivot.next; } // Sort left of pivot only if exists if (beforePivot != null && beforePivot != pivot) QuickSort(low, beforePivot); // Recursively sort the right half if (pivot != null && pivot.next != high) QuickSort(pivot.next, high); } } // Function to get the last node of the list static Node GetLastNode(Node head) { // Traverse the list to find the last node while (head != null && head.next != null) { head = head.next; } return head; } static void PrintList(Node node) { Node curr = node; while (curr != null) { Console.Write(" " + curr.data); curr = curr.next; } } static void Main(string[] args) { // Create a hard-coded linked list: // 5 -> 3 -> 4 -> 1 -> 2 Node head = new Node(5); head.next = new Node(3); head.next.next = new Node(4); head.next.next.next = new Node(1); head.next.next.next.next = new Node(2); Node lastNode = GetLastNode(head); QuickSort(head, lastNode); PrintList(head); } } JavaScript // JavaScript program to sort a doubly linked list // using quicksort class Node { constructor(data) { this.data = data; this.next = null; this.prev = null; } } // Function to swap the data between two nodes function swap(a, b) { let temp = a.data; a.data = b.data; b.data = temp; } // Partition function for quicksort function partition(low, high) { // Set pivot as the data of `high` node let pivot = high.data; // Pointer to place smaller elements let i = low.prev; // Traverse from `low` to `high` for (let j = low; j !== high; j = j.next) { if (j.data <= pivot) { i = (i === null) ? low : i.next; swap(i, j); } } // Swap pivot data with `i.next`'s data i = (i === null) ? low : i.next; swap(i, high); return i; } // Recursive quicksort function function quickSort(low, high) { if (low !== null && high !== null && low !== high && low !== high.next) { let pivot = partition(low, high); // Sort left side of the pivot quickSort(low, pivot.prev); // Sort right side of the pivot quickSort(pivot.next, high); } } // Function to get the last node of the list function getLastNode(head) { while (head !== null && head.next !== null) { head = head.next; } return head; } function printList(node) { let curr = node; while (curr !== null) { console.log(" " + curr.data); curr = curr.next; } } // Create a hard-coded doubly linked list: // 5 <-> 3 <-> 4 <-> 1 <-> 2 let head = new Node(5); head.next = new Node(3); head.next.prev = head; head.next.next = new Node(4); head.next.next.prev = head.next; head.next.next.next = new Node(1); head.next.next.next.prev = head.next.next; head.next.next.next.next = new Node(2); head.next.next.next.next.prev = head.next.next.next; let lastNode = getLastNode(head); quickSort(head, lastNode); printList(head); Output 1 2 3 4 5Time Complexity: On average, quicksort has a time complexity of O(nlogn), where n is the number of nodes. In the worst case (e.g., already sorted list), it becomes O(n²).Auxiliary Space: O(logn) due to the recursion stack in average cases, and O(n) in the worst case. Comment More infoAdvertise with us Next Article Nuts & Bolts Problem (Lock & Key problem) using Quick Sort kartik Follow Improve Article Tags : Linked List Sorting DSA HSBC Quick Sort doubly linked list Linked-List-Sorting +3 More Practice Tags : HSBCLinked ListSorting Similar Reads Quick Sort QuickSort is a sorting algorithm based on the Divide and Conquer that picks an element as a pivot and partitions the given array around the picked pivot by placing the pivot in its correct position in the sorted array. It works on the principle of divide and conquer, breaking down the problem into s 12 min read Time and Space Complexity Analysis of Quick Sort The time complexity of Quick Sort is O(n log n) on average case, but can become O(n^2) in the worst-case. The space complexity of Quick Sort in the best case is O(log n), while in the worst-case scenario, it becomes O(n) due to unbalanced partitioning causing a skewed recursion tree that requires a 4 min read Application and uses of Quicksort Quicksort: Quick sort is a Divide Conquer algorithm and the fastest sorting algorithm. In quick sort, it creates two empty arrays to hold elements less than the pivot element and the element greater than the pivot element and then recursively sort the sub-arrays. There are many versions of Quicksort 2 min read QuickSort using different languagesC++ Program for Quick SortQuick Sort is one of the most efficient sorting algorithms available to sort the given dataset. It is known for its efficiency in handling large datasets which made it a go-to choice for programmers looking to optimize their code.In C++, the STL's sort() function uses a mix of different sorting algo 4 min read Java Program for QuickSortLike Merge Sort, QuickSort is a Divide and Conquer algorithm. It picks an element as pivot and partitions the given array around the picked pivot. There are many different versions of QuickSort that pick pivot in different ways.Always pick first element as pivot.Always pick last element as pivot (im 2 min read QuickSort - PythonQuickSort is a sorting algorithm based on the Divide and Conquer that picks an element as a pivot and partitions the given array around the picked pivot by placing the pivot in its correct position in the sorted array.How does QuickSort Algorithm work?QuickSort works on the principle of divide and c 4 min read p5.js | Quick SortQuickSort is a Divide and Conquer algorithm. It picks an element as pivot and partitions the given array around the picked pivot. There are many different versions of quickSort that pick pivot in different ways. Always pick first element as pivot. Always pick last element as pivot. Pick a random ele 3 min read Iterative QuickSortIterative Quick SortFollowing is a typical recursive implementation of Quick Sort that uses last element as pivot. C++// CPP code for recursive function of Quicksort #include <bits/stdc++.h> using namespace std; /* This function takes last element as pivot, places the pivot element at its correct position in sort 15+ min read C Program for Iterative Quick SortC // An iterative implementation of quick sort #include <stdio.h> // A utility function to swap two elements void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; } /* This function is same in both iterative and recursive*/ int partition(int arr[], int l, int h) { int x = arr[h]; int i = (l 4 min read Java Program for Iterative Quick SortBelow is the implementation of Iterative Quick Sort:Java// Java implementation of iterative quick sort import java.io.*; public class IterativeQuickSort { void swap(int arr[], int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } /* This function is same in both iterative and recursive*/ in 3 min read Python Program for Iterative Quick SortThe code consists of two main functions: partition and quickSortIterative, along with a driver code to test the sorting process. The partition function is used for the process of partitioning a given subarray into two parts - elements less than or equal to the chosen pivot (arr[h]) on the left and e 4 min read Different implementations of QuickSortQuickSort using Random PivotingIn this article, we will discuss how to implement QuickSort using random pivoting. In QuickSort we first partition the array in place such that all elements to the left of the pivot element are smaller, while all elements to the right of the pivot are greater than the pivot. Then we recursively call 15+ min read QuickSort Tail Call Optimization (Reducing worst case space to Log n )Prerequisite : Tail Call EliminationIn QuickSort, partition function is in-place, but we need extra space for recursive function calls. A simple implementation of QuickSort makes two calls to itself and in worst case requires O(n) space on function call stack. The worst case happens when the selecte 11 min read Implement Quicksort with first element as pivotQuickSort is a Divide and Conquer algorithm. It picks an element as a pivot and partitions the given array around the pivot. There are many different versions of quickSort that pick the pivot in different ways. Always pick the first element as a pivot.Always pick the last element as a pivot.Pick a 13 min read Advanced Quick Sort (Hybrid Algorithm)Prerequisites: Insertion Sort, Quick Sort, Selection SortIn this article, a Hybrid algorithm with the combination of quick sort and insertion sort is implemented. As the name suggests, the Hybrid algorithm combines more than one algorithm. Why Hybrid algorithm: Quicksort algorithm is efficient if th 9 min read Quick Sort using Multi-threadingQuickSort is a popular sorting technique based on divide and conquer algorithm. In this technique, an element is chosen as a pivot and the array is partitioned around it. The target of partition is, given an array and an element x of the array as a pivot, put x at its correct position in a sorted ar 9 min read Stable QuickSortA sorting algorithm is said to be stable if it maintains the relative order of records in the case of equality of keys.Input : (1, 5), (3, 2) (1, 2) (5, 4) (6, 4) We need to sort key-value pairs in the increasing order of keys of first digit There are two possible solution for the two pairs where th 9 min read Dual pivot QuicksortAs we know, the single pivot quick sort takes a pivot from one of the ends of the array and partitioning the array, so that all elements are left to the pivot are less than or equal to the pivot, and all elements that are right to the pivot are greater than the pivot.The idea of dual pivot quick sor 10 min read 3-Way QuickSort (Dutch National Flag)In simple QuickSort algorithm, we select an element as pivot, partition the array around a pivot and recur for subarrays on the left and right of the pivot. Consider an array which has many redundant elements. For example, {1, 4, 2, 4, 2, 4, 1, 2, 4, 1, 2, 2, 2, 2, 4, 1, 4, 4, 4}. If 4 is picked as 15+ min read Visualization of QuickSortSorting Algorithm Visualization : Quick SortAn algorithm like Quicksort algorithm is hard to understand theoretically. We can understand easily by visualizing such kind of algorithms. In this article, a program that visualizes the Quicksort Algorithm has been implemented.The Graphical User Interface(GUI) is implemented in python using pygame 3 min read Visualizing Quick Sort using Tkinter in PythonPrerequisite: QuickSort Tkinter is a very easy-to-use and beginner-friendly GUI library that can be used to visualize the sorting algorithms. Here Quick Sort Algorithm is visualized which is a divide and conquer algorithm. It first considers a pivot element then, creates two subarrays to hold elemen 7 min read Visualization of Quick sort using MatplotlibVisualizing algorithms makes it easier to understand them by analyzing and comparing the number of operations that took place to compare and swap the elements. For this we will use matplotlib, to plot bar graphs to represent the elements of the array,  Approach : We will generate an array with rand 3 min read 3D Visualisation of Quick Sort using Matplotlib in PythonVisualizing algorithms makes it easier to understand them by analyzing and comparing the number of operations that took place to compare and swap the elements. 3D visualization of algorithms is less common, for this we will use Matplotlib to plot bar graphs and animate them to represent the elements 3 min read Partitions in QuickSortHoare's vs Lomuto partition scheme in QuickSortWe have discussed the implementation of QuickSort using Lomuto partition scheme. Lomuto's partition scheme is easy to implement as compared to Hoare scheme. This has inferior performance to Hoare's QuickSort.Lomuto's Partition Scheme:This algorithm works by assuming the pivot element as the last ele 15+ min read Quick Sort(Hoare's Partition) Visualization using JavaScriptGUI(Graphical User Interface) helps in better understanding than programs. In this article, we will visualize Quick Sort using JavaScript. We will see how the array is being partitioned into two parts and how we get the final sorted array. We will also visualize the time complexity of Quick Sort. Re 4 min read Quick Sort(Lomuto Partition) Visualization using JavaScriptGUI(Graphical User Interface) helps in better in understanding than programs. In this article, we will visualize Quick Sort using JavaScript. We will see how the array is being partitioned using Lomuto Partition and then how we get the final sorted array. We will also visualize the time complexity o 4 min read Implement Various Types of Partitions in Quick Sort in JavaQuicksort is a Divide and Conquer Algorithm that is used for sorting the elements. In this algorithm, we choose a pivot and partitions the given array according to the pivot. Quicksort algorithm is a mostly used algorithm because this algorithm is cache-friendly and performs in-place sorting of the 7 min read Some problems on QuickSortQuickSort on Singly Linked ListGiven a linked list, apply the Quick sort algorithm to sort the linked list. To sort the Linked list change pointers rather than swapping data.Example:Input: 5->4->1->3->2Output: 1->2->3->4->5Input: 4->3->2->1Output: 1->2->3->4Approach:The Quick Sort algorit 13 min read QuickSort on Doubly Linked ListGiven a doubly linked list, the task is to sort the doubly linked list in non-decreasing order using the quicksort.Examples:Input: head: 5<->3<->4<->1<->2Output: 1<->2<->3<->4<->5Explanation: Doubly Linked List after sorting using quicksort technique i 12 min read Nuts & Bolts Problem (Lock & Key problem) using Quick SortGiven a set of n nuts of different sizes and n bolts of different sizes. There is a one-one mapping between nuts and bolts. Match nuts and bolts efficiently. Constraint: Comparison of a nut to another nut or a bolt to another bolt is not allowed. It means a nut can only be compared with a bolt and a 12 min read Is Quick Sort Algorithm Adaptive or not Adaptive sorting algorithms are designed to take advantage of existing order in the input data. This means, if the array is already sorted or partially sorted, an adaptive algorithm will recognize that and sort the array faster than it would for a completely random array.Quick Sort is not an adaptiv 6 min read Like