简体   繁体   中英

Recursive Merge Sort Algorithm Implementation

I am a newbie to Algorithm. I try to implement recursive merge sorting using std::vector . But I am stuck. The code does not work.

I have looked at the algorithm from Introduction To Algorithms, Cormen/Leiserson/Rivest/Stein 3rd edition. The pseudocode which is I try to implement.

Here my merge function:

void merge(std::vector<int>& vec, size_t vec_init, size_t vec_mid, size_t vec_size) {
  int leftLoop = 0;
  int rightLoop = 0;
  int vecLoop = 0;
  size_t mid = vec_mid - vec_init + 1;

  std::vector<int> Left_Vec(std::begin(vec), std::begin(vec) + mid);
  std::vector<int> Right_Vec(std::begin(vec) + mid, std::end(vec));

  for (size_t vecLoop = vec_init; vecLoop<vec_size; ++vecLoop) {
      vec[vecLoop] = (Left_Vec[leftLoop] <= Right_Vec[rightLoop]) ? Left_Vec[leftLoop++] : Right_Vec[rightLoop++];
  }
}

And here my Merge-Sort function

void merge_sort(std::vector<int>& vec, size_t vec_init, size_t vec_size) {
    if (vec_init < vec_size) {
      size_t vec_mid = (vec_init + vec_size) / 2;
      merge_sort(vec, vec_init, vec_mid);
      merge_sort(vec, vec_mid + 1, vec_size);
      merge(vec, vec_init, vec_mid, vec_size);
   }
} 

When the input vec = {30,40,20,10} , the output vec = {10, 10, 0, 20} :

int main() {
    auto data = std::vector{ 30, 40, 20, 10 };
    merge_sort(data, 0, data.size());
    for (auto e : data) std::cout << e << ", ";
    std::cout << '\n';
    // outputs 10, 10, 0, 20, 
}

Where is my mistake about the algorithm or code?

There are a couple of problems. These changes will fix the code:

void merge(std::vector<int>& vec, size_t vec_start, size_t vec_mid, size_t vec_end) {
  size_t leftLoop = 0;
  size_t rightLoop = 0;
  size_t vecLoop = 0;
  // Not needed, much simpler if mid is relative to vec.begin()
  //size_t mid = vec_mid - vec_init + 1;

  // You didn't take vec_init and vec_size into account when calculating the ranges.
  std::vector<int> Left_Vec(std::begin(vec) + vec_start, std::begin(vec) + vec_mid);
  std::vector<int> Right_Vec(std::begin(vec) + vec_mid, std::begin(vec) + vec_end);

  // Values are not uniformly distributed in the left and right vec. You have to check for
  // running out of elements in any of them.
  for (/*size_t*/ vecLoop = vec_start; leftLoop < Left_Vec.size() && rightLoop < Right_Vec.size(); ++vecLoop) {
    //   ^~~~~ shadowed outer vecLoop  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    vec[vecLoop] = Left_Vec[leftLoop] <= Right_Vec[rightLoop] ? Left_Vec[leftLoop++] : Right_Vec[rightLoop++];
  }

  // Copy the rest of the values into vec.
  if (leftLoop == Left_Vec.size())
    std::copy(Right_Vec.begin() + rightLoop, Right_Vec.end(), vec.begin() + vecLoop);
  else
    std::copy(Left_Vec.begin() + leftLoop, Left_Vec.end(), vec.begin() + vecLoop);
}

void merge_sort(std::vector<int>& vec, size_t vec_start, size_t vec_end) {
  // Should only run the function if there are at least 2 elements, otherwise vec_mid
  // would be always at least vec_start + 1 and the recursion would never stop.
  if (vec_end - vec_start >= 2) {
    size_t vec_mid = (vec_start + vec_end) / 2;
    merge_sort(vec, vec_start, vec_mid);
    merge_sort(vec, vec_mid /* + 1 */, vec_end);
    //                         ^~~ + 1 here would skip an element
    merge(vec, vec_start, vec_mid, vec_end);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM