Aqui está minha implementação de Merge Sort:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <set>
using namespace std;
template <typename RandomIt>
void MergeSort(RandomIt range_begin, RandomIt range_end){
int num_elements = distance(range_begin,range_end);
if( num_elements < 2){
return;
}
vector<typename RandomIt::value_type> v(range_begin, range_end);
RandomIt mid_it = range_begin + num_elements/2;
MergeSort(range_begin, mid_it);
MergeSort(mid_it, range_end);
for (int x : v) {
cout << x << " ";
}
cout << endl;
merge(begin(v), begin(v) + v.size()/2, begin(v) + v.size()/2, end(v), range_begin);
}
Suposição importante: é garantido que o comprimento do intervalo fornecido é uma potência de dois, portanto o vetor sempre pode ser dividido em duas partes iguais.
Quando executo a função int main() recebo o seguinte:
int main() {
vector<int> v = {6, 4, 7, 6, 4, 4, 0, 1};
MergeSort(begin(v), end(v));
for (int x : v) {
cout << x << " ";
}
cout << endl;
return 0;
}
resultado: 4 4 0 1 6 4 7 6
A classificação não acontece e o algoritmo basicamente troca duas metades do vetor. Não consigo encontrar meu erro.
Dentro da função é declarado um vetor local
isso não está classificado. Ele é criado novamente a cada chamada recursiva da função.
A única operação com este vetor não classificado na primeira chamada recursiva da função é a seguinte
Isso significa que o conteúdo do resultado do vetor original está sendo construído com base em seu conteúdo original utilizando esta operação na primeira chamada recursiva da função. Todas as chamadas recursivas subsequentes da função não influenciam o conteúdo do vetor local declarado na primeira chamada recursiva da função.
O vetor local
v
é redundante. De qualquer forma, criar um novo vetor em cada chamada recursiva da função torna a função ineficiente. Você precisa usarstd::inplace_merge
com o vetor original dentro da função.A função pode ter a seguinte aparência
Neste caso a saída do programa será
Ou se o compilador suportar C++ 17, a função pode ter a seguinte aparência
Achei que a seguinte abordagem estava funcionando
O problema com o que você estava fazendo era que, ao mesclar as metades classificadas de 'v' de volta ao intervalo original, você não estava realmente modificando o intervalo original. Então, você está basicamente modificando o vetor local 'v'. Como resultado, os elementos classificados são armazenados em 'v', mas o intervalo original range_begin a range_end permanece inalterado