Skip to content

MergeSort

Intercalação de vetores ordenados

Dados vetores crescentes v[e...meio-1] e v[meio...d-1], queremos rearranjar v[e...d-1] em ordem crescente. Para isso, utilizamos o algoritmo representado abaixo. A iteração inicia com o primeiro elemento de cada subvetor, realiza a comparação entre eles, e insere o menor elemento entre eles na primeira posição do vetor auxiliar. A cada iteração, incrementa-se o índice de apenas um dos vetores auxiliares. Quando atinge-se a metade do vetor, percorrendo a primeira metade, ou o final, percorrendo a segunda, encerra-se o laço e os elementos que não haviam sido colocados no vetor auxiliar são inseridos. Por fim, desaloca-se da memória o vetor auxiliar.

static void intercala(int *v, int e, int meio, int d)
{
    int *aux = malloc((d - e + 1) * sizeof(int));
    int i = e;
    int j = meio + 1;
    int k = 0;
    while (i <= meio && j <= d)
    {
        if (v[i] <= v[j])
            aux[k++] = v[i++];
        else
            aux[k++] = v[j++];
    }
    // Colocar no auxiliar o que ficar faltando após a primeira iteração.

    while (i <= meio)
        aux[k++] = v[i++];

    while (j <= d)
        aux[k++] = v[j++];

    for (int m = 0, i = e; i <= d; m++, i++)
        v[i] = aux[m];
    free(aux);
}

Observação:

A palavra reservada static indica que a função tem caráter auxiliar e não deve ser invocada diretamente.

MergeSort

O algoritmo mergesort parte da premissa de dividir e conquistar, o vetor é dividido em subvetores, a partir do elemento central, iterativamente, cada metade é ordenada e intercalada. O algoritmo executa recursivamente até atingir o caso base, onde o elemento da esquerda possui um índice maior ou igual ao índice do elemento da direita, ou seja, até o caso em que o subvetor resultante possua tamanho 0 ou 1.

void mergesort(int *v, int e, int d)
{
    if (e >= d)
        return;
    int meio = (e + d) / 2;
    mergesort(v, e, meio);
    mergesort(v, meio + 1, d);
    intercala(v, e, meio, d);
}

O custo de intercalar \(n\) elementos é \(O(n)\). A árvore de recursão possui \(log\ n\) níveis, em que \(n\) é a quantidade de elementos do vetor. O custo de intercalar todos os elementos em um nível é de \(O(n)\).

O custo do algoritmo mergesort é: \(O(n\cdot log\ n)\).