【问题标题】:Learning Links and Linked Data Structures Java学习链接和链接数据结构 Java
【发布时间】:2014-04-02 20:58:10
【问题描述】:

我正在学习链接数据结构,这个概念对我来说很有意义,但代码却没有。

我希望有人可以为我解释一下。

这是来自演讲幻灯片:

我这里有一个构造函数:

private static class Node<E> {
    private E value;
    private Node<E> next;
    private Node( E value, Node<E> next ) {
        this.value = value;
        this.next = next;
    }
}

Value- 存储实际信息。 Next- 存储对先前存储的对象的引用。说得通。

然后……

public void addFirst( E o ) {
    Node<E> newNode = new Node<E>( o, null );
    if ( head == null ) {
        head = newNode;
    } else {
        newNode.next = head;
        head = newNode;
    }
}

上面的代码应该是添加元素。
但这是我的问题:newNode 已创建。 newNode.next 字段存储对对象头的引用。 (顺便说一句,我不知道在哪里声明了 head)然后head=newNode.

所以 Head 现在有了 newNode 存储的值,而 head.next 现在正在引用自己?

这里的问题是head中的原始值丢失了,没有newNode的引用。

我错过了什么吗?

【问题讨论】:

  • 您没有显示所有代码。显然 head 必须在某处声明,可能在 LinkedList 类中?
  • 如果要添加到单链表的开头,新的头应该是新的节点。旧的头部应该在 head.next 中。该代码绝对可以简化。
  • "head.next = newNode" 对我来说更有意义。
  • head.next 对我来说更有意义。但上面的代码来自演讲幻灯片。所以应该没有什么问题。
  • 很明显 head 是在类中的某处声明的,其中包含方法 addFirst

标签: java data-structures collections linked-list


【解决方案1】:

我认为您缺少对象的身份。考虑以下类及其字段:

List<E>
    Node<E> head
Node<E>
    E value
    Node<E> next

假设你有一个空列表,这意味着有这些对象(实际上只有一个):

List(1)
    head = null

为了更好地说明,我给了对象一个唯一的编号。实际上,一个对象是通过它的内存位置来明确识别的。

现在将"as" 添加到列表中:

Node&lt;E&gt; newNode = new Node&lt;E&gt;( o, null );

List(1)
    head = null
Node(2)
    value = "as"
    next = null

head = newNode;

List(1)
    head = Node(2)
Node(2)
    value = "as"
    next = null

现在添加"df":

Node&lt;E&gt; newNode = new Node&lt;E&gt;( o, null );

List(1)
    head = Node(2)
Node(2)
    value = "as"
    next = null
Node(3)
    value = "df"
    next = null

newNode.next = head;

List(1)
    head = Node(2)
Node(2)
    value = "as"
    next = null
Node(3)
    value = "df"
    next = Node(2)

head = newNode;

List(1)
    head = Node(3)
Node(2)
    value = "as"
    next = null
Node(3)
    value = "df"
    next = Node(2)

如您所见,单个节点的值没有改变,新的headNode(3) 没有引用自身。 head 的值为"df",下一个节点有"as",所以"df" 确实是在现有节点前面添加的。


正如其他人也指出的那样,addFirst 可以大大简化。看原文:

Node<E> newNode = new Node<E>( o, null );
if ( head == null ) {
    head = newNode;
} else {
    newNode.next = head;
    head = newNode;
}

head = newNode; 行出现在if 的两个分支的底部,因此可以将其移出:

Node<E> newNode = new Node<E>( o, null );
if ( head == null ) {
} else {
    newNode.next = head;
}
head = newNode;

...这使then 分支为空,因此最好反转条件:

Node<E> newNode = new Node<E>( o, null );
if ( head != null ) {
    newNode.next = head;
}
head = newNode;

仔细观察,在那之后ifnewNode.next 将是(旧的)head,无论if 是否被执行(那么很明显)(构造函数将其设置为 null,如果if 没有被执行,然后head 也是null)。所以另一种写法是:

Node<E> newNode = new Node<E>( o, head );
head = newNode;

现在你有了一个只使用过一次的变量:

head = new Node<E>( o, head );

但实际上,以您可以更好理解的方式编写代码,特别是如果您的目标是学习。

【讨论】:

  • 谢谢!这是完美的。
【解决方案2】:

将 addFirst 简化为:

public void addFirst( E o ) {
    head = new Node<E>( o, head );
}

head 将被设置为新节点。老头会在head.next

【讨论】:

    【解决方案3】:

    是的,你错过了那个叫做 addFirst 的方法,所以它是添加元素 before head 的方法。这正是方法真正在做的事情。它创建一个新节点,将其设置在头上,然后更新列表的头,指向一个新创建的节点。

    由于 java 是按值传递的,所以这段代码应该可以正常工作。

    【讨论】:

    • head=newNode 调用后,head 的值不会被删除吗?
    • java按值传递一切,所以答案是否定的
    【解决方案4】:

    老实说,这个例子肯定缺少一些东西。要么是作者写错了,要么是想让你思考问题并填空。根据您引用的 addFirst 方法,需要在定义 addFirst 方法的类中定义“head”。但是 Node 类示例的构造函数本质上是相同的。类构造函数将新节点添加到列表的前面(这正是 addFirst 所做的)。假设没有任何其他数据, addFirst() 在定义的 Node 上下文中没有任何意义。由于 Node 中的所有定义都是私有的,因此必须有一个包含对象来使用它(Node 可能是一个嵌套类)。

    所以可能是这样的:

    public class LinkedList<E> {
        private class Node<E> {
            private E value;
            private Node<E> next;
            private Node( E value, Node<E> next) {
                this.value = value;
                this.next = next;
            }
        }
    
        private Node<E> head;
    
        //Create a linked list
        public LinkedList() {
            head = null;
        }
    
        //Add a node to the front of the list
        public void addFirst( E o ) {
            Node<E> newNode = new Node<E>( o, head);
            head = newNode;
        }
    }
    

    使用它看起来像:

    LinkedList<String> list = new LinkedList<String>();
    list.addFirst("A");
    list.addFirst("B");
    list.addFirst("C");
    

    最终会在列表中出现类似“C”->“B”->“A”的内容。

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-04
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多