Membedah Quick Sort: Panduan Langkah Demi Langkah untuk Pemula
Quick Sort, algoritma pengurutan yang terkenal karena efisiensinya, sering kali tampak menakutkan bagi para pemula. Namun, dengan pendekatan langkah demi langkah yang sistematis, kita dapat memahami prinsip kerjanya dan mengimplementasikannya dengan percaya diri. Fokus artikel ini adalah membongkar kompleksitas Quick Sort, menyajikannya dalam format yang mudah dicerna, dan memberdayakan Anda untuk menguasai algoritma ini.
1. Inti Quick Sort: Divide and Conquer
Quick Sort menerapkan paradigma “Divide and Conquer” (bagi dan taklukkan). Prosesnya dapat diringkas menjadi tiga langkah utama:
- Divide (Bagi): Pilih sebuah elemen dari array sebagai “pivot”. Kemudian, partisi array sedemikian rupa sehingga semua elemen yang lebih kecil dari pivot berada di sebelah kirinya, dan semua elemen yang lebih besar berada di sebelah kanannya.
- Conquer (Taklukkan): Secara rekursif, urutkan sub-array di sebelah kiri pivot dan sub-array di sebelah kanan pivot.
- Combine (Gabung): Tidak diperlukan langkah penggabungan karena proses pengurutan terjadi “di tempat” (in-place), artinya algoritma tidak memerlukan array tambahan untuk menyimpan data sementara.
2. Pemilihan Pivot: Kunci Efisiensi Quick Sort
Pemilihan pivot adalah faktor krusial yang mempengaruhi efisiensi Quick Sort. Strategi pemilihan pivot yang buruk dapat mengakibatkan performa terburuk O(n^2), sedangkan pemilihan pivot yang baik (misalnya, median dari array) dapat mendekati performa terbaik O(n log n). Beberapa strategi pemilihan pivot yang umum digunakan antara lain:
- Pivot Pertama: Memilih elemen pertama dari array sebagai pivot. Strategi ini sederhana tetapi rentan terhadap performa buruk jika array sudah terurut atau hampir terurut.
- Pivot Terakhir: Memilih elemen terakhir dari array sebagai pivot. Mirip dengan strategi pertama, rentan terhadap performa buruk dalam skenario tertentu.
- Pivot Acak: Memilih pivot secara acak. Strategi ini membantu menghindari skenario terburuk yang mungkin terjadi dengan strategi deterministik.
- Median-of-Three: Memilih tiga elemen (biasanya elemen pertama, tengah, dan terakhir) dan memilih median dari ketiga elemen tersebut sebagai pivot. Strategi ini seringkali memberikan hasil yang lebih baik daripada strategi sederhana lainnya.
Contoh: Misalkan array kita adalah [7, 2, 1, 6, 8, 5, 3, 4]
dan kita menggunakan strategi “pivot pertama”. Pivot kita adalah 7.
3. Proses Partisi: Memisahkan Array
Proses partisi adalah inti dari algoritma Quick Sort. Proses ini menata ulang array sehingga semua elemen yang lebih kecil dari pivot berada di sebelah kirinya dan semua elemen yang lebih besar berada di sebelah kanannya. Salah satu cara untuk mengimplementasikan partisi adalah menggunakan dua pointer:
i
: Pointer yang menunjuk ke elemen terakhir yang lebih kecil dari pivot. Awalnya,i
diinisialisasi ke indeks di sebelah kiri elemen pertama (misalnya, -1).j
: Pointer yang melakukan iterasi melalui array.
Prosesnya adalah sebagai berikut:
- Iterasi melalui array dari indeks 0 hingga indeks
high - 1
(dimanahigh
adalah indeks elemen terakhir dalam sub-array yang sedang diurutkan). - Jika
arr[j]
lebih kecil dari pivot, inkremeni
dan tukararr[i]
denganarr[j]
. - Setelah iterasi selesai, tukar
arr[i + 1]
dengan pivot (yaitu,arr[high]
).
Contoh (Melanjutkan contoh sebelumnya):
- Array awal:
[7, 2, 1, 6, 8, 5, 3, 4]
(pivot = 7) i = -1
danj = 0
.arr[j] = 7
, tidak lebih kecil dari pivot.j = 1
.arr[j] = 2
, lebih kecil dari pivot.i = 0
. Tukararr[0]
denganarr[1]
:[2, 7, 1, 6, 8, 5, 3, 4]
j = 2
.arr[j] = 1
, lebih kecil dari pivot.i = 1
. Tukararr[1]
denganarr[2]
:[2, 1, 7, 6, 8, 5, 3, 4]
j = 3
.arr[j] = 6
, lebih kecil dari pivot.i = 2
. Tukararr[2]
denganarr[3]
:[2, 1, 6, 7, 8, 5, 3, 4]
- Lanjutkan iterasi hingga
j = 6
. j = 7
.arr[j] = 4
, lebih kecil dari pivot.i = 3
. Tukararr[3]
denganarr[7]
:[2, 1, 6, 4, 8, 5, 3, 7]
- Setelah iterasi selesai, tukar
arr[i + 1] = arr[4]
dengan pivot (7):[2, 1, 6, 4, 7, 5, 3, 8]
Sekarang, array telah dipartisi: [2, 1, 6, 4, 7, 5, 3, 8]
. Semua elemen di sebelah kiri 7 lebih kecil dari 7, dan semua elemen di sebelah kanan 7 lebih besar dari 7.
4. Implementasi Rekursif: Menaklukkan Sub-Array
Setelah proses partisi selesai, kita secara rekursif memanggil Quick Sort pada sub-array di sebelah kiri pivot dan sub-array di sebelah kanan pivot. Rekursi berlanjut hingga sub-array hanya berisi satu elemen (atau tidak ada elemen), yang secara implisit terurut.
Contoh (Pseudocode):
function quickSort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
quickSort(arr, low, pi - 1) // Urutkan sub-array kiri
quickSort(arr, pi + 1, high) // Urutkan sub-array kanan
function partition(arr, low, high):
pivot = arr[high]
i = (low - 1)
for j = low to high - 1:
if arr[j] < pivot:
i++
swap arr[i] and arr[j]
swap arr[i + 1] and arr[high]
return (i + 1)
5. Analisis Kompleksitas Waktu dan Ruang
- Kompleksitas Waktu:
- Kasus Terbaik dan Rata-Rata: O(n log n)
- Kasus Terburuk: O(n^2) (terjadi ketika pivot dipilih secara konsisten sebagai elemen terkecil atau terbesar)
- Kompleksitas Ruang: O(log n) (karena rekursi)
Tips dan Trik:
- Pilih strategi pemilihan pivot yang baik untuk menghindari performa terburuk.
- Quick Sort adalah algoritma “in-place”, sehingga hemat memori.
- Quick Sort umumnya lebih cepat daripada algoritma pengurutan O(n^2) lainnya (seperti Bubble Sort, Insertion Sort, dan Selection Sort) untuk data berukuran besar.
- Pertimbangkan untuk menggunakan variasi Quick Sort, seperti “Three-Way Partitioning Quick Sort”, untuk menangani array yang mengandung banyak elemen duplikat dengan lebih efisien.
Dengan pemahaman mendalam tentang prinsip kerja, proses partisi, dan strategi pemilihan pivot, Anda sekarang memiliki dasar yang kuat untuk mengimplementasikan dan mengoptimalkan Quick Sort. Latihan dan eksperimen akan lebih memperkuat pemahaman Anda dan membuka potensi algoritma yang kuat ini. Quick Sort bukan lagi mimpi buruk, melainkan alat yang ampuh di gudang senjata pemrograman Anda.