我的合并排序代码有什么问题?

时间:2012-02-07 20:30:02

标签: c# algorithm mergesort

我正在学习编码,虽然我尝试编写合并排序算法(我们在分析课程中听到的但不是家庭作业)。我正在使用培训师向我们展示的伪代码,但我无法确定问题。有人有机会指出我正确的方向吗?

编辑:算法仅返回List中的第一个值。

static List<int> mergeSort(List<int> mj)
{
    List<int>m = mj;
    if(m.Count <= 1)
        return m;
    List<int> merge = new List<int>();

    List<int> left = new List<int>();
    List<int> right = new List<int>();
    int middle = m.Count/2;

    for (int i = 0; i < middle; i++)
        left.Add(m[i]);
    for (int j = middle; j >= m.Count; j++)
        right.Add(m[j]);

    left = mergeSort(left);
    right = mergeSort(right);

    merge.AddRange(left);
    merge.AddRange(right);

    for (int k = 0; k < merge.Count; k++)
    {
        Console.Write(merge[k] + ",");
    }
    return merge;

}

4 个答案:

答案 0 :(得分:6)

你的代码问题(除了Mike Cowan提到的错误)是你没有进行任何实际的排序。你首先递归地将你的列表分成两半(这是正确的),但是你只是简单地将它们按原始顺序连接在一起,从而没有结果:

merge.AddRange(left);
merge.AddRange(right);

您需要做的是迭代您的两个子列表(通过归纳,应该分别在递归调用中排序),并按顺序将元素添加到合并列表

我们首先将0 th 元素:left[0]right[0]进行比较。无论哪个较小,都会添加到merge列表中,并且其子列表的计数器会递增。假设left[0] < right[0]:我们将left[0]添加到merge,然后在下一次迭代中,我们需要针对left[1]考虑right[0]。如果left[1]再次缩小,我们会将其添加到merge,然后在下一次迭代中,将left[2]right[0]进行对比。如果right[0]现在是两者中的较小者,我们会将 it 添加到merge,并在下一次迭代中将left[2]right[1]进行比较。等等。

这一直持续到其中一个子列表用完为止。当发生这种情况时,我们只需将剩余子列表中的所有元素添加到merge

int leftIndex = 0;        
int rightIndex = 0;

while (leftIndex < left.Count && rightIndex < right.Count)
    if (left[leftIndex] < right[rightIndex])
        merge.Add(left[leftIndex++]);
    else
        merge.Add(right[rightIndex++]);

while (leftIndex < left.Count)
    merge.Add(left[leftIndex++]);
while (rightIndex < right.Count)
    merge.Add(right[rightIndex++]);

此外,您不应该在的递归方法中写入控制台。将Console.Write来电转移到Main方法:

static void Main(string[] args)
{
    List<int> original = new List<int>(new int[] { 4, 75, 12, 65, 2, 71, 56, 33, 78,1, 4, 56, 85, 12, 5,77, 32, 5 });
    List<int> sorted = mergeSort(original);

    for (int k = 0; k < sorted.Count; k++)
        Console.Write(sorted[k] + ",");
}

答案 1 :(得分:5)

这一行:

for (int j = middle; j >= m.Count; j++)
    right.Add(m[j]);

应为:

for (int j = middle; j < m.Count; j++)
    right.Add(m[j]);

答案 2 :(得分:4)

首先,该行

for (int j = middle; j >= m.Count; j++)

应该是

for (int j = middle; j < m.Count; j++)

另外,你实际上从未实际合并左右,你只是将它们放在彼此的顶部。这条线

merge.AddRange(left);
merge.AddRange(right);

应该像

mergeLeftRight(left, right)

其中 mergeLeftRight 是您定义的第二个执行实际排序的函数。阅读关于合并排序的维基百科文章:http://en.wikipedia.org/wiki/Merge_sort

答案 3 :(得分:2)

简单的合并排序步骤

  1. if(mj.length == 1)返回mj;
  2. 拆分为左右列表并递归
  3. 当左右列表返回时,合并它们&lt; - 你不这样做
  4. 返回合并左右列表