Quicksort

Pemilihan Pivot

Pada setiap versi awal quicksort, elemen yang paling kiri dari partisi akan sering menjadi pilihan sebagai elemen pivot. Sayangnya, ini menyebabkan perilaku worst-case pada array yang telah diurut, yang merupakan penggunaan kasus yang sering dipakai. Masalah ini dengan mudah diselesaikan dengan memilih salah satu dari index acak untuk pivot, memilih indek tengah dari partisi atau (secara khusus untuk partisi panjang) memilih median dari elemen awal, tengah, dan akhir dari partisi untuk pivot (sebagaimana direkomendari oleh Robert Sedgewick.
Memilih elemen pivot juga rumit dengan dengan kehadiran dari Integer Overflow. Jika indeks batas dari subarray yang diurutkan cukup besar, ungkapan naif untuk indeks tengah, (kiri + kanan)/2, akan menyebabkan luapan dan memberikan indeks pivot yang salah. Masalah ini dapat terselesaikan dengan menggunakan, sebagai contoh, kiri + (kanan-kiri)/2 pada indeks elemen tengah, pada masalah dari aritmetika kompleks. Masalah yang sama muncul pada beberapa metode yang lain dari pemilihan elemen pivot.

Paralelisasi

Seperti Merge Sort, Quicksort juga dapat diparalelisasikan dikarenakan sifat pembagi-dan-penakluk alaminya. Operasi Partisi In-Place sulit untuk diparalelisasikan, tetapi setelah dibagi, bagian list yang berbeda dapat diurutkan secara paralel. Berikut ini merupakan pendekatan langsung: Jika kita memiliki prosesor , kita dapat membagi list dari element  menjadi sublist  pada rata-rata waktu O(n), kemudian mengurutkannya pada rata-rata waktu . Abaikan pra pengolahan O(n) dan waktu penggabungan merupakan Linear Speedup atau Percepatan Linear. Jika pemisahannya tak tampak, abaikan nilai waktu penggabungan O(n). Jika Partisi pemisah didasari pada penggantian pivot, sangat rumit untuk memparelisasikan dan secara langsung memiliki nilai waktu O(n). Jika diberikan O(logn) atau lebih banyak prosesor, hanya sebesar O(n) waktu keseluruhan yang digunakan, sedangkan pendekatan dengan linear speedup akan mencapai waktu O(log n) secara keseluruhan.
Salah satu keuntungan dari quicksort paralel sederhana daripada algortima sorting paralel yang lain ialah tidak dibutuhkannya sinkronisasi, tetapi kerugiannya ialah tipe sorting ini masih membutuhkan O(n) dan hanya sublinear speedup dari O(log n) yang dapat dicapai. Rangkaian baru dimulai segera setelah sublist tersedia untuk bekerja dan tidak berkomunikasi dengan rangkaian yang lain. Ketika setelah semua rangkaian selesai, Proses sorting juga akan selesai.
Satu lagi algortima sorting paralel yang mutakhir dapat mencapai ikatan waktu yang bahkan lebih baik. Sebagai contoh pada tahun 1991 David Powers menjelaskan quicksort paralelisasi (dan radix sort yang dapat berjalan di waktu O(log n) pada CRWC prosesor n dengan menjalankan pemisahan secara tak langsung.

Analisis Average-case menggunakan kemungkinan berlainan

Quicksort menggunakan waktu rata-rata O(n log n), ketika inputan merupakan permutasi acak. Mengapa? Sebagai pemulaian, tidak sulit untuk mengetahui bahwa opearasi pemisahan menggunakan O(n) waktu.
Pada kasus unbalance sering muncul, setiap kita melakukan partisi kita membagi list menjadi dua buah sublist dari besar 0 dan  (sebagai contoh jika seluruh elemen array itu sama). Ini berarti setiap rekursif memanggil proses list dari besar kurang satu dari list sebelumnya. Konsekuensinya, kita dapat membuat penggilan bersarang  sebelum kita menccapai list dengan besar 1. Ini berarti bahwa pemanggilan tree ialah rantai linear dari pemanggilan bersarang . Pemanggilan ke- memanggil  pada partisi, dan , jadi pada kasus ini, Quick sort mengambil waktu sebesar . Itu merupakan worst case dimana input yang diberikan dari perbandingan dilakukan oleh algoritme sorting, terdapat pula algortima penyesuaian yang secara efektif membuat inputan worst-case pada quicksort menjadi mudah, dengan tanpa teknik pemilihan pivot secara khusus.
Pada kasus balance, setiap kali kita melakukan partisi, kita membagi list menjadi dua buah sublist yang bernilai hampir sama. Ini berarti setiap proses pemanggilan rekursif memanggil setengah dari besar list. Konsekuensinya, kita dapat hanya memakai pemanggilan bersarang  sebelum mencapai list dengan besar 1. Ini berarti bahwa kedalaman pemanggilan tree sebesar . Tetapi tidak ada dua pemanggilan pada level pemanggilan tree pada bagian yang sama dari list yang aslinya; oleh karena itu setiap level pemanggilan hanya membutuhkan waktu keseluruhan O(n) (setiap pemanggilan memiliki nilai keluar yang konstan, tetapi sejak terdapat hanya O(n) pemanggilan pada setiap level, kejadian ini digolongkan pada faktor O(n)). Hasilnya ialah algortima hanya menggunakan waktu sebanyak O(n log n).
Sebenarnya, seimbang secara sempurna tidak dibutuhkan; bahkan jika setiap pivot membagi elemen dengan 75% pada satu sisi dan 25% pada sisi yang lainnya (atau pada pecahan tetap), pemanggilan dalam masih dibutuhkan untuk , jadi total running time masih berupa O(n log n).
Jadi apa yang terjadi pada average case? Jika pivot memiliki peringkat acak di tengah 50 persen, yang di antara persentil ke-25 dan persentil ke-75, kemudian memisahkan elemen dengan paling kurang 25% dan paling banyak 75% dari setiap sisi. Jika kita dapat secara konsisten memilih pivot dari pertengahan 50 persen, kita hanya harus memisahkan list paling banyak  kali sebelum mencapai list sebesar 1, menghasilkan sebuah algoritme O(n log n)
Ketika inputan merupakan permutasi acak, pivot akan memiliki peringkat acak, dan tidak menjamin berada pada pertengahan 50 persen. Bagaimanapun, ketika kita memulai dari permutasi acak, setiap pemanggilan pivot secara rekursif memiliki peringkat acak dari listnya, dan jika terdapat pada pertengahan list, maka akan menghabiskan waktu setengah. Itu cukup bagus, anggap bahwa kamu membalikkan koin: kepala berarti bahwa peringkat pivot berada pada 50 persen, sedang ekor tidak. Anggap bahwa kamu membalikkan coin berkali-kali sehingga mendapatkan kepala sejumlah k, walaupun akan menghabiskan banyak waktu, secara rata-rata hanya membutuhkan pembalikan 2k, kesempatan yang kamu tidak akan dapatkan sebesar  kepala setelah  lemparan sangat mustahil (dapat diteliti menggunakan ikatan Chernoff). Dengan memakan cara yang sama, rekursif yang dilakukan oleh Quicksort akan mengentikan average case pada pemanggilan dari hanya . Tetapi jika pemanggilan rata-rata ialah O(long n), dan setiap level dari proses pemanggilan tree paling banyak  elemen, makan jumlah total dari tugas yang dilakukan pada kasus average case ialah O(n log n). Perlu diperhatikan bahwa algoritme tidak perlu memverifikasi pivot berada ditengah jika diberikan pecahan tetap acak dari berapa kali masukkan, yang cukup untuk kerumitan yang diinginkan.

Analisis Quicksort acak

Menggunakan analisis yang sama, seseorang dapat menunjukkan bahwa quicksort yang teracak memiliki sifat yang diinginkan, untuk inputan apapun, membutuhkan O(n log n) kali. Bagaimanapun, terdapat bukti yang kombinatorial, yang lebih elegan dari kedua analisis menggunakan kemungkinan yang berlainan dan analisis menggunakan rekursif.
Untuk setiap eksekusi quicksort harus bersesuaian dengan binary search tree (BST): pivot awal berada pada node rootl pivot dari tengah kiri merupakan subtree kiri root, pivot dari tengah kanan merupakan subtree kanan root, dan seterusnya. Jumlah perbandingan dari eksekusi Quicksort sama dengan perbandingan selama konstruksi BST dengan urutan masukan. Jadi, jumlah perbandingan rata-rata untuk Quicksort acak sama dengan average case dari menghasilkan BST ketika nilai yang dimasukkan  dari permutasi acak.
Ditinjau dari pembuatan BST dengan memasukan urutan  nilai yang membentuk permutasi acak. Jika C dianggap sebagai waktu pembuatan BST, maka kita akan memiliki:
dengan melinearisasikan ekspektasi, nilai E(C) dari C adalah
Tetapkan i dan j<i. Nilai , setelah diurutkan, tetapkan interval j+1. Pengamatan struktural inti dimana  dibandingkan dengan  pada algoritme jika dan hanya jika  jatuh di dalam satu dari dua interval samping pada .
Amati bahwa sejak  merupakan permutasi acak,  juga merupakan permutasi acak, jadi probabilitas  berdekatan dengan  yang sama persis dengan .
Dan menjadi Perhitungan akhir dengan:

Pivot yang Berbasis Pemilihan

Algoritme seleksi memilih jumlah list k yang terkecil; masalah ini merupakan yang paling mudah secara umumnya daripada sorting. Algoritme seleksi yang sederhana teatpi efektif bekerja hampir sama seperti quicksort, kecuali yang daripada memanggil rekursif pada kedua sublist, algoritme ini hanya membuat satu pemanggilan rekursif ekor pada sublist yang mengandung elemen yang diinginkan. Perubahan kecil ini menurunkan kerumitan rata-rata pada linear atau O(n) kali, dan membuatnya menjadi Algoritme In-Place. Ragam algoritme ini membawa worst case turun menjadi O(n).
Sebaliknya setelah kita mengetahui worst case O(n) algoritme seleksi tersedia, kita dapat menggunakannya untuk mencari pivot ideal (median) pada setiap langkah quicksort, yang menghasilkan ragam kalkulasi waktu worst case O(n log n). Pada implementasi praktiknya, bagaimanapun, varian ini dianggap lebih lambat dari rata-rata.

Membandingkan dengan Algoritme sorting yang lainnya

Quicksort ialah versi optimisasi memori dari Binary Tree Sort. Alih-alih memasukkan item secara berurutan pada tree yang jelas, quicksort mengatur mereka secara bersamaan pada tree yang tersirat dengan pemanggilan rekursif. Algoritme membuat perbandingan yang persis sama, tetapi pada urutan yang berbeda. Sifat yang paling diinginkan dari Algoritme Sorting ialah kestabilannya - yang urutan elemennya pada nilai yang sama tidak berubah, memberikan urutan kontrol dari tabel multikey (contoh direktori atau listing folder) pada umumnya. Sifat ini sangat sulit untuk diatur pada quicksort (atau in-place) (yang hanya menggunakan memori tambahan tetap untuk pointer dan buffer, dan memori tambahan lognN untuk pengaturan untuk rekursif yang tampak maupun tidak. Untuk ragam Quicksort melibatkan memori lebih dikarenakan perwakilannya menggunakan pointer (contoh list atau tree) atau file (list yang sering digunakan), yang menjaga stabilitas dengan mudah. Untuk contoh yang lebih kompleks dan rumit, struktur data cenderung meningkatkan waktu yang dibutuhkan, secara umum meningkatkan memori virtual atau disk.
Pesaing quicksort langsung ialah Heapsort. Waktu kalkulasi Worst case Heasort selalu bernilai O(n log n). Tetapi average casenya heapsort diasumsikan lebih lambat dari Quicksort in-place standarnya. Masalah ini masih diperdebatkan dan masih diteliti, karena ada beberapa jurnal ilmiah yang mengatakan sebaliknya. Introsort merupakan variasi dari quicksort yang menukar heapsort ketika terdapat kasus buruk yang dideteksi untuk menghindari worst case quicksort. Lebih lanjut diketahui heapsort akan sangat dibutuhkan, menggunakan heapsort secara langsung akan lebih cepat daripada harus menunggu introsort untuk menukarnya.
Quicksort juga bersaing dengan Mergesort, algoritme sorting rekursif yang lainnya tetapi dengan keuntungan waktu kalkulasi worst casenya O(n log n). Mergesort merupakan sorting stabil, tidak seperti quicksort in-place dan heapsort standar, dan dapat dengan mudah diadaptasikan untuk berjalan pada linked list dan list dengan penyimpanan yang sangat besar pada media dengan akses lambat seperti disk penyimpanan atau penyimpanan pada jaringan. Seperti pula mergesort, quicksort dapat diimplementasikan sebagai sorting stabil in-place, tetapi hal ini jarang digunakan. Walaupun quicksort dikatakan dapat berjalan pada linked list, tapi sering mendapatkan pivot yang buruk tanpa menggunakan akses acak. Kerugian utama dari mergesort ialah, ketika berjalan pada array, implementasi yang efisient membutuhkan ruang tambahan O(n), sedangkan variasi dari quicksort dengan patitisasi in-place dan rekursif ekor hanya menggunakan memori sebesar O(log n). (dengan catatan bahwa ketika menjalankannya pada linked list, mergesort hanya membutuhkan ruang tambahan yang konstan, namun kecil).
Bucket Sort dengan dua keranjang atau bucket hampir sama dengan quicksort; pivot pada kasus ini secara efektif mengambil nilai tengah dari range nilai, yang dimana berjalan dengan sangat baik pada average case untuk input yang terdistribusi secara umumnya.