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".
-
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)
-
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".
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":
- 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.
- 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}. - 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:
Ao classificar a matriz {80,30,60,40,20,10,50,70} por "Mesclar e classificar de baixo para cima":
- 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}.
- Combine essas 8 subseqüências ordenadas em pares. Obtenha 4 colunas de subárvore ordenadas {30,80}, {40,60}, {10,20} e {50,70}.
- Combine essas 4 subseqüências ordenadas em pares. Obtenha 2 colunas de subárvore ordenadas {30,40,60,80} e {10,20,50,70}.
- 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!
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