【问题标题】:How do I print all of the intermediate steps of MergeSort?如何打印 MergeSort 的所有中间步骤?
【发布时间】:2025-12-11 02:00:01
【问题描述】:

大约两周前,在我的 C++ 简介课程中,我被分配了一个项目,该项目涉及使用向量和排序算法。我已经成功实现了所有必需的算法,并且可以通过打印来自中间步骤和最终排序的所有向量来验证它们是否有效。我遇到的唯一问题是让合并排序以以下格式打印其中间结果:

[14, 7, 3, 12, 9, 11, 6, 2]

[14, 7, 3, 12] [9, 11, 6, 2]

[14, 7] [3, 12] [9, 11] [6, 2]

[14] [7] [3] [12] [9] [11] [6] [2]

[7, 14] [3, 12] [9, 11] [2, 6]

[3, 7, 12, 14] [2, 6, 9, 11]

[2, 3, 6, 7, 9, 11, 12, 14]

其中第一行和最后一行是原始和排序的原始向量。

我已经尝试修改我的向量打印过程,该过程接受我的合并排序函数通过对从被调用方接收到的原始数组进行一半而创建的两个向量。它以一种非常奇怪的方式打印结果,您将在下面看到。我也放弃了制作一个可以容纳所有内容并为每一行迭代的二维数组的想法。询问我应该在哪里调用我的新的和改进的打印功能也很重要......?

以下是我打印归并排序向量的过程:

/*
    Procedure: printMergeSort
    Purpose:   prints merge sort steps to the console
*/

void printMergeSort(vector <int> left, vector <int> right)
{

    for (int i = 0; i < left.size(); ++i)
    {

        if (i == 0)
            printf("[%d, ", left[i]);
        else if (i < left.size() - 1)
            printf("%d, ", left[i]);
        else
            printf("%d], ", left[i]);

    }

    for (int i = 0; i < right.size(); ++i)
    {

        if (i == 0)
            printf("[%d, ", right[i]);
        else if (i < right.size() - 1)
            printf("%d, ", right[i]);
        else
            printf("%d] \n", right[i]);

    }

}``

还有我的合并和归并排序代码:

/*
    Procedure: merge
    Purpose:   Helper funcrion for mergeSort...
               Sorts the subarrays and merges them
*/

void merge(vector<int>& leftVector, vector<int>& rightVector, vector<int>& vectortoMerge)
{

    int lefttmostValue = leftVector.size();
    int rightmostValue = rightVector.size();
    int i = 0, j = 0, k = 0;

    //printMergeSort(leftVector, rightVector);

    while (j < lefttmostValue and k < rightmostValue)
    {

        if (leftVector[j] < rightVector[k])
        {

            vectortoMerge[i] = leftVector[j];
            //printf("%d ", vectortoMerge[i]); 
            ++j;

        }
        else
        {

            vectortoMerge[i] = rightVector[k];

            //printf("%d ", vectortoMerge[i]);
            ++k;

        }

        ++i;

    }
    while (j < lefttmostValue)
    {

        vectortoMerge[i] = leftVector[j];       
        //printf("%d ", vectortoMerge[i]);
        ++j; ++i;

    }

    while (k < rightmostValue) 
    {

        vectortoMerge[i] = rightVector[k];
        //printf("%d ", vectortoMerge[i]);
        ++k; ++i;

    }

}

/*
    procedure: mergeSort
    Purpose:   Main function for the merge sort algorithm....
               Splits the vector into 2 and makes a call the merge() function
*/

void mergeSort(vector<int>& vectortoSort)
{
    if (vectortoSort.size() <= 1) return;

    int middleElement = vectortoSort.size() / 2;
    vector<int> leftVector;
    vector<int> rightVector;

    for (int j = 0; j < middleElement; ++j)
        leftVector.push_back(vectortoSort[j]);
    for (int j = 0; j < (vectortoSort.size()) - middleElement; ++j)
        rightVector.push_back(vectortoSort[middleElement + j]);

    printMergeSort(leftVector, rightVector);
    printf(", ");
    mergeSort(leftVector);
    mergeSort(rightVector);
    merge(leftVector, rightVector, vectortoSort);


}

预期的输出如上所述,但输入这些值时,我得到以下信息:

[14, 7, 3, 12], [9, 11, 6, 2][14, 7], [3, 12][14, [7, [3, [12, [9, 11] , [6, 2][9, [11, [6, [2,

有没有更好的方法来解决这个问题?我真的很感激能伸出援手,因为我所有的同事和朋友都被这件事难住了!

谢谢!!!

【问题讨论】:

  • 这到底是谁指派的?看起来很邪恶....
  • 输出很奇怪,因为 printMergeSort 不能正确处理单元素数组。
  • 我会考虑存储中间结果。也许是一个由递归级别索引的字符串数组,您可以根据级别附加到字符串(而不是打印)。打印只会在最后完成。

标签: c++ sorting vector merge mergesort


【解决方案1】:

我同意 Karl Knechtel 的回答。但是有一个出路(硬出路):计算递归深度的每一层,并将对应的向量沿着层索引推送到容器中;逐层打印容器。这是一个 sn-p(未优化):

void print(const vector<int>& vec) {
    printf("[");
    for (auto it = vec.begin(); it != vec.end(); it++) {
        (it == vec.end() - 1) ? printf("%d", *it) : printf("%d, ", *it);
    }
    printf("]");
}

vector<pair<int, vector<int>>> vecs;
static int MaxDepth = 0;

void mergeSort(vector<int>& vectortoSort, int level = 0)
{
    if (level > MaxDepth) MaxDepth = level + 1;
    if (vectortoSort.size() <= 1)
    {
        return;
    }

    int middleElement = vectortoSort.size() / 2;
    vector<int> leftVector;
    vector<int> rightVector;

    for (int j = 0; j < middleElement; ++j)
        leftVector.push_back(vectortoSort[j]);
    for (int j = 0; j < (vectortoSort.size()) - middleElement; ++j)
        rightVector.push_back(vectortoSort[middleElement + j]);

    vecs.push_back(make_pair(level, leftVector));  mergeSort(leftVector, level + 1);
    vecs.push_back(make_pair(level, rightVector)); mergeSort(rightVector, level + 1);

    merge(leftVector, rightVector, vectortoSort);
    vecs.push_back(make_pair(MaxDepth +1 - level, vectortoSort));
}

void main()
{
    vector<int> vec{ 14, 7, 3, 12, 9, 11, 6, 2 };
    vecs.push_back(make_pair(-1, vec));
    mergeSort(vec); 
    for (int i = -1; i < MaxDepth + 2; i++) {
        for (const auto& e : vecs) {
            if (e.first == i)
            {
                print(e.second);
                cout << "  ";
            }
        }
        cout << "\n";
    }
}

这是一个屏幕截图:

【讨论】:

  • 谢谢!它非常适合打印。如何让它输出到文件?检查下面的答案,看看我得到了什么。
  • 在打印前将 int 转换为 char 的最佳方法是什么?这是一个澄清示例:初始向量在打印时包含 65、66、67 我希望它输出 A、B、C(可选地从头开始使用 char)
【解决方案2】:

问题在于打印时的索引。当数组大小很小时,你的代码的 else 没有被达到(对不起我的英语):试试这样的

printf("[");
for (int i = 0; i < left.size(); ++i)
{
    if (i != 0)
        printf(", ");
    printf("%d", left[i]);
}
printf("], [");

for (int i = 0; i < right.size(); ++i)
{
    if (i != 0)
        printf(", ");
    printf("%d", right[i]);
}
printf("]\n");

【讨论】:

    【解决方案3】:

    第一次调用正确地产生了所需的[14, 7, 3, 12], [9, 11, 6, 2] 行;然后第一个递归调用被应用到[14, 7, 3, 12] 并且 completelyanything 完成后半部分之前(递归地)对那一半进行排序。因此无法生成所需的[14, 7] [3, 12] [9, 11] [6, 2] 行,因为递归将在[9, 11] [6, 2] 打印之前继续处理[14, 7] [3, 12] 块。

    要解决此问题,您需要将递归完全转换为广度优先遍历。

    【讨论】:

      【解决方案4】:

      伙计们的回答真棒!!

      我还需要将我的向量输出到每个算法的文件中。 这是我使用 @seccpur 的打印方法得到的结果:

      [, 14, 7, 312] [, 9, 11, 62]

      [, 147] [, 312] [, 911] [, 62]

      [14] [7] [3] [12] [9] [11] [6] [2]

      [, 714] [, 312] [, 911] [, 26]

      [, 3, 7, 1214] [, 2, 6, 911]

      [, 2, 3, 6, 7, 9, 11, 1214]

      如何使 @seccpur 的打印代码适用于我的 ofstream 对象?

      【讨论】: