Ali
Ali

Reputation: 5476

C++: Implementing merge sort from scratch

I was trying to test my self and wanted to write mergesort, without actually looking up any code online, and to do it in a certain time period. I am stuck at this point where I cannot simply understand what I am doing wrong, since merge sort, as much as i remember, is to divide the strings up to the point where string is only 1 character and later on merge them back together. The code I've written below tries to do the exact thing. I was wondering whether I got the concept wrong, or just my implementation?

string merge(string str1, string str2) {
  string final = "";
  int i = 0, j = 0;
  bool fromStr1 = false;

  while(true) {
    if(str1[i] < str2[j]) {
      final += str1[i];
      i++;
      if(i == str1.size()) {
        break;
      }
    }
    else {
      final += str2[j];
      j++;
      if(j == str2.size()) {
        break;
        fromStr1 = true;
      }
    }
  }

  if(fromStr1) {
    for(int t = i; t < str1.size(); t++) {
      final += str1[t];
    }
  }
  else {
    for(int t = j; t < str2.size(); t++) {
      final += str2[t];
    }
  }

  return final;
}

string mergeSort(string str1, int start, int end) {
  if(end - start == 1)
    return str1;
  else {
    int pivot = (end - start) / 2;
    string newStr1 = mergeSort(str1, start, pivot);
    string newStr2 = mergeSort(str1, pivot + 1, end);
    return merge(newStr1, newStr2);
  }
}

Upvotes: 0

Views: 1504

Answers (3)

Alexey Frunze
Alexey Frunze

Reputation: 62048

Note the changes:

#include <iostream>
#include <string>

using namespace std;

string merge(string str1, string str2) {
  string final = "";
  int i = 0, j = 0;
  bool fromStr1 = false;

  while (true) {
    if (i >= (int)str1.size()) {
      break;
    }
    if (j >= (int)str2.size()) {
      fromStr1 = true; // changed the order of this with break!
      break;
    }

    if (str1[i] < str2[j]) {
      final += str1[i];
      i++;
    }
    else {
      final += str2[j];
      j++;
    }
  }

  if (fromStr1) {
    for (int t = i; t < (int)str1.size(); t++) {
      final += str1[t];
    }
  }
  else {
    for(int t = j; t < (int)str2.size(); t++) {
      final += str2[t];
    }
  }

  return final;
}

string mergeSort(string str1) {
  int len = str1.size();
  if (len <= 1)
    return str1;
  else {
    string newStr1 = mergeSort(str1.substr(0, len / 2));
    string newStr2 = mergeSort(str1.substr(len / 2, len - len / 2));
    return merge(newStr1, newStr2);
  }
}

int main()
{
  cout << '"' << mergeSort("") << '"' << endl;
  cout << '"' << mergeSort("a") << '"' << endl;
  cout << '"' << mergeSort("ba") << '"' << endl;
  cout << '"' << mergeSort("132") << '"' << endl;
  cout << '"' << mergeSort("4321") << '"' << endl;
  cout << '"' << mergeSort("54321") << '"' << endl;
  return 0;
}

Output (ideone):

""
"a"
"ab"
"123"
"1234"
"12345"

Upvotes: 1

Beta
Beta

Reputation: 99094

This doesn't look right:

int pivot = (end - start) / 2;
string newStr1 = mergeSort(str1, start, pivot);
string newStr2 = mergeSort(str1, pivot + 1, end);

Don't you mean pivot=(end+start)/2? Or else mergeSort(str1, start, start+pivot) and mergeSort(str1, start+pivot+1, end)?

EDIT:

And your merge doesn't cope well with empty strings. You should have tested this function before hooking it up to mergeSort.

Upvotes: 1

Zim-Zam O&#39;Pootertoot
Zim-Zam O&#39;Pootertoot

Reputation: 18148

It's been ages since I used C++, but doesn't break immediately exit the loop? Because fromStr1 = true; is never reached in that case.

Upvotes: 0

Related Questions