Algoritmos de Ordenação: Do Simples ao Avançado

Introdução à Ordenação de Dados

A ordenação é uma operação fundamental na computação, consistindo no arranjo de elementos em uma sequência lógica, seja numérica ou alfabética. A escolha do algoritmo ideal depende do volume de dados, da memória disponível e da estabilidade desejada.

Algoritmos de Ordenação Simples

1. Selecsion Sort (Ordenação por Seleção)

Este algoritmo baseia-se na busca contínua pelo menor elemento dentro da parte não ordenada do array, posicionando-o no início da sequência. Embora simples, sua eficiência é limitada para grandes conjuntos de dados devido à sua complexidade temporal O(n²).


public void selectionSort(int[] vetor) {
    int n = vetor.length;
    for (int i = 0; i < n - 1; i++) {
        int indiceMinimo = i;
        for (int j = i + 1; j < n; j++) {
            if (vetor[j] < vetor[indiceMinimo]) {
                indiceMinimo = j;
            }
        }
        if (indiceMinimo != i) {
            trocar(vetor, i, indiceMinimo);
        }
    }
}

private void trocar(int[] arr, int a, int b) {
    int temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}

2. Bubble Sort (Ordenação por Bolha)

O Bubble Sort percorre o array múltiplas vezes, comparando elementos adjacentes e trocando-os de lugar caso estejam na ordem errada. O maior elemento "flutua" para o final a cada iteração. Uma otimização comum é interromper a execução se nenhuma troca ocorrer em um ciclo completo.


public void bubbleSort(int[] colecao) {
    int total = colecao.length;
    boolean houveTroca;
    for (int i = 0; i < total - 1; i++) {
        houveTroca = false;
        for (int j = 0; j < total - 1 - i; j++) {
            if (colecao[j] > colecao[j + 1]) {
                trocar(colecao, j, j + 1);
                houveTroca = true;
            }
        }
        if (!houveTroca) break;
    }
}

3. Insertion Sort (Ordenação por Inserção)

Este método constrói a lista final um item por vez. Ele é eficiente para listas pequenas ou para dados que já estão parcialmente ordenados, movendo os elementos maiores para abrir espaço para o item atual.


public void insertionSort(int[] dados) {
    for (int i = 1; i < dados.length; i++) {
        int valorAtual = dados[i];
        int j = i - 1;
        while (j >= 0 && dados[j] > valorAtual) {
            dados[j + 1] = dados[j];
            j--;
        }
        dados[j + 1] = valorAtual;
    }
}

4. Shell Sort

O Shell Sort é uma extensão do Insertion Sort que permite a troca de elementos distantes. Ele utiliza um intervalo (h) que diminui gradualmente até chegar a 1, reduzindo significativamente o número de movimentações necessárias.


public void shellSort(int[] lista) {
    int tamanho = lista.length;
    int h = 1;
    while (h < tamanho / 3) h = 3 * h + 1;

    while (h >= 1) {
        for (int i = h; i < tamanho; i++) {
            for (int j = i; j >= h && lista[j] < lista[j - h]; j -= h) {
                trocar(lista, j, j - h);
            }
        }
        h /= 3;
    }
}

Algoritmos de Ordenação Avançados

1. Merge Sort (Ordenação por Inetrcalação)

Baseado na estratégia "Dividir para Conquistar", o Merge Sort divide o array recursivamente em metades até que cada sub-array tenha apenas um elemento. Em seguida, os sub-arrays são mesclados de forma ordenada.


public void mergeSort(int[] array, int inicio, int fim) {
    if (inicio < fim) {
        int meio = inicio + (fim - inicio) / 2;
        mergeSort(array, inicio, meio);
        mergeSort(array, meio + 1, fim);
        unificar(array, inicio, meio, fim);
    }
}

private void unificar(int[] arr, int esq, int meio, int dir) {
    int[] temp = new int[dir - esq + 1];
    int i = esq, j = meio + 1, k = 0;

    while (i <= meio && j <= dir) {
        temp[k++] = (arr[i] <= arr[j]) ? arr[i++] : arr[j++];
    }
    while (i <= meio) temp[k++] = arr[i++];
    while (j <= dir) temp[k++] = arr[j++];

    for (i = 0; i < temp.length; i++) {
        arr[esq + i] = temp[i];
    }
}

2. Quick Sort

O Quick Sort seleciona um elemento como "pivô" e particiona o array em dois: elementos menores que o pivô à esquerda e maiores à direita. A eficiência deste algoritmo depende da escolha do pivô, apresentando um excelente desempenho médio de O(n log n).


public void quickSort(int[] v, int esq, int dir) {
    if (esq < dir) {
        int indicePivo = particionar(v, esq, dir);
        quickSort(v, esq, indicePivo - 1);
        quickSort(v, indicePivo + 1, dir);
    }
}

private int particionar(int[] v, int esq, int dir) {
    int pivo = v[esq];
    int i = esq + 1;
    int j = dir;

    while (i <= j) {
        while (i <= j && v[i] <= pivo) i++;
        while (i <= j && v[j] > pivo) j--;
        if (i < j) trocar(v, i, j);
    }
    trocar(v, esq, j);
    return j;
}

Ordenação com Heaps

Heap Sort

Este algoritmo utiliza uma estrutura de dados de árvore binária chamada Heap para gerenciar os elementos. Ele transforma o array em um "Max-Heap" (onde o pai é maior que os filhos) e extrai repetidamente o maior elemento, movendo-o para o final da estrutura.


public void heapSort(int[] vetor) {
    int n = vetor.length;

    for (int i = n / 2 - 1; i >= 0; i--) {
        reajustarHeap(vetor, n, i);
    }

    for (int i = n - 1; i > 0; i--) {
        trocar(vetor, 0, i);
        reajustarHeap(vetor, i, 0);
    }
}

private void reajustarHeap(int[] arr, int n, int i) {
    int maior = i;
    int esquerda = 2 * i + 1;
    int direita = 2 * i + 2;

    if (esquerda < n && arr[esquerda] > arr[maior]) maior = esquerda;
    if (direita < n && arr[direita] > arr[maior]) maior = direita;

    if (maior != i) {
        trocar(arr, i, maior);
        reajustarHeap(arr, n, maior);
    }
}

Tags: sorting-algorithms java data-structures computer-science algorithm-optimization

Publicado em 7-19 03:54