【问题标题】:doubly-circular linked list in c#C#中的双循环链表
【发布时间】:2011-06-14 06:55:42
【问题描述】:

我使用的是双循环链表。添加值后,我正在从列表中检索值。我正在使用此代码添加值:

public void Add(T data)
{
    if (root == null)
    {
        this.Add(data);
        root = new LinkedListNode<T>(data);
        last = root;
    }
    else
    {
        last.Next = new LinkedListNode<T>(data);
        last.Next.Previous = last;
        last = last.Next;
    }
}

我给出的数据是:

char[] dir = { 'n', 'w', 's', 'e' };
TestProject.classes.LinkedList<char> list = new TestProject.classes.LinkedList<char>();

foreach (char c in dir)
{
    list.Add(c);
}

我正在检索列表数据:

public LinkedListNode<T> GetAt(int index)
{
    var current = root;
    for (int i = 0; i < index; i++)
    {
        if (current == null)
            return null;
        current = current.Next;
    }
    return current;
}

问题是它在检索节点值时将current 的值作为null 给出。

该列表是 stackoverflow 本身的一个示例。

请帮帮我..

我的整个链表类如下:

public class LinkedList<T>
{
    protected LinkedListNode<T> root = null;
    protected LinkedListNode<T> last = null;
    public LinkedList()
    {
    }

    public string ToString()
    {
        StringBuilder sb = new StringBuilder();
        var node = root;
        while (node != null)
        {
            sb.Append("{ " + node.Data.ToString() + " } ");
            node = node.Next;
        }
        return sb.ToString();
    }

    public T this[int index]
    {
        get
        {
            var node = GetAt(index);
            if (node == null)
                throw new ArgumentOutOfRangeException();
            return node.Data;
        }
        set
        {
            var node = GetAt(index);
            if (node == null)
                throw new ArgumentOutOfRangeException();
            node.Data = value;
        }
    }

    public LinkedListNode<T> GetAt(int index)
    {
        var current = root;
        for (int i = 0; i < index; i++)
        {
            if (current == null)
                return null;
            current = current.Next;
        }
        return current;
    }

    public void Add(T data)
    {
        if (root == null)
        {
            this.Add(data);
            root = new LinkedListNode<T>(data);
            last = root;
        }
        else
        {
            last.Next = new LinkedListNode<T>(data);
            last.Next.Previous = last;
            last = last.Next;
        }
    }
}

public class LinkedListNode<T>
{
    public T Data { get; set; }

    public LinkedListNode(T data)
    {
        Data = data;
    }

    public LinkedListNode<T> Next { get; set; }
    public LinkedListNode<T> Previous { get; set; }
}

【问题讨论】:

  • 这不是:public void Add(T data) { if (root == null) { this.Add(data); 最终递归(即堆栈溢出)吗?你一遍又一遍地重复调用同一个函数……没有理由让 root 在调用之间发生变化……
  • @forsvarir:但是当我从“public LinkedListNode GetAt(int index)”函数中检索数据时,值正在发生变化..它给出的当前值为空..
  • @kawade 您是否在构造函数中初始化root?您是否将last 设置为相同的值?
  • @forsvarir: 不,我没有在 cunstructor 中初始化任何东西
  • 你能发布剩下的列表类吗?

标签: c# list linked-list


【解决方案1】:

如果root == null在调用this时,这个函数没有理由工作,它应该在一遍又一遍地调用自己时导致堆栈溢出......

public void Add(T data)
{
    if (root == null)
    {
        this.Add(data);  // recurse?!?

所以,如果您成功调用它,似乎有三个选项:

  • 您已成功配置编译器优化,以便删除调用(这似乎不太可能,但我想有可能)。
  • 您永远不会使用root==null 调用它,这意味着其他东西正在修改root,可能因为它受到保护,但是如果您提供的使用代码是正确的,则不应该是这种情况,因为你没有提到派生类。
  • 您的使用代码被改写了,实际上您是从 try/catch 块中调用 add 并忽略抛出的异常。

正如我在评论中所说,删除对this.add(data) 的额外调用应该可以解决您的问题(通过填充列表),但是,我建议您在调试器中逐步执行函数调用,以便你可以看到发生了什么。我很想知道它是否真的调用了“添加”函数。

就从列表中检索信息而言,get 函数看起来应该可以工作,假设信息已正确放入列表中,并且您在插入数据的同一列表中调用 get。同样,如果它不工作,调试器是你的朋友,当你试图找出哪个位没有按照你期望的方式填充时。

【讨论】:

    【解决方案2】:

    正如@forsvarir 所指出的:当不存在根节点时​​,您不应该再次调用Add。只需删除该呼叫,一切都会好起来的。

    如果我是你,我不会将 Indexer 或 GetAt 方法添加到 LinkedList 实现中。使用需要索引访问的链表是非常低效的。

    让您的列表改为实现IEnumerable,并让用户使用 LINQ。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2020-12-18
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多