Uma Nota sobre Particionamento em Quicksort
O particionamento é a operação central do quicksort. Existem dois esquemas clássicos: o de Hoare [1] e o de Lomuto. A análise do caso esperado do algoritmo como um todo é de Sedgewick [2].
Dado um arranjo e um pivô , o particionamento reorganiza os valores de modo que todo elemento à esquerda de algum índice satisfaça e todo elemento à direita satisfaça .
Uma função partition(a, lo, hi) reorganiza de modo que
exista um índice onde para e
para , e retorna .
Para qualquer arranjo de tamanho , o particionamento de Hoare executa no máximo comparações no pior caso.
Os ponteiros esquerdo e direito avançam de forma monotônica e se encontram em passos. Um argumento de contagem justo mostra que o total de comparações é limitado por no pior caso, atingido quando o pivô cai próximo de um quarto do arranjo.
A implementação a seguir em TypeScript espelha o esquema original de Hoare, com dois ponteiros convergindo e swap() trocando elementos
fora de lugar:
// Partição estilo Hoare
function partition(arr: number[], lo: number, hi: number): number {
const pivot = arr[lo];
let i = lo - 1;
let j = hi + 1;
while (true) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j) return j;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
Chamar partition(arr, lo, hi) retorna o índice de separação. Um pivô desbalanceado degrada o quicksort para ; escolher o pivô
aleatoriamente restaura a expectativa .