Algoritmos de Ordenação Comuns: Bubble Sort, Insertion Sort, Shell Sort, Quick Sort e Merge Sort

Bubble Sort (Ordenação por Flutuação)

  • Visão geral: Geralmente o primeiro algoritmo de ordenação aprendido por iniciantes, considerado fundamental.
  • Eficiência: Muito baixa. O tempo de ordenação torna-se extremamente longo quando o volume de dados atinge um certo patamar.
  • Princípio: Cada elemento é comparado com os demais; se a condição for satisfeita, os elementos trocam de posição, caso contrário, nenhuma ação é tomada.
  • Complexidade de tempo: O(n²)
  • Complexidade de espaço: O(1)
  • Estabilidade: Estável
void bubble_sort(int dados[], int tamanho) {
    int temporario;
    for (int atual = 0; atual < tamanho - 1; ++atual) {
        for (int compara = 0; compara < tamanho - atual - 1; ++compara) {
            if (dados[compara] > dados[compara + 1]) {
                temporario = dados[compara];
                dados[compara] = dados[compara + 1];
                dados[compara + 1] = temporario;
            }
        }
    }
}

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

  • Visão geral: Um método de ordenação simples e direto.
  • Eficiência: Baixa, comparável ao Bubbble Sort em termos de desempenho.
  • Princípio: Começando do segundo elemento, guarda seu valor e o compara iterativamente com os anteriores. Se a condição for atendida, insere o elemento na posição correta; caso contrário, continua a comparação. Se nenhuma posição adequada for encontrada, insere o elemento no início.
  • Complexidade de tempo: O(n²)
  • Complexidade de espaço: O(1)
  • Estabilidade: Estável
void insertion_sort(int vetor[], int n) {
    int chave, pos;
    for (int i = 1; i < n; ++i) {
        chave = vetor[i];
        pos = i - 1;
        while (pos >= 0 && vetor[pos] > chave) {
            vetor[pos + 1] = vetor[pos];
            pos--;
        }
        vetor[pos + 1] = chave;
    }
}

Shell Sort

  • Visão geral: Um algoritmo avançado, uma otimização do Insertion Sort. O array é dividido em subconjuntos com base em um incremento, e cada subconjunto é ordenado individualmente usando o Insertion Sort.
  • Eficiência: Relativamente alta.
void shell_sort(int arranjo[], int tamanho) {
    int intervalo;
    for (intervalo = tamanho / 2; intervalo > 0; intervalo /= 2) {
        for (int i = intervalo; i < tamanho; i++) {
            int valor_temp = arranjo[i];
            int j;
            for (j = i; j >= intervalo && arranjo[j - intervalo] > valor_temp; j -= intervalo) {
                arranjo[j] = arranjo[j - intervalo];
            }
            arranjo[j] = valor_temp;
        }
    }
}

Quick Sort (Ordenação Rápida)

  • Visão geral: Um dos algoritmos de ordenação mais rápidos na prática, mas não é estável. Implementado recursivamente.
  • Eficiência: Muito alta.
  • Princípio: Seleciona um elemento pivô. Particiona o array de modo que elementos menores que o pivô fiquem à esquerda e os maiores à direita. O processo é repetido recursivamente nas sublistas resultantes.
  • Complexidade de tempo: O(n log n)
  • Complexidade de espaço: O(log n)
  • Estabilidade: Instável
void particiona(int arr[], int baixo, int alto) {
    int pivo = arr[alto];
    int i = (baixo - 1);
    for (int j = baixo; j <= alto - 1; j++) {
        if (arr[j] < pivo) {
            i++;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    int temp = arr[i + 1];
    arr[i + 1] = arr[alto];
    arr[alto] = temp;
    return (i + 1);
}

void quick_sort(int arr[], int baixo, int alto) {
    if (baixo < alto) {
        int pi = particiona(arr, baixo, alto);
        quick_sort(arr, baixo, pi - 1);
        quick_sort(arr, pi + 1, alto);
    }
}

Merge Sort (Ordenação por Intercalação)

  • Visão geral: O algoritmo de ordenação estável mais eficiente. Implementado recursivamente.
  • Eficiência: Muito alta.
  • Princípio: Divide o array recursivamente pela metade até que cada subarray tenha um único elemento. Depois, intercala (combina) os subarrays de forma ordenada, construindo o array ordenado final.
  • Complexidade de tempo: O(n log n)
  • Complexidade de espaço: O(n)
  • Estabilidade: Estável
void intercala(int arr[], int esq, int meio, int dir) {
    int i, j, k;
    int n1 = meio - esq + 1;
    int n2 = dir - meio;
    int L[n1], R[n2];
    for (i = 0; i < n1; i++)
        L[i] = arr[esq + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[meio + 1 + j];
    i = 0;
    j = 0;
    k = esq;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

void merge_sort(int arr[], int esq, int dir) {
    if (esq < dir) {
        int meio = esq + (dir - esq) / 2;
        merge_sort(arr, esq, meio);
        merge_sort(arr, meio + 1, dir);
        intercala(arr, esq, meio, dir);
    }
}

Tags: algoritmos de ordenação C complexidade de tempo estabilidade recursão

Publicado em 6-2 20:15 por Thomas