Quick Sort
Terakhir diperbarui
Quicksort adalah algoritma divide and conquer yang mengurutkan di sekitar sebuah "pivot". Algoritma ini memilih satu elemen pivot, lalu mempartisi array sehingga semua yang lebih kecil berada sebelum pivot dan semua yang lebih besar berada setelahnya, dan langkah ini mengunci pivot di posisi akhirnya yang terurut. Setelah itu, algoritma ini berjalan secara rekursif pada partisi kiri dan kanan. Visualisasi ini memakai skema Lomuto dengan elemen terakhir sebagai pivot. Tekan Putar untuk melihat proses partisi dan penempatan pivot.
Dalam praktik, quicksort biasanya menjadi algoritma pengurutan umum tercepat berkat perilaku cache yang baik dan partisi in-place, dengan rata-rata O(n log n). Kasus terburuknya O(n²) (misalnya array yang sudah terurut dengan pilihan pivot yang buruk), yang bisa dihindari dengan strategi pivot yang baik seperti median-of-three atau pengacakan.
Kompleksitas waktu dan ruang
| Kasus | Kompleksitas | Catatan |
|---|---|---|
| Kasus terbaik | O(n log n) | Partisi seimbang |
| Kasus rata-rata | O(n log n) | Urutan acak |
| Kasus terburuk | O(n²) | Pivot yang terus-menerus tidak seimbang |
| Ruang | O(log n) | Stack rekursi (partisi in-place) |
| Stabil | Tidak | Penukaran saat partisi mengubah urutan elemen yang sama |
Langkah demi langkah
| Langkah | Apa yang terjadi |
|---|---|
| 1 | Pilih pivot (di sini, elemen terakhir dari rentang). |
| 2 | Partisi: pindahkan semua elemen yang lebih kecil daripada pivot ke kirinya. |
| 3 | Tukar pivot ke batas partisi: pivot kini berada di posisi akhirnya. |
| 4 | Jalankan quicksort secara rekursif pada partisi kiri. |
| 5 | Jalankan quicksort secara rekursif pada partisi kanan. |
Contoh penerapan
Mengurutkan [5, 2, 4, 1] dengan skema Lomuto (elemen terakhir sebagai pivot):
| Putaran | Array | Aksi |
|---|---|---|
| Mulai | [5, 2, 4, 1] | Partisi seluruh rentang; pivot-nya 1 (elemen terakhir). |
| 1 | [1, 2, 4, 5] | Tidak ada yang lebih kecil daripada 1, jadi tukar 1 ke indeks 0; pivot 1 kini final. Lanjutkan secara rekursif ke kanan pada [2, 4, 5]. |
| 2 | [1, 2, 4, 5] | Partisi [2, 4, 5] dengan pivot 5; 2 dan 4 sama-sama lebih kecil, jadi 5 tetap di akhir dan sudah final. Lanjutkan secara rekursif ke kiri pada [2, 4]. |
| 3 | [1, 2, 4, 5] | Partisi [2, 4] dengan pivot 4; 2 lebih kecil, jadi 4 tetap di tempatnya dan sudah final. 2 adalah satu elemen, jadi sudah terurut. |
| Selesai | [1, 2, 4, 5] | Setiap pivot sudah terkunci di tempatnya; array sudah terurut. |
Kapan memakai quicksort
| Pakai saat | Hindari saat |
|---|---|
| Kamu butuh pengurutan umum yang cepat di memori dengan faktor konstanta kecil. | Kamu butuh waktu kasus terburuk O(n log n) yang terjamin (pakai heap sort atau merge sort). |
Memori terbatas: partisi dilakukan in-place dan hanya butuh ruang stack O(log n). | Kamu butuh pengurutan stabil yang mempertahankan urutan key yang sama. |
| Datanya berurutan acak atau tidak diketahui dan kamu memakai pivot acak atau median-of-three. | Inputnya sudah terurut atau hampir terurut dan pivot-nya tetap, sehingga memicu O(n²). |
| Lokalitas cache yang baik penting, karena quicksort mengakses memori secara berurutan. | Kamu mengurutkan linked list, di mana merge sort tidak butuh akses acak yang diandalkan quicksort. |
Kode Quick Sort
Implementasi Quick Sort yang rapi dan siap dijalankan dalam Python, JavaScript, Java, C++, C, Pseudocode. Pilih bahasa, salin kodenya, atau buka langsung di Coddy Playground.
Kode Quick Sort dalam Python
1def quick_sort(a, low=0, high=None):2 if high is None:3 high = len(a) - 14 if low < high:5 p = partition(a, low, high)6 quick_sort(a, low, p - 1)7 quick_sort(a, p + 1, high)8 return a9
10
11def partition(a, low, high):12 # Lomuto partition: everything < pivot moves left of it13 pivot = a[high]14 i = low15 for j in range(low, high):16 if a[j] < pivot:17 a[i], a[j] = a[j], a[i]18 i += 119 a[i], a[high] = a[high], a[i]20 return i21
22
23nums = [10, 7, 8, 9, 1, 5]24print("Before:", nums)25quick_sort(nums)26print("After: ", nums)Kode Quick Sort dalam JavaScript
1function quickSort(a, lo = 0, hi = a.length - 1) {2 if (lo >= hi) return a;3 const p = partition(a, lo, hi);4 quickSort(a, lo, p - 1);5 quickSort(a, p + 1, hi);6 return a;7}8
9// Lomuto partition: last element is the pivot10function partition(a, lo, hi) {11 const pivot = a[hi];12 let i = lo;13 for (let j = lo; j < hi; j++) {14 if (a[j] < pivot) {15 [a[i], a[j]] = [a[j], a[i]];16 i++;17 }18 }19 [a[i], a[hi]] = [a[hi], a[i]];20 return i;21}22
23const data = [5, 2, 9, 1, 7, 3];24console.log("Before:", data);25console.log("Sorted:", quickSort([...data]));Kode Quick Sort dalam Java
1import java.util.Arrays;2
3public class Main {4 static void quickSort(int[] arr, int low, int high) {5 if (low >= high) return;6 int p = partition(arr, low, high);7 quickSort(arr, low, p - 1);8 quickSort(arr, p + 1, high);9 }10
11 // Lomuto partition: last element is the pivot12 static int partition(int[] arr, int low, int high) {13 int pivot = arr[high];14 int i = low - 1;15 for (int j = low; j < high; j++) {16 if (arr[j] < pivot) swap(arr, ++i, j);17 }18 swap(arr, i + 1, high);19 return i + 1;20 }21
22 static void swap(int[] arr, int a, int b) {23 int tmp = arr[a];24 arr[a] = arr[b];25 arr[b] = tmp;26 }27
28 public static void main(String[] args) {29 int[] arr = {10, 7, 8, 9, 1, 5};30 System.out.println("Before: " + Arrays.toString(arr));31 quickSort(arr, 0, arr.length - 1);32 System.out.println("After: " + Arrays.toString(arr));33 }34}Kode Quick Sort dalam C++
1#include <iostream>2#include <utility>3#include <vector>4
5void printVec(const std::vector<int>& a) {6 for (int x : a) std::cout << x << " ";7 std::cout << "\n";8}9
10// Lomuto partition: place the pivot in its final position11int partition(std::vector<int>& a, int lo, int hi) {12 int pivot = a[hi];13 int i = lo;14 for (int j = lo; j < hi; ++j) {15 if (a[j] < pivot) std::swap(a[i++], a[j]);16 }17 std::swap(a[i], a[hi]);18 return i;19}20
21void quickSort(std::vector<int>& a, int lo, int hi) {22 if (lo >= hi) return;23 int p = partition(a, lo, hi);24 quickSort(a, lo, p - 1);25 quickSort(a, p + 1, hi);26}27
28int main() {29 std::vector<int> data = {10, 7, 8, 9, 1, 5};30 std::cout << "Before: ";31 printVec(data);32 quickSort(data, 0, static_cast<int>(data.size()) - 1);33 std::cout << "After: ";34 printVec(data);35 return 0;36}Kode Quick Sort dalam C
1#include <stdio.h>2
3void printArr(const int a[], int n) {4 for (int i = 0; i < n; i++) printf("%d ", a[i]);5 printf("\n");6}7
8void swap(int* x, int* y) {9 int tmp = *x;10 *x = *y;11 *y = tmp;12}13
14// Lomuto partition: place the pivot in its final position15int partition(int a[], int lo, int hi) {16 int pivot = a[hi];17 int i = lo;18 for (int j = lo; j < hi; j++) {19 if (a[j] < pivot) swap(&a[i++], &a[j]);20 }21 swap(&a[i], &a[hi]);22 return i;23}24
25void quickSort(int a[], int lo, int hi) {26 if (lo >= hi) return;27 int p = partition(a, lo, hi);28 quickSort(a, lo, p - 1);29 quickSort(a, p + 1, hi);30}31
32int main(void) {33 int data[] = {10, 7, 8, 9, 1, 5};34 int n = sizeof(data) / sizeof(data[0]);35 printf("Before: ");36 printArr(data, n);37 quickSort(data, 0, n - 1);38 printf("After: ");39 printArr(data, n);40 return 0;41}Kode Quick Sort dalam Pseudocode
1DECLARE nums : ARRAY[1:7] OF INTEGER2DECLARE n : INTEGER3n ← 74nums[1] ← 75nums[2] ← 36nums[3] ← 97nums[4] ← 18nums[5] ← 59nums[6] ← 810nums[7] ← 211DECLARE i : INTEGER12
13FUNCTION partition(lo : INTEGER, hi : INTEGER) RETURNS INTEGER14 DECLARE pivot : INTEGER15 DECLARE a : INTEGER16 DECLARE b : INTEGER17 DECLARE temp : INTEGER18 pivot ← nums[hi]19 a ← lo - 120 FOR b ← lo TO hi - 121 IF nums[b] <= pivot THEN22 a ← a + 123 temp ← nums[a]24 nums[a] ← nums[b]25 nums[b] ← temp26 ENDIF27 NEXT b28 temp ← nums[a + 1]29 nums[a + 1] ← nums[hi]30 nums[hi] ← temp31 RETURN a + 132ENDFUNCTION33
34PROCEDURE quickSort(lo : INTEGER, hi : INTEGER)35 DECLARE p : INTEGER36 IF lo < hi THEN37 // Place the pivot, then sort each side of it38 p ← partition(lo, hi)39 CALL quickSort(lo, p - 1)40 CALL quickSort(p + 1, hi)41 ENDIF42ENDPROCEDURE43
44CALL quickSort(1, n)45
46FOR i ← 1 TO n47 OUTPUT nums[i]48NEXT iFAQ Quick Sort
Berapa kompleksitas waktu quicksort?
O(n log n) dan O(n log n) pada kasus terbaik, tetapi merosot menjadi O(n²) pada kasus terburuk saat partisinya terus-menerus tidak seimbang. Pivot acak atau median-of-three membuat kasus terburuk sangat kecil kemungkinannya.Apakah quicksort stabil?
Tidak. Partisi in-place standar menukar elemen yang berjauhan, sehingga bisa mengubah urutan relatif key yang sama. Ada varian yang stabil, tetapi varian itu kehilangan keunggulan in-place milik quicksort.
Mengapa quicksort sering lebih cepat daripada merge sort?
O(n log n)-nya, tetapi harus membayar buffer O(n) dan perpindahan data yang lebih banyak.Quicksort vs merge sort: mana yang sebaiknya dipakai?
O(n log n) yang terjamin, atau saat kamu mengurutkan linked list atau data eksternal yang tidak muat di RAM.Mengapa quicksort menjadi O(n²) pada array yang sudah terurut?
n level rekursi, bukan log n. Memilih pivot secara acak atau dengan median-of-three mematahkan pola ini dan mengembalikan perilaku O(n log n).Apa perbedaan skema partisi Lomuto dan Hoare?
Skema Lomuto memakai satu indeks yang memindai dari kiri ke kanan dan lebih mudah ditulis, itulah sebabnya visualisasi ini memakainya. Skema Hoare memakai dua pointer yang bergerak ke dalam dan biasanya melakukan lebih sedikit penukaran, sehingga lebih cepat dalam praktik, tetapi tidak menempatkan pivot di posisi akhirnya selama langkah partisi.