template<class Compare, class Iterator>
void merge_sort(Iterator start, Iterator fin, int sort_type) {
Compare comp;
typedef typename iterator_traits<Iterator>::value_type _value_type; //black type magic to infer data type
if (distance(start, fin) > 1) {
vector<_value_type> left (start, start+distance(start, fin)/2);
vector<_value_type> right (start+distance(start, fin)/2, fin);
merge_sort<Compare>(left.begin(), left.end(), 2);
merge_sort<Compare>(right.begin(), right.end(), 2);
auto i = left.begin();
auto j = right.begin();
while (i!= left.end() or j!= right.end()) {
if (i == left.end()) {
*start++ = *j++;
} else if (j == right.end()) {
*start++ = *i++;
} else if (comp(*i, *j)) {
*start++ = *i++;
} else {
*start++ = *j++;
}
}
}
So, I've written this implementation of merge_sort
, but it seems to be quite slow --- it took 1500ms to sort a vector of 1 000 000 random int
s, while standard qsort
did the same in less than a tenth of that --- 130ms. Is there (and there definitely is) something wrong with my code, and how can I fix it so that it's more effective?
UPDATE: So, umm, I've updated the code and is should use only one auxiliary vector. The speed did not improve much, though. Anything else?
template<class Compare, class Iterator>
void merge_sort(Iterator start, Iterator fin, int sort_type) {
Compare comp;
typedef typename iterator_traits<Iterator>::value_type _value_type; //black type magic to infer data type
if (distance(start, fin) > 1) {
static vector<_value_type> temp (distance(start, fin), 0);
auto i = start;
auto j = start + distance(start, fin)/2;
auto k = temp.begin();
merge_sort<Compare>(i, j, 2);
merge_sort<Compare>(j, fin, 2);
while (i != start+distance(start, fin)/2 or j != fin) {
if (i == start+distance(start, fin)/2) {
*(k++) = *(j++);
} else if (j == fin){
*(k++) = *(i++);
} else if (comp(*i, *j)) {
*(k++) = *(i++);
} else {
*(k++) = *(j++);
}
}
copy(temp.begin(), temp.begin()+distance(start, fin), start);
}
UPDATE 1.5 It's a miracle this even works; it definitely shouldn't. I'll fix this later.