【问题标题】:How to append a node in a doubly linked list in Java?如何在Java中的双向链表中附加一个节点?
【发布时间】:2016-11-05 04:33:48
【问题描述】:

我开始学习 Java。作为一项任务,我必须使用我包含在代码中的给定接口来实现一个双向链表。 我的方法insertAtTheEnd() 似乎无法正常工作,因为在插入几个元素后我在元素上有值null。 我检查了有关该主题的类似问题,并尝试将答案应用于我的问题,但无法进一步了解。因此,感谢任何帮助我如何设置此方法以使其工作。 谢谢!

public interface IValueElement
{
    public String getName();
    public void setName(String paramName);
    public int getValue();
    public void setValue(int paramValue);
}

public interface IListElement
{
    public IValueElement getValueElement();
    public void setValueElement(IValueElement value);
    public IListElement getPredecessor();
    public void setPredecessor(IListElement predecessor);
    public IListElement getSuccessor();
    public void setSuccessor(IListElement successor);
}

public interface IList
{
    public IListElement getHead();
    public void insertAtTheEnd(IValueElement value);
//...
}

public class List implements IList
{
    public List()
    {
        if (head == null)
        {
            head = new ListElement(null);
        }
        else
        {
            return;
        }   
    }

    private IListElement head;

    public IListElement getHead()
    {
        return head;
    }

    public void insertAtTheEnd(IValueElement value)
    {
        if (head.getSuccessor() != null)
        {
            IListElement l = head;
            while (l.getSuccessor() != null)
                l = l.getSuccessor();
            IListElement q = new ListElement(value);
            l.setPredecessor(q);
        }
        else
        {
            IListElement q = new ListElement(value);
            q.setPredecessor(head);
            q.setSuccessor(null);
            head.setSuccessor(q);
            head.setPredecessor(q);
        }
    }
}

另外,这里是我对 ValueElement 和 ListElement 的实现:

//ListElement.java

public class ListElement implements IListElement
{
    public ListElement(IValueElement value)
    {
        this.valueElement = checkValueElementAttribute(value);
    }

    private IValueElement checkValueElementAttribute(IValueElement value)
    {
        return (value == null) ? new ValueElement(null, 0) : value;
    }

    private IValueElement valueElement;

    public IValueElement getValueElement()
    {
        return this.valueElement;
    }

    public void setValueElement(IValueElement value)
    {
        if (value != null)
        {
            this.valueElement = value;
        }
    }

    private IListElement predecessor;

    public IListElement getPredecessor()
    {
        return this.predecessor;
    }

    public void setPredecessor(IListElement predecessor)
    {
        this.predecessor = predecessor;
    }

    private IListElement successor;

    public IListElement getSuccessor()
    {
        return this.successor;
    }

    public void setSuccessor(IListElement successor)
    {
        this.successor = successor;
    }
}


// ValueElement.java
public class ValueElement implements IValueElement
{
    private String name;

    public String getName()
    {
        return this.name;
    }

    public void setName(String paramName)
    {
        if (paramName != null)
        {
            this.name = paramName;
        }
    }

    public ValueElement(String name, int value)
    {
        if (name == null || name.equals(""))
        {
            name = "default";
        }
        else
        {
            this.name = name;
        }
        this.value = value;
    }

    private int value;

    public int getValue()
    {
        return this.value;
    }

    public void setValue(int paramValue)
    {
        if (paramValue != 0)
        {
            this.value = paramValue;
        }
    }

    public String toString()
    {
        return "Name: " + this.name + " - Value: " + this.value;
    }

}

【问题讨论】:

  • 为什么构造函数包含这些行,它们完全没有必要,因为新构造的对象总是将head 设为空。您可以完全删除构造函数并在声明它的位置初始化head
  • 查看您的 if 块。与 else 块不同,它不设置任何东西的后继者。所以缺少一些东西。另外,q 是新的结束节点,所以它应该是l 的后继节点,而不是它的前任节点。好的变量命名会对您有所帮助。
  • @Kayaman:你说得对,谢谢你的提示。头部不应该为空,这是一个错误。
  • @JB Nizet:好的,我明白你的意思,必须回顾一下这个块,并尝试更深入地了解我的前任和继任者到底发生了什么。
  • 当您在调试器中单步执行代码并查看每一行设置的值时,哪一行没有达到您的预期?

标签: java doubly-linked-list


【解决方案1】:

请提供完整的代码,以便我们运行它并帮助您,目前我们只能想到这些问题:

1) 您可能没有在这些节点上调用 setValueElement 2)您的 else 块包含对同一元素的前任和后继的设置,因此它是明确错误的代码行

这不应该是你的代码

public void insertAtTheEnd(IValueElement value)
    {
        if (head.getSuccessor() != null)
        {
            IListElement l = head;
            while (l.getSuccessor() != null)
                l = l.getSuccessor();
            IListElement q = new ListElement(value);
            l.setSuccessor(q);
        }       

    else
        {
            IListElement q = new ListElement(value);
            q.setPredecessor(head);
            q.setSuccessor(null);
            head.setSuccessor(q);
        }
    }

【讨论】:

  • 这应该是评论
  • 谢谢,我会检查那行。我刚刚包含了请求的代码(请参阅上一个答案)。
  • @AADTechnical 我的声誉不允许我发表评论
  • 谢谢,我早先看到了问题所在,在您发表评论后,我得到了相同的结果。我仍然有问题,插入元素后 head 的前身为空。根据分配,这一定不能发生,并且 head 的前身应该是指最后一个元素。这就是我最初写的原因 - head.setPredecessor(q) - 但这不起作用。
  • @mark 我明白了,你的任务要求你创建一个循环链表,不是吗? .在这种情况下,只需将最后一个元素的后继设置为 head 并将 head 的前导设置为最后一个元素。另外,如果您喜欢答案,请将其标记为已接受:)
【解决方案2】:

是否已经为您提供了 IValueElement 和 IListElement 的实现,或者它们是否也必须实现?从您提供的代码中,我看不到它们的实现。

关于您的方法 insertAtTheEnd,看起来您的想法基本正确,但也许您可以改进它。

在 if 块的末尾,您将 l 的前任设置为 q。我认为这可能是错误的方式。那时 l 是列表中的最后一个元素,沿着后继链走直到没有更多的元素,在我看来,现在应该将新元素 (q) 添加为 l 而不是前任的后继元素。 此外,我认为 q 需要将其前身设置为 l。

在你的 else 块中你正确设置了 q 的前任和后继,并且正确设置了 head 的后继,但是,为什么你将 head 的前任设置为 q?这将使 q 既是领导者的继任者,也是前任者。我认为您应该删除最后一个 setPredecessor 调用。

【讨论】:

  • 感谢您的回答,我会检查并尝试改进它。由于我是 Java 新手,这可能需要我一些时间。我刚刚包含了 IValueElement 和 IListElement 的实现。
猜你喜欢
  • 2014-12-13
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
  • 2022-12-09
相关资源
最近更新 更多