【问题标题】:Trouble in implementing link list sorting in c#在 C# 中实现链接列表排序的问题
【发布时间】:2009-07-25 21:19:23
【问题描述】:

我在为单个列表实现排序算法(合并)时遇到问题,定义如下 我的mergesort方法总是给我null..我无法弄清楚出了什么问题 你们能帮帮我吗?

节点类

public class Node
        {
           private int data;
           private  Node next;
    }

链表类

public class SSL
        {
            private Node head;
    }

我的合并排序代码

public static void MergeSort(SSL a)
        {
            SSL x = new SSL();
            SSL y = new SSL();
            if (a.Head == null || a.Head.Next == null) // base case if list has 0 or 1 element
                return;
            AlternateSplitting(a, x, y);
            MergeSort(x);
            MergeSort(y);
            a = SortedMerge(x, y);
        }

我实现了以下辅助方法来实现归并排序

AlternateSplitting:此方法会将列表拆分为 2 个列表

public static void AlternateSplitting(SSL src, SSL odd, SSL even)
        {

            while (src.Head != null)
            {
                MoveNode(odd, src);
                if (src.Head != null)
                    MoveNode(even, src);
            }


        } // end of AlternateSplitting

此方法将合并2个列表并返回一个新列表

public static SSL SortedMerge(SSL a, SSL b)
        {
            SSL c = new SSL();
            if (a.Head == null)
                return b;
            else
                if (b.Head == null)
                    return a;
                else
                {
                    bool flagA = false;
                    bool flagB = false;
                    Node currentA = new Node();
                    Node currentB = new Node();

                    while (!flagA && !flagB)
                    {
                        currentA = a.Head;
                        currentB = b.Head;
                        if (currentA.Data < currentB.Data)
                        {
                            MoveNodeToEnd(a, c);
                            currentA = a.Head;
                            if (currentA== null)
                                flagA = true;
                        }
                        else
                            if (currentA.Data > currentB.Data)
                            {
                                MoveNodeToEnd(b, c);
                                currentB = b.Head;
                                if (currentB== null)
                                    flagB = true;

                            }
                    } // end of while

                    if (flagA)
                    {

                        while (currentB != null)
                        {
                            MoveNodeToEnd(b, c);
                            currentB = b.Head;
                        }

                    }
                    else
                        if(flagB)
                        {

                            while (currentA != null)
                            {
                                MoveNodeToEnd(a, c);
                                currentA = a.Head;
                            }

                        }
                    return c;


                } // end of outer else

        } // end of function sorted merge

【问题讨论】:

  • 可能。 MoveNode 和 MoveNodeToEnd 以及您正在动态创建新列表的事实都看起来很糟糕。你应该在操作节点。
  • @Sanjaya:除非我创建列表,否则我该怎么做?你能再解释一下吗?

标签: c# linked-list


【解决方案1】:

我无法弄清楚是什么 错了你们能帮帮我吗?

找到一个错误,然后修复它一天。教你如何发现错误,相信我,修复错误需要一生的时间。 :-)

您的根本问题不在于算法错误 - 但是,由于它给出了不正确的结果,因此它肯定是错误的。但这不是根本的问题。根本问题是您不知道如何找出程序出错的地方。先解决这个问题!了解如何调试程序。

能够发现程序中的缺陷是一项后天的技能,就像任何其他技能一样——您必须学习基础知识,然后练习数百小时。所以学习基础知识。

首先要熟悉调试器的基本功能。确保您可以单步执行程序、设置断点、检查局部变量等等。

然后给自己写一些调试工具。它们可能很慢——你只会在调试时使用它们。您不希望在代码的生产版本中使用调试工具。

我要编写的第一个调试工具是一个方法,它接受一个特定的节点并生成一个逗号分隔的列表,其中包含从该节点开始的列表中的整数。因此,您会说 DumpNode(currentB),然后返回的是“{10,20,50,30}”。显然,如果您可以为节点做同样的事情,那么对 SSL 做同样的事情是微不足道的。

我还会编写一些工具来做一些事情,比如计算列表中的节点,告诉你给定的列表是否已经排序,等等。

现在您可以在监视窗口中输入一些内容,以便更轻松地观察数据结构的变化。 (有一些方法可以让调试器自动进行这种渲染,但我们在这里讨论的是基础知识,所以让我们保持简单。)

这将帮助您更轻松地了解通过程序的数据流。这可能足以发现问题。但也许不是。最好的错误是那些向你表明自己身份的错误,它们挥舞着一面大红旗,上面写着“这里有一个错误”。 调试断言是将难以发现的错误转化为自我识别错误的工具。

在编写算法时,想一想“什么一定是真的?”在不同的点。例如,在 AlternateSplitting 运行之前,假设列表有 10 个项目。运行完成后,两个结果列表最好各有 5 个项目。 如果没有,如果每个有 10 个项目或每个有 0 个项目,或者一个有 3 个,另一个有 7 个,很明显,你在那里的某个地方有一个错误。所以开始编写仅调试代码:

public static void AlternateSplitting(SSL src, SSL odd, SSL even)        
{
#if DEBUG
  int srcCount = CountList(src);
#endif
  while (src.Head != null) { blah blah blah }
#if DEBUG
  int oddCount = CountList(odd);
  int evenCount = CountList(even);
  Debug.Assert(CountList(src) == 0);
  Debug.Assert(oddCount + evenCount == srcCount);
  Debug.Assert(oddCount == evenCount || oddCount == evenCount + 1);
#endif
}

现在 AlternateSplitting 将在调试版本中为您工作以检测其自身的错误。如果您的错误是因为拆分没有正确运行,您会在运行它时立即知道。

对列表合并算法做同样的事情——找出“我知道此时 X 必须为真”的每个点,然后在该点编写一个 Debug.Assert(X)。然后运行你的测试用例。如果你有一个错误,那么程序会告诉你,调试器会带你去解决它。

祝你好运!

【讨论】:

  • 明智的话。我希望更多的人会回答这样的问题:)
  • 我明白你的意思了,感谢 Eric 的明智之言....我会努力解决这个问题
猜你喜欢
  • 1970-01-01
  • 2019-11-24
  • 2020-02-25
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多