0

我无法为下面定义的单个列表实现排序算法(合并)我的合并排序方法总是给我 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
4

1 回答 1

8

我无法弄清楚出了什么问题,你们能帮帮我吗?

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

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

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

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

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

我要编写的第一个调试工具是一个方法,它接受一个特定的节点并生成一个逗号分隔的整数列表,该列表中从该节点开始。因此,您会说 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)。然后运行你的测试用例。如果你有一个错误,那么程序会告诉你,调试器会带你去解决它。

祝你好运!

于 2009-07-26T14:12:40.663 回答