Pular para conteúdo

QuickSort

O QuickSort particiona um intervalo ao redor de um pivô e ordena as partições recursivamente. Muitas vezes é rápido e econômico em memória, mas exige cuidado com pivôs, valores duplicados e profundidade da pilha.

static void quickSort(int[] values) {
    quickSort(values, 0, values.length - 1);
}

private static void quickSort(int[] values, int low, int high) {
    while (low < high) {
        int pivot = partition(values, low, high);
        if (pivot - low < high - pivot) {
            quickSort(values, low, pivot - 1);
            low = pivot + 1;
        } else {
            quickSort(values, pivot + 1, high);
            high = pivot - 1;
        }
    }
}

private static int partition(int[] values, int low, int high) {
    int pivotValue = values[high];
    int boundary = low;
    for (int scan = low; scan < high; scan++) {
        if (values[scan] <= pivotValue) swap(values, boundary++, scan);
    }
    swap(values, boundary, high);
    return boundary;
}

private static void swap(int[] values, int first, int second) {
    int temporary = values[first];
    values[first] = values[second];
    values[second] = temporary;
}

O exemplo escolhe o último valor como pivô para facilitar a compreensão. Durante o particionamento, os valores anteriores a boundary são menores ou iguais ao pivô, e os valores já examinados depois dele são maiores. Posicionar o pivô em boundary estabelece sua posição final; a indução prova o resultado recursivo.

Partições balanceadas custam Θ(n log n). A escolha aleatória do pivô tem tempo esperado Θ(n log n), não uma garantia absoluta; pivôs consistentemente extremos custam Θ(n²). O particionamento usa armazenamento Θ(1), e fazer a recursão apenas no lado menor limita a profundidade da pilha a O(log n). O algoritmo não é estável. O particionamento em três vias é preferível quando muitas chaves são iguais ao pivô.