Logo

dev-resources.site

for different kinds of informations.

Understanding Quick Sort in Kotlin : A Beginner's Guide

Published at
1/11/2025
Categories
kotlin
algorithms
Author
wolfof420street
Categories
2 categories in total
kotlin
open
algorithms
open
Author
15 person written this
wolfof420street
open
Understanding Quick Sort in Kotlin : A Beginner's Guide

What is QuickSort?

QuickSort is a highly efficient, comparison-based sorting algorithm that uses a divide-and-conquer strategy. Developed by Tony Hoare in 1959, it has become one of the most widely used sorting algorithms due to its excellent average-case performance and efficient memory usage.

The algorithm works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays according to whether they are less than or greater than the pivot. The sub-arrays are then recursively sorted.

When to Use QuickSort?

QuickSort is an excellent general-purpose sorting algorithm with several ideal use cases:

  • Large Datasets: QuickSort's O(n log n) average time complexity makes it efficient for large arrays.

  • Limited Memory: Its in-place sorting capability makes it memory efficient.

  • Random Access Memory: QuickSort performs well when accessing elements at arbitrary positions.

However, it may not be the best choice when stable sorting is required or when dealing with nearly sorted data.

How QuickSort Works

QuickSort employs a divide-and-conquer strategy through partitioning around a pivot element.

Step-by-Step Explanation

  1. Choose Pivot:

    • Select a pivot element from the array (commonly first, last, or middle element).
  2. Partition:

    • Rearrange elements so that all elements smaller than the pivot are on the left.
    • All elements larger than the pivot are on the right.
  3. Recursive Sort:

    • Recursively apply the same process to the sub-arrays on either side of the pivot.

Visual Representation of QuickSort

To sort the array [64, 34, 25, 12, 22] with last element as pivot:

  1. First partition (pivot = 22):
    • Result: [12, 34, 25, 64, 22] โ†’ [12, 22, 25, 64, 34]
  2. Recursively sort left and right partitions

Pseudocode for QuickSort

function quickSort(arr, low, high):
    if low < high:
        pivot_index = partition(arr, low, high)
        quickSort(arr, low, pivot_index - 1)
        quickSort(arr, pivot_index + 1, high)

function partition(arr, low, high):
    pivot = arr[high]
    i = low - 1
    for j from low to high - 1:
        if arr[j] <= pivot:
            i = i + 1
            swap arr[i] with arr[j]
    swap arr[i + 1] with arr[high]
    return i + 1
Enter fullscreen mode Exit fullscreen mode

Implementing QuickSort in Kotlin

fun quickSort(arr: IntArray, low: Int = 0, high: Int = arr.size - 1) {
    if (low < high) {
        val pivotIndex = partition(arr, low, high)
        quickSort(arr, low, pivotIndex - 1)
        quickSort(arr, pivotIndex + 1, high)
    }
}

fun partition(arr: IntArray, low: Int, high: Int): Int {
    val pivot = arr[high]
    var i = low - 1

    for (j in low until high) {
        if (arr[j] <= pivot) {
            i++
            // Swap elements
            arr[i] = arr[j].also { arr[j] = arr[i] }
        }
    }
    // Place pivot in correct position
    arr[i + 1] = arr[high].also { arr[high] = arr[i + 1] }
    return i + 1
}
Enter fullscreen mode Exit fullscreen mode

Code Walkthrough

  • Main Function:

    • Recursively divides array into smaller partitions.
    • Continues until partitions are of size 1 or 0.
  • Partition Function:

    • Selects last element as pivot.
    • Places smaller elements to left, larger to right.
    • Returns final position of pivot.

Visual Step-by-Step Process

Initial Array: [64, 34, 25, 12, 22]

First Partition:

[64, 34, 25, 12, 22]  // Choose 22 as pivot
                   โ†“
[12, 34, 25, 64, 22]  // Arrange elements around pivot
 โ†“           โ†‘   โ†“
[12, 22, 25, 64, 34]  // Pivot in final position
     โ†“
Enter fullscreen mode Exit fullscreen mode

Recursive Partitions:

Left: [12]           // Already sorted
Right: [25, 64, 34]  // Continue partitioning
      [25, 34, 64]   // Final sorted array
Enter fullscreen mode Exit fullscreen mode

Legend:

  • โ†“ : Pivot element
  • โ†‘ : Elements being compared
  • Unmarked: Unsorted elements

Time Complexity Analysis

Best Case: O(n log n)

  • Occurs when pivot consistently divides array into equal halves
  • Each level of recursion processes n elements
  • log n levels of recursion

Worst Case: O(nยฒ)

  • Occurs when pivot is always smallest/largest element
  • Each partition removes only one element
  • n levels of recursion required

Average Case: O(n log n)

  • Random pivot selection typically provides good partitioning
  • Balanced division of array in most cases

Space Complexity: O(log n)

  • Recursive call stack in balanced cases
  • O(n) in worst case with unbalanced partitioning

Detailed Performance Breakdown

Number of Operations

For an array of size n:

  1. Comparisons:

    • Best case: n log n
    • Worst case: nยฒ/2
    • Average case: 1.386n log n
  2. Swaps:

    • Best case: n log n
    • Worst case: nยฒ/2
    • Average case: 0.693n log n

Performance Table

Array Size (n) Best Case (n log n) Average Case Worst Case (nยฒ)
10 33 46 100
100 664 921 10,000
1,000 9,966 13,812 1,000,000

Optimization Techniques

  1. Median-of-Three Pivot Selection
fun medianOfThree(arr: IntArray, low: Int, high: Int): Int {
    val mid = (low + high) / 2
    if (arr[low] > arr[mid]) swap(arr, low, mid)
    if (arr[mid] > arr[high]) swap(arr, mid, high)
    if (arr[low] > arr[mid]) swap(arr, low, mid)
    return mid
}
Enter fullscreen mode Exit fullscreen mode
  1. Three-Way Partitioning
fun quickSort3Way(arr: IntArray, low: Int, high: Int) {
    if (high <= low) return

    var lt = low
    var gt = high
    val pivot = arr[low]
    var i = low + 1

    while (i <= gt) {
        when {
            arr[i] < pivot -> swap(arr, lt++, i++)
            arr[i] > pivot -> swap(arr, i, gt--)
            else -> i++
        }
    }

    quickSort3Way(arr, low, lt - 1)
    quickSort3Way(arr, gt + 1, high)
}
Enter fullscreen mode Exit fullscreen mode

Comparison with Other Sorting Algorithms

Algorithm Average Case Worst Case Space Stable In-Place
QuickSort O(n log n) O(nยฒ) O(log n) No Yes
MergeSort O(n log n) O(n log n) O(n) Yes No
HeapSort O(n log n) O(n log n) O(1) No Yes
InsertionSort O(nยฒ) O(nยฒ) O(1) Yes Yes

Advantages and Disadvantages of QuickSort

Advantages:

  • Excellent average case performance
  • In-place sorting with minimal additional memory
  • Cache-friendly due to good locality of reference
  • Parallelizable for multi-threaded implementations

Disadvantages:

  • Unstable - doesn't preserve order of equal elements
  • Poor performance on already sorted or nearly sorted data
  • Vulnerable to poor pivot selection
  • Recursive nature can lead to stack overflow

Conclusion

QuickSort remains one of the most practical and efficient sorting algorithms available. Its combination of good average-case performance, in-place sorting, and cache efficiency makes it a popular choice in many programming languages' standard libraries. While it has some drawbacks, various optimizations and hybrid approaches have been developed to address these limitations, cementing QuickSort's position as a cornerstone of modern sorting implementations.

kotlin Article's
30 articles in total
Favicon
Using SVGs on Canvas with Compose Multiplatform
Favicon
Kotlin Generics Simplified
Favicon
Understanding Quick Sort in Kotlin : A Beginner's Guide
Favicon
Understanding Selection Sort in Kotlin: A Beginner's Guide
Favicon
Wednesday Links - Edition 2025-01-08
Favicon
Testing Pi Logic integrations.
Favicon
Understanding (a bit of) the Gradle Kotlin DSL
Favicon
Android TreeView(Hierarchy based) with Kotlin
Favicon
Creando un notebook con Jupyter y Kotlin
Favicon
Getting Started with Android Testing: Building Reliable Apps with Confidence (Part 3/3)
Favicon
Getting Started with Android Testing: Building Reliable Apps with Confidence (Part 2/3)
Favicon
Understanding Room Database in Android: A Beginner's Guide
Favicon
Fixing Rounded Navigation Bar Corner Padding in Jetpack Compose
Favicon
Getting Started with Android Testing: Building Reliable Apps with Confidence (Part 1/3)
Favicon
My conference year
Favicon
Authentication in Android Project with Firebase.
Favicon
Learn Firebase for Android Development from Scratch, a beginner guide.
Favicon
๐Ÿงน Improve Filtering with the Predicate Interface!
Favicon
How to make the best of a slow machine running on limited resources with a Windows environment as a Java Engineer
Favicon
How to implement detekt in Spring Boot + Kotlin + Gradle project
Favicon
How to Create and Publish an Android Library for Beginners
Favicon
Pub-sub Redis in Micronaut
Favicon
ISBN Stacks โ€” A look at a possible Spring Application implementation without annotations
Favicon
Protecting Applications with Kong security plugins and using StatsD to monitor system states โ€” A healthy camera story
Favicon
Configurable Kong API Gateway with Micronaut Services in Kotlin โ€” A very odd Yucca tribute concert
Favicon
Learning AWS with Localstack and Reactive Kotlin โ€” A stamps and coins implementation
Favicon
Coroutines, Distributed Cache, Resilience, and Replication in Kotlin โ€” Making a VMAโ€™s application
Favicon
From Paris to Berlin โ€” Creating Circuit-Breakers in Kotlin
Favicon
Understanding Merge Sort in Kotlin: A Beginner's Guide
Favicon
City Library โ€” An advanced guide to Circuit Breakers in Kotlin

Featured ones: