Estrutura de dados e algoritmo - algoritmo de classificação de mesclagem gráfica e implementação de código C / C ++ [coleção recomendada]

1. Introdução ao Merge Sort

Combinar duas sequências de números ordinais em uma sequência de números ordinais é chamado de "fusão".
Merge Sort (Merge Sort) é classificar a seqüência de números usando a ideia de fusão. De acordo com a implementação específica, a classificação de mesclagem inclui duas maneiras: "de cima para baixo" e "de baixo para cima".

  1. Mesclagem e classificação de baixo para cima: divida a sequência a ser classificada em várias subseqüências de comprimento 1 e, em seguida, mescle essas sequências em pares; obtenha várias sequências ordinais de comprimento 2 e, em seguida, mescle essas sequências em pares; obtenha um número de sequência ordinal de comprimento 4 e, em seguida, mescle-os dois a dois; mescle-os diretamente em uma sequência. Dessa forma, obtemos o resultado de classificação que desejamos. (Consulte a imagem abaixo)

  2. Mesclar a classificação de cima para baixo: ele e "de baixo para cima" são opostos na classificação. Inclui basicamente 3 etapas:
    ① Decomposição - divide o intervalo atual em dois, ou seja, encontre o ponto de divisão mid = (baixo + alto) / 2;
    ② Resolva - execute recursivamente dois subintervalos a [baixo ... médio] e um [médio +1 ... alto] para mesclar e classificar. A condição final da recursão é que o comprimento do subintervalo seja 1.
    ③ Mesclar - mesclar os dois subintervalos classificados a [baixo… médio] e a [médio + 1… alto] em um intervalo ordenado [baixo… alto].

A imagem abaixo reflete claramente a diferença entre a classificação de mesclagem "de baixo para cima" e "de cima para baixo".
Insira a descrição da imagem aqui

Dois, mesclar e classificar a descrição gráfica

归并排序(从上往下)代码

/*
 * 将一个数组中的两个相邻有序区间合并成一个
 *
 * 参数说明:
 *     a -- 包含两个有序区间的数组
 *     start -- 第1个有序区间的起始地址。
 *     mid   -- 第1个有序区间的结束地址。也是第2个有序区间的起始地址。
 *     end   -- 第2个有序区间的结束地址。
 */
void merge(int a[], int start, int mid, int end)
{
    
    
    int *tmp = (int *)malloc((end-start+1)*sizeof(int));    // tmp是汇总2个有序区的临时区域
    int i = start;            // 第1个有序区的索引
    int j = mid + 1;        // 第2个有序区的索引
    int k = 0;                // 临时区域的索引

    while(i <= mid && j <= end)
    {
    
    
        if (a[i] <= a[j])
            tmp[k++] = a[i++];
        else
            tmp[k++] = a[j++];
    }

    while(i <= mid)
        tmp[k++] = a[i++];

    while(j <= end)
        tmp[k++] = a[j++];

    // 将排序后的元素,全部都整合到数组a中。
    for (i = 0; i < k; i++)
        a[start + i] = tmp[i];

    free(tmp);
}

/*
 * 归并排序(从上往下)
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     start -- 数组的起始地址
 *     endi -- 数组的结束地址
 */
void merge_sort_up2down(int a[], int start, int end)
{
    
    
    if(a==NULL || start >= end)
        return ;

    int mid = (end + start)/2;
    merge_sort_up2down(a, start, mid); // 递归排序a[start...mid]
    merge_sort_up2down(a, mid+1, end); // 递归排序a[mid+1...end]

    // a[start...mid] 和 a[mid...end]是两个有序空间,
    // 将它们排序成一个有序空间a[start...end]
    merge(a, start, mid, end);
}

Ao classificar a matriz {80,30,60,40,20,10,50,70} por "mesclar classificação de cima para baixo":

  1. Considere a matriz {80,30,60,40,20,10,50,70} como composta por duas submatrizes ordenadas {80,30,60,40} e {20,10,50,70}. Basta classificar os dois grupos de subárvores ordenados.
  2. Considere a submatriz {80,30,60,40} como composta por duas submatrizes ordenadas {80,30} e {60,40}.
    Considere a submatriz {20,10,50,70} como composta de duas submatrizes ordenadas {20,10} e {50,70}.
  3. Considere a submatriz {80,30} como composta por duas submatrizes ordenadas {80} e {30}.
    Considere a submatriz {60,40} como composta de duas submatrizes ordenadas {60} e {40}.
    Considere a submatriz {20,10} como composta de duas submatrizes ordenadas {20} e {10}.
    Considere a submatriz {50,70} como composta de duas submatrizes ordenadas {50} e {70}.

归并排序(从下往上)代码

/*
 * 对数组a做若干次合并:数组a的总长度为len,将它分为若干个长度为gap的子数组;
 *             将"每2个相邻的子数组" 进行合并排序。
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     len -- 数组的长度
 *     gap -- 子数组的长度
 */
void merge_groups(int a[], int len, int gap)
{
    
    
    int i;
    int twolen = 2 * gap;    // 两个相邻的子数组的长度

    // 将"每2个相邻的子数组" 进行合并排序。
    for(i = 0; i+2*gap-1 < len; i+=(2*gap))
    {
    
    
        merge(a, i, i+gap-1, i+2*gap-1);
    }

    // 若 i+gap-1 < len-1,则剩余一个子数组没有配对。
    // 将该子数组合并到已排序的数组中。
    if ( i+gap-1 < len-1)
    {
    
    
        merge(a, i, i + gap - 1, len - 1);
    }
}

/*
 * 归并排序(从下往上)
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     len -- 数组的长度
 */
void merge_sort_down2up(int a[], int len)
{
    
    
    int n;

    if (a==NULL || len<=0)
        return ;

    for(n = 1; n < len; n*=2)
        merge_groups(a, len, n);
}

A ideia de mesclar e classificar de baixo para cima é exatamente o oposto de "mesclar e classificar de baixo para cima". Conforme mostrado na figura abaixo:
Insira a descrição da imagem aqui
Ao classificar a matriz {80,30,60,40,20,10,50,70} por "Mesclar e classificar de baixo para cima":

  1. Considere a matriz {80,30,60,40,20,10,50,70} consistindo em 8 submatrizes ordenadas {80}, {30}, {60}, {40}, {20}, {10 }, {50} e {70}.
  2. Combine essas 8 subseqüências ordenadas em pares. Obtenha 4 colunas de subárvore ordenadas {30,80}, {40,60}, {10,20} e {50,70}.
  3. Combine essas 4 subseqüências ordenadas em pares. Obtenha 2 colunas de subárvore ordenadas {30,40,60,80} e {10,20,50,70}.
  4. Combine essas 2 subseqüências ordenadas em pares. Obtenha 1 coluna de subárvore ordenada {10,20,30,40,50,60,70,80}.

O editor recomenda meu próprio grupo de intercâmbio de tecnologia de linguagem linuxC / C ++: [ 1106675687 ] Compilei alguns livros didáticos e materiais de vídeo que acho melhores para compartilhar nos arquivos do grupo e você pode adicioná-los se precisar deles!
Insira a descrição da imagem aqui

Terceiro, a complexidade do tempo e a estabilidade do merge sort

A complexidade de tempo de
merge sort A complexidade de tempo de merge sort é O (N lgN).
Suponha que haja N números na sequência sendo classificada. A complexidade de tempo da travessia é O (N). Quantas travessias são necessárias?
A forma de merge sort é uma árvore binária, e o número de vezes que ela precisa ser percorrida é a profundidade da árvore binária, e de acordo com a árvore binária completa, pode-se concluir que sua complexidade de tempo é O (N
lgN) .

Estabilidade da
classificação de mesclagem A classificação de mesclagem é um algoritmo estável, que satisfaz a definição de algoritmo estável.
Estabilidade do algoritmo - suponha que haja a [i] = a [j] na sequência, se antes da classificação, a [i] está antes de a [j]; e após a classificação, a [i] ainda está antes de a [j]. Então, esse algoritmo de classificação é estável!

Quatro, implementação de merge sort

Três implementações de merge sort são fornecidas abaixo: C, C ++ e Java. Os princípios e resultados de saída dessas três implementações são os mesmos.Cada implementação inclui duas formas: "classificação de mesclagem de cima para baixo" e "classificação de mesclagem de baixo para cima". Código de implementação de
implementação C de
mesclagem de classificação (merge_sort.c)

View Code


Código de implementação de implementação de Merge Sort C ++ (MergeSort.cpp)

View Code


Código de implementação Java do Merge Sort (MergeSort.java)

 View Code

Os princípios e resultados de saída das três implementações acima são os mesmos. Aqui está o resultado:

before sort:80 30 60 40 20 10 50 70 
after  sort:10 20 30 40 50 60 70 80 

Acho que você gosta

Origin blog.csdn.net/m0_50662680/article/details/113055011
Recomendado
Clasificación