4

我正在尝试采用我制作的自定义链表类并制作一个枚举器以在我的一个 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()
    {
    }
}
4

4 回答 4

3

迭代器块使创建实现的对象IEnumerable<T> 变得更加容易:

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

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

于 2013-12-10T18:24:09.847 回答
1

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

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

于 2013-05-23T22:12:11.033 回答
1

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

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 + 不要忘记构造函数。

于 2018-03-04T17:28:48.340 回答
0

我不知道您的Node<T>代码是什么样的,但这看起来很奇怪:

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并更改startstartNode. 此外,如果node.getNext()不返回 Node 对象,则应重命名该方法以指示它在做什么。

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

我可能仍然建议更改一些名称以澄清操作。:)

于 2013-12-10T18:18:31.177 回答