Quicksort is a widely used sorting algorithm that follows the divide-and-conquer paradigm. It works by selecting a pivot element from the array and partitioning the other elements into two subarrays based on their relationship to the pivot. The subarray containing elements smaller than the pivot is placed to its left, while the subarray with elements greater than the pivot is placed to its right. This process is recursively applied to the subarrays until the entire array is sorted.
Here is a step-by-step explanation of the quick-sort algorithm:
We choose a pivot element from the array. There are various ways to select the pivot, such as choosing the first, last, or middle element of the array.
We partition the array by rearranging its elements such that all elements less than the pivot come before it, and all elements greater than the pivot come after it. The pivot should be in its final sorted position.
We recursively apply the above steps to the subarray on the left side of the pivot (elements smaller than the pivot) and the subarray on the right side of the pivot (elements greater than the pivot).
We continue partitioning and sorting the subarrays until the base case is reached, which occurs when a subarray has only one element or is empty.
Once the recursive calls are complete, the entire array is sorted in ascending order.
The quicksort algorithm can be used to sort data structures other than arrays. While the traditional implementation of quicksort is commonly used to sort arrays, the underlying partitioning and recursive approach can be adapted to sort other data structures.
Some examples of data structures that can be sorted using the quicksort algorithm include:
In each case, the specific implementation details may vary depending on the data structure being used. Adapting the quicksort algorithm to sort these data structures requires consideration of the data structure’s properties and careful manipulation of the elements within the structure.
Let’s take an example of a binary search tree (BST) on which we want to implement the quicksort algorithm. The following code solves this problem:
class Node:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef insert(root, value):if root is None:return Node(value)if value < root.value:root.left = insert(root.left, value)else:root.right = insert(root.right, value)return rootdef postorder(root, array):if root:postorder(root.left, array)postorder(root.right, array)array.append(root.value)def inorder(root, array):if root:inorder(root.left, array)array.append(root.value)inorder(root.right, array)def quicksort_tree(root):if root is None:return Nonearray = []postorder(root, array)sorted_array = quicksort(array)return construct_tree(sorted_array, 0, len(sorted_array) - 1)def quicksort(array):if len(array) <= 1:return arraypivot = array[len(array) // 2]less = [x for x in array if x < pivot]equal = [x for x in array if x == pivot]greater = [x for x in array if x > pivot]return quicksort(less) + equal + quicksort(greater)def construct_tree(array, start, end):if start > end:return Nonemid = (start + end) // 2root = Node(array[mid])root.left = construct_tree(array, start, mid - 1)root.right = construct_tree(array, mid + 1, end)return root# Example usageroot = Noneroot = insert(root, 4)root = insert(root, 2)root = insert(root, 1)root = insert(root, 3)root = insert(root, 6)root = insert(root, 5)root = insert(root, 7)print("Original BST:")def print_tree_postorder(root):if root:print_tree_postorder(root.left)print_tree_postorder(root.right)print(root.value, end=" ")print_tree_postorder(root)print()sorted_bst = quicksort_tree(root)print("Sorted BST:")def print_tree_inorder(root):if root:print_tree_inorder(root.left)print(root.value, end=" ")print_tree_inorder(root.right)print_tree_inorder(sorted_bst)
Lines 1–5: We define a class Node
that represents a node in a binary tree. Each Node
object has three attributes: value
(stores the value associated with the node), left
( a reference to the left child node), and right
(a reference to the right child node).
Lines 7–14: The insert()
function takes a root
node and the value
attribute as parameters. It recursively inserts a new node with the given value into the binary tree rooted at the root
node, maintaining the binary search tree property, and returns the modified root node.
Lines 16-26: We define the post-order and in-order traversals for the binary search trees.
Lines 28–46: The quicksort_tree()
function takes a root
node as input. If the root
node is None
, it returns None
. Otherwise, it performs a post-order traversal of the tree, storing the node values in an array. It then applies the quicksort algorithm to the array to obtain a sorted array.
Lines 59–66: We create an example binary search tree on which the quicksort algorithm is implemented.
Free Resources