【问题标题】:Simple Merge Sort in C#C#中的简单合并排序
【发布时间】:2017-04-10 04:29:02
【问题描述】:

我一直在对排序算法进行小修改,并遇到了合并排序。我已经编写了我的代码,并且在最后一小时一直在修改它,以确定它为什么仍然无法工作。我得到标准的 StackOverFlow 异常。谁能告诉我算法有什么问题?提前致谢。到目前为止,我设法写了以下内容:

public Int32[] MergeSort(Int32[] array)
{
    int counter = 0;
    if (array.Length == 0) { return array; }
    int mid = array.Length / 2;
    Int32[] leftHalf = new Int32[mid+1];
    Int32[] rightHalf = new Int32[mid+1];
    for (int i = 0; i < mid; i++) {
        leftHalf[i] = array[i];
    }
    for (int j = mid; j < array.Length; j++) {
        rightHalf[counter] = array[j];
        counter++;
    }
    counter = 0;
    MergeSort(leftHalf);
    MergeSort(rightHalf);
    return SortAndMerge(leftHalf,rightHalf);
}

public Int32[] SortAndMerge(Int32[] left, Int32[] right) {
    Int32[] myResult = new Int32[left.Length+right.Length];
    while (left.Length > 0 || right.Length > 0) {
        if (left.Length > 0 && right.Length > 0)
        {
            if (left[0] <= right[0])
            {
                myResult[myResult.Length] = left[0];
                int toRemoveIndex = Array.IndexOf(left, left[0]);
                left = left.Where((x, y) => y != toRemoveIndex).ToArray();
            }
            else
            {
                myResult[myResult.Length] = right[0];
                int toRemoveIndex = Array.IndexOf(right, right[0]);
                right = right.Where((z, g) => g != toRemoveIndex).ToArray();
            }

        }
        else if (left.Length > 0)
        {
            myResult[myResult.Length] = left[0];
            int toRemoveIndex = Array.IndexOf(left, left[0]);
            left = left.Where((x, y) => y != toRemoveIndex).ToArray();
        }
        else if (right.Length > 0) {
            myResult[myResult.Length] = right[0];
            int toRemoveIndex = Array.IndexOf(right, right[0]);
            right = right.Where((x, y) => y != toRemoveIndex).ToArray();
        }
    }
    return myResult;
}

【问题讨论】:

  • 你能解释一下counterMergeSort 函数中做了什么吗?...我的意思是我知道它在做什么,但是为什么不使用rightHalf[j - mid] 而不是rightHalf[counter].. .可能会更清楚?
  • 很抱歉问Rustam,但是使用了这么多嵌套的if,真的需要吗?在寻找为什么会出现 SO 错误之前,我们是否应该考虑摆脱这些嵌套的 if,作为我修改算法的一部分,我将看看算法是否确实需要这样的丑陋。
  • 调试器会给你一个堆栈跟踪,你可以逐行浏览代码。这会给你很多关于正在发生的事情的信息,尤其是关于永恒循环的信息。
  • 在这些上下文中的堆栈溢出通常意味着“无限递归”。检查您的边界条件。
  • @DomFarolino 为了追加到 rightHalf 我使用计数器作为索引 rightHalf[0]、rightHalf[1] 等。[j-mid] 不会给你一个从 0+ 开始的自然序列+;

标签: c# algorithm sorting mergesort


【解决方案1】:
if (array.Length == 0) return;

这绝不是真的,因此例外,因为您总是这样创建数组。

Int32[] leftHalf = new Int32[mid+1];

最小长度为 1。

在此处查看正确的合并排序算法。

https://en.wikipedia.org/wiki/Merge_sort#Algorithm

【讨论】:

    【解决方案2】:

    你介意重构吗?为什么不使用zip 这里是来自 msdn 的示例

    int[] numbers = { 1, 2, 3, 4 };
    string[] words = { "one", "two", "three" };
    var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
    foreach (var item in numbersAndWords)
    Console.WriteLine(item);
    

    此代码产生以下输出:

    1 个

    2 两个

    三三

    还有用于排序的 linq。

    【讨论】:

    • 我正在考虑实现合并排序,这就是为什么 ZIP 不适合我的原因。无论如何,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 2015-07-30
    • 2015-03-27
    • 2011-08-15
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    相关资源
    最近更新 更多