学习链接和链接数据结构Java

时间:2014-04-02 20:58:11

标签: java data-structures collections linked-list

我正在学习关联数据结构,这个概念对我有意义,但代码没有。

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

这是演讲幻灯片:

我在这里有一个构造函数:

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;
    }
}

价值 - 存储实际信息。 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=newNode

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

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

我错过了什么吗?

4 个答案:

答案 0 :(得分:0)

简化addFirst:

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

head将被设置为新节点。旧的头部将在head.next

答案 1 :(得分:0)

是的,你错过了这个方法叫做addFirst,所以它是在头之前添加元素的方法。这正是真正做的方法。它创建一个新节点,将其设置为下一个,然后更新列表的头部,指向新创建的节点。

由于java是按值传递,因此该代码应该可以正常工作。

答案 2 :(得分:0)

我认为你错过了对象的身份。请考虑以下类及其字段:

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

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

List(1)
    head = null

为了更好地说明,我给了对象一个唯一的数字。实际上,通过其存储位置明确地识别对象。

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

Node<E> newNode = new Node<E>( 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<E> newNode = new Node<E>( 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;

仔细观察,在if之后,newNode.next将是(旧的)head,无论if是否已被执行(然后显而易见)或不执行(构造函数将其设置为null,如果未执行if,则head也是null。所以另一种写这个的方法是:

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

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

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

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

答案 3 :(得分:0)

说实话,这个例子肯定缺少一些东西。无论是作者犯了错误,还是想让你仔细思考并填补空白。根据您引用的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”的内容 - &gt; “B” - &gt;列表中的“A”。