HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcppMinor

How can I optimize this mergesort?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thiscanmergesortoptimizehow

Problem

In main:

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:

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.