【问题标题】:C++: Implementing merge sort from scratchC++:从头开始实现归并排序
【发布时间】:2013-04-17 22:51:50
【问题描述】:

我试图测试自己并想编写归并排序,但实际上并没有在网上查找任何代码,并在特定时间段内完成。我被困在这一点上,我不能简单地理解我做错了什么,因为据我所知,合并排序是将字符串划分到字符串只有 1 个字符的点,然后将它们重新合并在一起。我在下面写的代码尝试来做确切的事情。我想知道我的概念是错误的,还是只是我的实现

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);
  }
}

【问题讨论】:

  • 听起来您的概念是对的,尽管当您处理少量项目时停止拆分事物并使用(例如)插入排序来处理少量项目是很常见的,然后合并这些运行。
  • 好吧,一方面你只有一个字符串......你永远不会在分裂阶段把它分开。

标签: c++ algorithm sorting implementation mergesort


【解决方案1】:

注意变化:

#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;
}

输出(ideone):

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

【讨论】:

  • 非常感谢您提供完美的答案,并感谢您以我希望的方式解决它。
【解决方案2】:

这看起来不对:

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

你不是说pivot=(end+start)/2吗?还是mergeSort(str1, start, start+pivot)mergeSort(str1, start+pivot+1, end)

编辑:

你的merge 不能很好地处理空字符串。在将它连接到mergeSort 之前,您应该已经测试了这个函数。

【讨论】:

    【解决方案3】:

    自从我使用 C++ 以来已经很久了,但是break 不会立即退出循环吗?因为在这种情况下永远无法到达fromStr1 = true;

    【讨论】:

      猜你喜欢
      • 2014-07-15
      • 2021-08-09
      • 2014-04-21
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多