snippetcppMinor
How can I optimize this mergesort?
Viewed 0 times
thiscanmergesortoptimizehow
Problem
In main:
Merge:
Would a recursive or iterative approach improve run time? Is there a better way to use pointers? This would be for an array that is not likely to be in any partially sorted order.
for(int i = 1; i < upto; i *= 2)
{ for(int j = 0; j < (upto - i); j += (2*i))
{ int end2 = (2*i < (upto - j)) ? 2*i : upto - j;
mymerge(&(array[j]), i, end2); } }Merge:
void mymerge(people *arr, int end1, int end2){
int i = 0;
int j = end1;
int k = 0;
people * temp = new people[end2];
while(i arr[j].lname){
temp[k] = arr[j];
j += 1;
}else if(arr[i].fname arr[j].fname){
temp[k] = arr[j];
j += 1;
}else if(arr[i].dob = arr[j].dob){
temp[k] = arr[j];
j += 1; }
k += 1;
}
while( i < end1){
temp[k] = arr[i];
i +=1; k +=1; }
while(j < end2){
temp[k] = arr[j];
j += 1; k += 1; }
for(int c = 0; c < end2; c += 1)
arr[c] = temp[c];
delete [] temp;
}Would a recursive or iterative approach improve run time? Is there a better way to use pointers? This would be for an array that is not likely to be in any partially sorted order.
Solution
First you should define your ordering separately from your merge:
Incrementing by one can be done with the
Or you can do it in-place with:
Using new/delete is a bad idea. It makes you do all the memory management. It is better to use classes that do it all for you. In your case std::vector is a better choice for memory management of arrays
Prefer to use standard algorithms rather than manual loops.
If you are copying something and not going to use the original again. Then try and move the object to the destination rather than copying it.
Now your merge becomes more readable:
Now that I have cleaned up the
bool operator rhs.lname) {return false;}
// lhs.lname == rhs.lname
if (lhs.fname rhs.fname) {return false;}
// lhs.lname == rhs.lname && lhs.fname == rhs.fname
if (lhs.dob rhs.dob) {return false;}
return false;
}Incrementing by one can be done with the
operator++j += 1;
// Easier to write as:
++j;Or you can do it in-place with:
temp[k] = arr[i];
i += 1;
// Easier to write as
temp[k] = arr[i++];Using new/delete is a bad idea. It makes you do all the memory management. It is better to use classes that do it all for you. In your case std::vector is a better choice for memory management of arrays
people * temp = new people[end2];
....
delete [] temp;
// Better to use std::vector
std::vector temp(end2);
....Prefer to use standard algorithms rather than manual loops.
for(int c = 0; c < end2; c += 1) {
arr[c] = temp[c];
}
// Use std::copy
std::copy(temp.begin(), temp.end(), arr);If you are copying something and not going to use the original again. Then try and move the object to the destination rather than copying it.
temp[k] = arr[i];
// Prefer to move rather than copy
// if you are not going to use the value at arr[i] again.
temp[k] = std::move(arr[i]);
// Note this assumes you have defined move constructor and move assignment operator
// for the class people. If you have not defined these operations then it will
// default to use the normal copy versions.Now your merge becomes more readable:
void mymerge(people *arr, int end1, int end2)
{
int i = 0;
int j = end1;
std::vector temp;
temp.reserve(end2);
while(i < end1 && j < end2)
{
people& src = (arr[i] < arr[j])
? arr[i++]
: arr[j++];
temp.emplace_back(std::move(src));
}
std::move(&arr[i], &arr[end1], std::back_inserter(temp));
std::move(&arr[j], &arr[end2], std::back_inserter(temp));
std::move(temp.begin(), temp.end(), arr);
}Now that I have cleaned up the
mymerge() function I can understand what you are doing and it looks like it should work. But it requires the input sections to be already pre-sorted. I am not sure how your double loop in main() achieves this.Code Snippets
bool operator<(people const& lhs, people const& rhs)
{
if (lhs.lname < rhs.lname) {return true;}
if (lhs.lname > rhs.lname) {return false;}
// lhs.lname == rhs.lname
if (lhs.fname < rhs.fname) {return true;}
if (lhs.fname > rhs.fname) {return false;}
// lhs.lname == rhs.lname && lhs.fname == rhs.fname
if (lhs.dob < rhs.dob) {return true;}
// Optimize away the last test.
//if (lhs.dob > rhs.dob) {return false;}
return false;
}j += 1;
// Easier to write as:
++j;temp[k] = arr[i];
i += 1;
// Easier to write as
temp[k] = arr[i++];people * temp = new people[end2];
....
delete [] temp;
// Better to use std::vector
std::vector<people> temp(end2);
....for(int c = 0; c < end2; c += 1) {
arr[c] = temp[c];
}
// Use std::copy
std::copy(temp.begin(), temp.end(), arr);Context
StackExchange Code Review Q#71972, answer score: 4
Revisions (0)
No revisions yet.