【问题标题】:Need help making a enumerator for a linked list in c#需要帮助在 c# 中为链表创建枚举器
【发布时间】:2013-05-19 10:25:13
【问题描述】:

我正在尝试采用我制作的自定义链表类并制作一个枚举器以在我的一个 C# 程序中使用它。我不想展示太多我的代码,所以希望这已经足够了。

我不确定,但这就是枚举器的样子吗?

class SinglyLinkedListEnumerator<T> : IEnumerator<T>
{
    private Node<E> node;
    private Node<E> start;

    public SinglyLinkedListEnumerator(Node<T> node)
    {
        this.node = node;
        start = node;
    }

    public T Current
    {
        get { return node.getData(); }
    }

    public Boolean MoveNext()
    {
        if (node.getNext() != null)
        {
            node = node.getNext();
            return true;
        }
        return false;
    }

    public void Reset()
    {
        node = start;
    }

    public void IDisposable.Dispose()
    {
    }
}

【问题讨论】:

    标签: c# enumeration singly-linked-list


    【解决方案1】:

    迭代器块使创建实现IEnumerable&lt;T&gt;的对象变得更加容易

    public static IEnumerable<T> Iterate<T>(Node<T> root)
    {
        var current = root;
        while (current != null)
        {
            yield return current.getData();
            current = current.getNext();
        }
    }
    

    它删除了大部分样板代码,只允许您定义所有逻辑以确定序列中的节点是什么,同时仍然提供像您一样写出所有代码的所有功能。

    【讨论】:

    • 仅供参考,可能与此问答相关,也可能不相关,但这里有一个问答,比较了 iterator blockselect 的使用:@987654321 @
    【解决方案2】:

    在 C# 世界中,这个概念称为枚举,而不是迭代。不要与enum 混淆。

    无论如何,您正在寻找的相应接口是System.Collections.Generic 命名空间中的IEnumerable&lt;T&gt;IEnumerator&lt;T&gt;。查看他们的文档,您应该一切顺利。这个概念本身与您在 Java 中所做的几乎相同。

    【讨论】:

    • 我查看了他们的文档,我看到了“属性”和方法。我不确定属性是什么意思,那些是必需的方法吗?那么这是否使普通方法成为可选的?我仍然很困惑。我会将我的 next() 方法更改为 move() 吗?文档也没有告诉我这些方法应该返回什么,但我可能只是想念它。
    • 属性是 Java 中不存在的语言特性。在 Java 中,您有 getter 和/或 setter 方法。在 C# 中,您有属性。 msdn.microsoft.com/en-us/library/x9fsa0sw%28v=vs.80%29.aspx.
    • 关于 MoveNext:在 C# 中,移动到下一个元素并获取是分开的。你有Current-Property(在Java中是getCurrent()),你有MoveNext(),如果它可以前进到下一个元素,它会返回true,而不是返回下一个元素本身。
    • 我更新了显示我现在拥有的问题,你能告诉我它看起来是否正确吗?
    • 请注意,即使在 C# 中,也有很多人仍然使用术语 迭代。使用它并没有错。
    【解决方案3】:

    链表的枚举器应如下所示:

    public class MyLinkedList : IEnumerable        {
            Node head = null;
            Node current = null;
    
            public IEnumerator GetEnumerator()            
            {
                current = head;
                while (current != null)
                {
                    yield return current.Data;
                    current = current.Next;
                }            
            }            
    

    虽然节点本身

    public class Node 
        {
            public int Data;
            public Node Next;
            public Node(int value) { Data = value; }            
        }
    

    对于二叉树,您应该实现所有三个:Current、MoveNext 和 Reset + 不要忘记构造函数。

    【讨论】:

      【解决方案4】:

      我不知道你的 Node&lt;T&gt; 代码是什么样的,但这看起来很奇怪:

      public Boolean MoveNext()
      {
          if (node.getNext() != null)
          {
              node = node.getNext();
              return true;
          }
          return false;
      }
      

      理想情况下,MoveNext 看起来应该是这样的:

      public Boolean MoveNext()
      {
          // make sure current node is not null
          if (node != null)
          {
              node = node.getNext();
          }
      
          // simply return whether current node is null or not
          return node != null;
      }  
      

      在您的初始方法中,您将获得下一个节点两次,可能给您错误的结果。我假设getNext 只是返回对当前节点下一个兄弟节点的引用。否则,我看不到您的枚举器(或迭代器)类有任何初始问题。

      为了清楚起见,我将使用currentNode 代替node 并将start 更改为startNode另外,如果node.getNext() 没有返回一个Node 对象,那么该方法应该被重命名以表明它在做什么。

      我假设node.getNext() 正在移动一个内部引用,但@Servy 纠正了我。谢谢!

      我可能仍然建议更改名称以阐明操作。 :)

      【讨论】:

      • 请记住,node 本身并不是一个迭代器,它是一个节点。它的下一个节点是固定的。调用getNext 不会改变节点来改变它的下一个节点。虽然您的更改确实使它更简洁一些,但他的代码并没有错误
      • 谢谢@Servy ...似乎可以对OP的代码做出一些假设,但那时可能不准确。 ;)
      • 这似乎是一个非常安全的假设。您假设调用GetNext 将更改节点对其下一个节点的内部引用。 那个假设的依据是什么?我没有看到。 OP还表示他的代码有效,他只是想知道这是否是好的做法。他已经表明他的代码有效,这使我的假设非常安全。
      • 我的假设是基于这一行:if (node.getNext() != null)。我处于 Enumerator.MoveNext() 模式。我同意你的看法,尽管我的假设是错误的。
      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 2012-12-02
      相关资源
      最近更新 更多