【问题标题】:What's wrong with my merge sort implementation [closed]我的合并排序实现有什么问题[关闭]
【发布时间】:2018-06-02 02:07:53
【问题描述】:

我确定我犯了一个非常愚蠢的错误,但我已经做了几个小时了,我只是希望我的代码能够漂亮地排序......当奇数进入等式时,实现出现了问题。

下面是我的MergeSplit方法:

     static List<Motor> MergeSplit(List<int> ListX)
     {
            int n = ListX.Count;
            if (n <= 1)
                return ListX;

            List<int> left = new List<int>();
            List<int> right = new List<int>();

            for (int i = 0; i < n; i++)
            {
                if (i < (n / 2))
                    left.Add(ListX[i]);
                else
                    right.Add(ListX[i]);
            }

            left = MergeSplit(left);
            right = MergeSplit(right);
            return Merge(left, right);

      }

这里是Merge 方法:

    static List<int> Merge(List<int> ListX, List<int>  ListY)
    {
        List<int> result = new List<int>();

        int i = 0;
        while (ListX.Count > i && ListY.Count > i)
        {
            if (ListX[i] > ListY[i])
            {
                result.Add(ListY[i]);
                result.Add(ListX[i]);
            }
            else
            {
                result.Add(ListX[i]);
                result.Add(ListY[i]);
            }
            i++;
        }

        //If odd, add the rest to the result
        if (ListX.Count > ListY.Count)
            result.Add(ListX[ListX.Count - 1]);
        else if (ListY.Count > ListX.Count)
            result.Add(ListY[ListY.Count - 1]);

        return result;
    }

感谢您的帮助!

更新

算法只是没有正确排序某些输入

【问题讨论】:

  • 但是您的代码甚至不会编译,因为您返回 return ListX 但返回类型是 List&lt;Motor&gt;
  • Something is going wrong 是一个绝对无用的问题描述。相反,具体解释出了什么问题。你有什么问题?。如果您需要帮助,您需要清楚地解释问题并提出具体问题。 Something is going wrongWhat's wrong? 在任何意义上都不是具体的。您提供的输入是什么?您得到了哪些不符合您期望的输出?
  • 欢迎来到 Stack Overflow!这里的大多数人都会回答问题,但他们不会为您调试代码。这个问题可能会被否决并关闭。但是,如果您可以缩小问题范围,您可以编辑您的问题或发布另一个问题。请务必使用tour 并访问How to Ask。祝你好运!

标签: c# sorting mergesort


【解决方案1】:

问题在于您的合并例程

您正在比较左右并将它们分别添加到列表中,您应该比较头部,并将最低的添加到结果中,并分别删除该头部以进行下一次比较

这是来自维基https://en.wikipedia.org/wiki/Merge_sort的伪代码

while left is not empty and right is not empty do
    if first(left) ≤ first(right) then
        append first(left) to result
        left := rest(left)
    else
        append first(right) to result
        right := rest(right)

你可以在这里看到为什么这很重要

正如您所看到的,它实际上比较了第一个左边和第一个右边,然后将它们添加到结果中并从列表中删除该项目。这与您正在做的事情大不相同。您要么需要 2 个索引变量,要么从列表中删除项目

while (listX.Count > 0 && listY.Count > 0)
   if (listX[0] > listY[0])
   {
      result.Add(listY[0]);
      listY.RemoveAt(0);
   }
   else
   {
      result.Add(listX[0]);
      listX.RemoveAt(0);
   }


if (listX.Count > 0)
   result.AddRange(listX);
else if (listY.Count > 0)
   result.AddRange(listY);

只是为了好玩,我发现这更容易与队列一起玩,他们似乎喜欢这种东西

private static Queue<int> Merge(Queue<int> left, Queue<int> right)
{
   var result = new Queue<int>();

   while (left.Count > 0 && right.Count > 0)
      result.Enqueue(left.Peek() > right.Peek() ? right.Dequeue() : left.Dequeue());

   foreach (var item in left)
      result.Enqueue(item);

   foreach (var item in right)
      result.Enqueue(item);

   return result;
}

private static Queue<int> MergeSplit(Queue<int> list)
{
   var n = list.Count;

   if (n <= 1)
      return list;

   var left = new Queue<int>();
   var right = new Queue<int>();

   for (var i = 0; i < n; i++)
      if (i < n / 2)
         left.Enqueue(list.Dequeue());
      else
         right.Enqueue(list.Dequeue());

   left = MergeSplit(left);
   right = MergeSplit(right);
   return Merge(left, right);
}

用法

var list = new List<int> { 8, 7, 6, 4, 43, 23, 435, 76, 7, 7877, 5, 421, 2 };
var results = MergeSplit(new Queue<int>(list));
Console.WriteLine(string.Join(", ", results));

输出

2, 4, 5, 6, 7, 7, 8, 23, 43, 76, 421, 435, 7877

Full Demo Here

【讨论】:

  • 非常感谢!我意识到提出对社区没有好处的问题是不好的,所以我非常感谢您的帮助!很容易理解 - 是一个基本的概念错误。再次感谢!对于排队代码!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
相关资源
最近更新 更多