【问题标题】:Adding an element to a singly linked list in Java在 Java 中将元素添加到单链表
【发布时间】:2016-10-08 19:04:59
【问题描述】:

我正在用 Java 实现一个单链表。我不喜欢这段代码的地方是我每次添加元素时都需要检查if (head.next == null)。但条件只满足一次,在添加第一个元素时。

有没有办法在没有这种条件的情况下实现单链非循环列表?

package sample;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class SinglyLinkedList<T> implements Iterable<T> {

    private Node<T> head = new Node<T>(null);
    private Node<T> last = null;

    public SinglyLinkedList(T... elements) {
        addAll(elements);
    }

    public void add(T element) {
        if (head.next == null) {
            head.next = new Node<T>(element);
            last = head.next;
        } else {
            Node<T> newNode = new Node<T>(element);
            last.next = newNode;
            last = last.next;
        }
    }

    public void addAll(T... elements) {
        for (T element : elements) {
            add(element);
        }
    }

    @Override
    public String toString() {
        Iterator<T> iterator = iterator();
        if (!iterator.hasNext()) {
            return "[]";
        }
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        while (iterator.hasNext()) {
            T element = iterator.next();
            builder.append(element);
            if (!iterator.hasNext()) {
                return builder.append("]").toString();
            }
            builder.append(", ");
        }
        return builder.toString();
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {

            Node<T> current = head;

            @Override
            public boolean hasNext() {
                return current.next != null;
            }

            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                Node<T> temp = current;
                current = current.next;
                return temp.next.element;
            }

        };
    }

    private static class Node<T> {

        private Node<T> next;
        private T element;

        Node(T element) {
            this.element = element;
        }

        @Override
        public String toString() {
            return element.toString();
        }
    }
}

【问题讨论】:

  • 为什么需要last 对象?
  • @MarounMaroun,因为我需要将元素附加到列表中。其实add这个方法应该叫addLast
  • @MarounMaroun,你认为last 是多余的吗?我看到了一些示例,它们只有头指针并遍历列表以将项目添加到末尾。因此,添加需要 O(n),而插入单链表需要 O(1)。另见bigocheatsheet.com

标签: java data-structures singly-linked-list


【解决方案1】:

您可以将 last 初始化为指向 head ,然后您的 if 是多余的:

private Node<T> head = new Node<T>(null);
private Node<T> last = head;

public void add(T element) {
        Node<T> newNode = new Node<T>(element);
        last.next = newNode;
        last = last.next;
}

【讨论】:

  • 谢谢!现在我明白它为什么起作用了。所以last 持有与head 相同内存的引用。所以在添加第一个元素时,last.next = newNode; 意味着last.next 以及head.next 将持有对第一个添加元素的引用。
【解决方案2】:

在很多情况下,“良好的 OO 设计”允许您无需 if/else 检查;最常见的是使用某种形式的多态性。

含义:不是询问某个对象有关某些属性的信息,而是在您的客户端代码中对此做出决定,而是以某种方式确保您的客户端代码可以简单地调用某个其他对象的方法。然后,“if”被“隐藏”在最初生成“其他对象”并将其提供给您的客户端代码的代码中。 (您可以在这些 videos 中找到一些很好的例子。

但是 - 我认为在这种情况下这显然是矫枉过正!

关键是:从可读性的角度来看,一次检查确实没有坏处(您可能可以将事物重构为更多方法)。和性能......也不重要。如果您的代码被如此频繁地调用以至于这很重要,那么 JIT 无论如何都会启动,并且可能会创建在大多数情况下直接采用正确分支的代码。

因此:这是一个很好的实现;我认为你不应该担心这个 if-check there!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    相关资源
    最近更新 更多