Menu
Coddy logo textTech

Quick Sort

Última atualização

Quicksort é um algoritmo de dividir para conquistar que ordena em torno de um "pivô". Ele escolhe um elemento pivô e então particiona o array de modo que tudo o que é menor venha antes e tudo o que é maior venha depois, o que fixa o pivô em sua posição final ordenada. Em seguida, recorre sobre as partições esquerda e direita. Esta visualização usa o esquema de Lomuto com o último elemento como pivô. Pressione reproduzir para ver a partição e a colocação do pivô.

Quicksort costuma ser a ordenação de propósito geral mais rápida na prática graças ao bom comportamento de cache e à partição no próprio local, com média de O(n log n). Seu pior caso é O(n²) (por exemplo, um array já ordenado com uma escolha ruim de pivô), que estratégias de pivô como mediana de três ou aleatorização evitam.

Complexidade de tempo e espaço

CasoComplexidadeNotas
Melhor casoO(n log n)Partições equilibradas
Caso médioO(n log n)Ordem aleatória
Pior casoO(n²)Pivôs desequilibrados de forma consistente
EspaçoO(log n)Pilha de recursão (partição no próprio local)
EstávelNãoAs trocas da partição reordenam elementos iguais

Passo a passo

PassoO que acontece
1Escolha um pivô (aqui, o último elemento do intervalo).
2Partição: mova para a esquerda dele todos os elementos menores que o pivô.
3Troque o pivô para a fronteira: agora ele está na posição final.
4Aplique quicksort recursivamente na partição esquerda.
5Aplique quicksort recursivamente na partição direita.

Exemplo resolvido

Ordenando [5, 2, 4, 1] com o esquema de Lomuto (último elemento como pivô):

PassagemArrayAção
Início[5, 2, 4, 1]Particiona todo o intervalo; o pivô é 1 (último elemento).
1[1, 2, 4, 5]Nada é menor que 1, então troca 1 para o índice 0; o pivô 1 fica final. Recorre à direita sobre [2, 4, 5].
2[1, 2, 4, 5]Particiona [2, 4, 5] com pivô 5; tanto 2 quanto 4 são menores, então 5 permanece no fim e fica final. Recorre à esquerda sobre [2, 4].
3[1, 2, 4, 5]Particiona [2, 4] com pivô 4; 2 é menor, então 4 permanece no lugar e fica final. 2 é um único elemento, então já está ordenado.
Fim[1, 2, 4, 5]Cada pivô fica fixado em seu lugar; o array está ordenado.

Quando usar quicksort

Use quandoEvite quando
Você precisa de uma ordenação em memória rápida e de propósito geral com constantes pequenas.Você precisa de tempo garantido O(n log n) no pior caso (use heap sort ou merge sort).
A memória é escassa: a partição é no próprio local e precisa apenas de O(log n) de pilha.Você precisa de uma ordenação estável que preserve a ordem das chaves iguais.
Os dados estão em ordem aleatória ou desconhecida e você usa um pivô aleatório ou mediana de três.A entrada já está ordenada ou quase ordenada e o pivô é fixo, disparando O(n²).
A localidade de cache importa, já que o quicksort acessa a memória sequencialmente.Você ordena uma lista encadeada, onde o merge sort evita o acesso aleatório do qual o quicksort depende.

Código de Quick Sort

Uma implementação limpa e executável de Quick Sort em Python, JavaScript, Java, C++, C. Escolha uma linguagem, copie o código ou abra-o já carregado no Playground da Coddy.

Código de Quick Sort em Python

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)
Execute este código no Playground de Python

Perguntas frequentes sobre Quick Sort

Qual é a complexidade de tempo do quicksort?
Quicksort tem média O(n log n) e é O(n log n) no melhor caso, mas degrada para O(n²) no pior caso quando as partições ficam consistentemente desequilibradas. Pivôs aleatórios ou de mediana de três tornam o pior caso muito improvável.
Quicksort é estável?
Não. A partição padrão no próprio local troca elementos distantes, o que pode mudar a ordem relativa de chaves iguais. Existem variantes estáveis, mas elas abrem mão da vantagem do quicksort de operar no próprio local.
Por que o quicksort costuma ser mais rápido que o merge sort?
Quicksort particiona no próprio local com excelente localidade de cache e sem buffer adicional, então suas constantes são pequenas. Merge sort iguala seu limite O(n log n), mas paga por um buffer O(n) e mais movimentação de dados.
Quicksort vs merge sort: qual devo usar?
Escolha quicksort para ordenar arrays em memória de forma rápida e no próprio local, onde suas constantes pequenas geralmente vencem. Escolha merge sort quando precisar de uma ordenação estável, garantia de pior caso O(n log n), ou quando ordenar listas encadeadas ou dados externos que não cabem na RAM.
Por que o quicksort se torna O(n²) em um array ordenado?
Com um pivô fixo como o primeiro ou último elemento, uma entrada já ordenada faz cada partição separar apenas um elemento, produzindo n níveis de recursão em vez de log n. Escolher o pivô aleatoriamente ou com mediana de três quebra esse padrão e restaura o comportamento O(n log n).
Qual é a diferença entre os esquemas de partição de Lomuto e Hoare?
O esquema de Lomuto usa um único índice que varre da esquerda para a direita e é mais simples de codificar, por isso esta visualização o usa. O esquema de Hoare usa dois ponteiros que avançam para o interior e costuma fazer menos trocas, sendo mais rápido na prática, mas não coloca o pivô em sua posição final durante o passo de partição.
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR