【问题标题】:Doubly Linked List implementation not working双向链表实现不起作用
【发布时间】:2019-08-16 01:41:00
【问题描述】:

我有一个双向链表实现如下:

public class DoublyLinkedList<T> {
    DoublyLinkedListNode<T> head;

    public DoublyLinkedListNode<T> getHead() {
        return head;
    }

    public void setHead(DoublyLinkedListNode<T> head) {
        this.head = head;
    }

    public void addNode(DoublyLinkedListNode<T> node) {
        if(null == head) {
            head = new DoublyLinkedListNode<>(node.getData());
        }else{
            traverseAndAdd(node);
        }
    }

    private boolean traverseAndAdd(DoublyLinkedListNode<T> node) {
         boolean isAdded = false;
    DoublyLinkedListNode<T> tempHead = head;
  do{
        if(tempHead.getNext() == null) {
            head.setNext(node);
            node.setPrev(head);
            isAdded = true;
            break;
        }

         tempHead = tempHead.getNext();
    }while(null != tempHead);

    return isAdded;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        while(null != head) {
            sb.append(head.getData());
            head = head.getNext();
        }

        return sb.toString();
    }

}

下面是我的 DoublyLinkedListNode 类:

public class DoublyLinkedListNode<T> {

    T data;
    DoublyLinkedListNode<T> prev;
    DoublyLinkedListNode<T> next;

    public DoublyLinkedListNode(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public DoublyLinkedListNode<T> getPrev() {
        return prev;
    }

    public void setPrev(DoublyLinkedListNode<T> prev) {
        this.prev = prev;
    }

    public DoublyLinkedListNode<T> getNext() {
        return next;
    }

    public void setNext(DoublyLinkedListNode<T> next) {
        this.next = next;
    }
}

现在,当我创建一个 DoublyLinkedList 实例并尝试以某种方式向其添加节点时,我的 head 实例变量始终为空。

即使我在 addNode 方法中对其进行初始化,当我尝试添加下一个节点时它始终为 null。

如果这个实现有任何问题,请告诉我。

以下是我如何将节点添加到我的列表中:

DoublyLinkedList<Integer> mylist = new DoublyLinkedList<>();
DoublyLinkedListNode<Integer> node1 = new DoublyLinkedListNode<>(10);
DoublyLinkedListNode<Integer> node2= new DoublyLinkedListNode<>(20);
DoublyLinkedListNode<Integer> node3 = new DoublyLinkedListNode<>(30);
DoublyLinkedListNode<Integer> node4 = new DoublyLinkedListNode<>(40);
DoublyLinkedListNode<Integer> node5 = new DoublyLinkedListNode<>(50);
DoublyLinkedListNode<Integer> node6 = new DoublyLinkedListNode<>(60);
mylist.addNode(node1);
mylist.addNode(node2);
mylist.addNode(node3);
mylist.addNode(node4);
mylist.addNode(node5);
mylist.addNode(node6);
System.out.println(mylist.toString());

【问题讨论】:

  • 我认为的问题是每次“添加节点”或打印列表时都会更改“头”光标的指针。因此,标题光标丢失了对列表中第一项的引用。尝试使用新的变量克隆头。
  • @LuisDaniel 头部光标的指针没有改变。每次我添加一个新的节点头时,结果总是为空。在调试时,我注意到每次在下一行执行 head = new DoublyLinkedListNode() 时,head 的值都显示为 null。
  • 如果是null为什么不抛出空指针异常?
  • @RomanC 我没有抛出空指针,因为我有一个明确的检查来初始化它是否为空。这永远不会抛出空指针
  • 不,您没有签入初始化或实现。另外,如果 head 不为空,请不要更改它的值。如果代码中的某些内容不应该为空,那么您应该声明空指针异常并记录它。

标签: java doubly-linked-list


【解决方案1】:

您的头引用并不总是空的,它确实会为添加第一个节点而初始化,这是您代码中 traverseAndAdd() 方法中的问题。

private boolean traverseAndAdd(DoublyLinkedListNode<T> node) {
    boolean isAdded = false;
    while(null != head.getNext()) {
        if(head.getNext() == null) {
            //this code is unreachable
        }
        //why are u changing the head value
        head = head.getNext();
    }
    return isAdded;
}

所以用

替换函数
private void traverseAndAdd(DoublyLinkedListNode<T> node) {
    DoublyLinkedListNode<T>temp=head;
    while(null != temp.getNext()) {
        temp=temp.getNext();
    }
    temp.setNext(node);
    node.setPrev(temp);
}

另一个错误,在 toString() 方法中,您将 null 值分配给 head。 head 值首先被初始化,但每次调用 toString() 时都会变为 null。将方法替换为

public String toString() {
    StringBuffer sb = new StringBuffer();
    DoublyLinkedListNode<T>temp=head;
    while(null != temp) {
        sb.append(temp.getData());
        temp = temp.getNext();
    }
    return sb.toString();
}

【讨论】:

  • 另外,你可以简单地写 head = node;而不是 head = new DoublyLinkedListNode(node.getData());
  • 注意点。我会做出有问题的改变。
  • 它也没有为我初始化。每次我添加一个节点时,它都会被添加为头节点
【解决方案2】:

这行得通

class DoublyLinkedList <T> {

    DoublyLinkedListNode<T> head;

    public DoublyLinkedListNode<T> getHead() {
        return head;
    }

    public void setHead(DoublyLinkedListNode<T> head) {
        this.head = head;
    }

    public void addNode(DoublyLinkedListNode<T> node) {
        if (null == head) {
            head = new DoublyLinkedListNode<>(node.getData());
        } else {
            traverseAndAdd(node);
        }
    }

    private boolean traverseAndAdd(DoublyLinkedListNode<T> node) {

        boolean isAdded = false;

        for (DoublyLinkedListNode<T> it = head; it != null; it = it.getNext()) {
            if(null == it.getNext()) {
                it.setNext(node);
                node.setPrev(it);
                isAdded = true;
                break;
            }
        }

        return isAdded;
    }

    @Override
    public String toString() {

        StringBuffer sb = new StringBuffer();

        for (DoublyLinkedListNode<T> it = head; it != null; it = it.getNext()) {
            sb.append(it.getData() + "\n");
        }

        return sb.toString();

    }
}

class DoublyLinkedListNode <T> {

    T data;
    DoublyLinkedListNode<T> prev;
    DoublyLinkedListNode<T> next;

    public DoublyLinkedListNode(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public DoublyLinkedListNode<T> getPrev() {
        return prev;
    }

    public void setPrev(DoublyLinkedListNode<T> prev) {
        this.prev = prev;
    }

    public DoublyLinkedListNode<T> getNext() {
        return next;
    }

    public void setNext(DoublyLinkedListNode<T> next) {
        this.next = next;
    }
}

public class Main {

    public static void main(String []args) {
        DoublyLinkedList<Integer> mylist = new DoublyLinkedList<>();

        DoublyLinkedListNode<Integer> node1 = new DoublyLinkedListNode<>(10);
        DoublyLinkedListNode<Integer> node2 = new DoublyLinkedListNode<>(20);
        DoublyLinkedListNode<Integer> node3 = new DoublyLinkedListNode<>(30);
        DoublyLinkedListNode<Integer> node4 = new DoublyLinkedListNode<>(40);
        DoublyLinkedListNode<Integer> node5 = new DoublyLinkedListNode<>(50);
        DoublyLinkedListNode<Integer> node6 = new DoublyLinkedListNode<>(60);
        mylist.addNode(node1);
        mylist.addNode(node2);
        mylist.addNode(node3);
        mylist.addNode(node4);
        mylist.addNode(node5);
        mylist.addNode(node6);

        System.out.println(mylist.toString());
        System.out.println(mylist.toString());
    }
}

【讨论】:

  • 因为每次我添加一个节点 head 总是 null 并且它永远不会进入 addNode 方法的 else 部分 public void addNode(DoublyLinkedListNode node) { if(null == head) { head = new DoubleLinkedListNode(node.getData()); }else{ traverseAndAdd(node); } }
  • 一旦我退出方法 addNode 头被初始化回 null
猜你喜欢
  • 1970-01-01
  • 2021-11-18
  • 2011-06-03
  • 2018-03-14
  • 2012-05-10
  • 2014-07-01
  • 1970-01-01
  • 2015-05-16
相关资源
最近更新 更多