java-双向链表逻辑

Posted

技术标签:

【中文标题】java-双向链表逻辑【英文标题】:java-Doubly Linked List logic 【发布时间】:2015-08-05 08:40:57 【问题描述】:

我正在尝试了解双向链表的 java 实现。我有以下代码:

public class DLLNode
    //define variables
    public int info;
    public DLLNode next;
    public DLLNode prev;


    //Passing constructors
    public DLLNode(int i)
        info = i;
        next = prev = null;
    

    public DLLNode(int i, DLLNode n, DLLNode p)
        info = i;
        next = n;
        prev = p;
    

还有以下内容:

public class DLL 
    DLLNode head;
    DLLNode tail;

    public DLL()
        head = tail = null;
    

    //Check whether list is empty or not
    public boolean isEmpty()
        return head == null;
    

//Insert element to head
    public void insertHead(int n)
        if(isEmpty())
            head = tail = new DLLNode(n);
        
        else
            head = new DLLNode(n, null, head);
            head.next.prev = head;
        
    

为清楚起见,此处仅显示 insertHead() 方法。

现在我明白了,如果有人在 main 方法中运行 insertHead(10),如果列表为空;形成一个新对象,并且头尾引用变量都指向该对象。

我不明白的是如果列表不为空;这段代码非常混乱。

head = new DLLNode(n, null, head);
head.next.prev = head; //really confusing, what does this mean??

1)我的理解是n=10,null和head被传递给构造函数:public DLLNode(int i,DLLNode n,DLLNode p)。然后赋值info=10,next=null和prev=head发生。一个问题是,如果列表中至少有一个项目可用,并且我将另一个项目添加到 HEAD 位置,“next”不应该指向前一个头,而“prev”指向 null?可能是代码错误??

2)代码是什么

head.next.prev = head;

是什么意思??为什么有必要?我真的不明白这个逻辑......:(

任何帮助将不胜感激..

【问题讨论】:

看来你是对的,应该是new DLLNode(n, head, null)。你试过运行它吗? 它确实可以编译,但逻辑与使用的方法名称混淆。那/这让我很担心,我害怕我错过了一些微不足道的事情。 编译,是的。运行 - 不超过一个元素。这种东西是试验的好地方。在调试器中使用它,您会对它是否是好代码更有信心。 我会这样做的。感谢您的快速回复 @maraca - 因为您在 second 参数中传递 null 并在 third 参数中传递 head。第二个参数去next——所以next变成null,第三个参数去prev,会变成老头。由于next 为空,head.next.prev 将抛出 NPE。 【参考方案1】:

这个实现是错误的。如果多次调用insertHead 会抛出NullPointerException

 head = new DLLNode(n, null, head);
 head.next.prev = head;  // head.next is null because of the above call

相反,插入的实现应该是:

public void insertHead(int n) 
    if (isEmpty()) 
        head = tail = new DLLNode(n);
     else 
        head = new DLLNode(n, head, null);
        head.next.prev = head;
    

在头部插入节点是一个两步操作:

    创建节点,将其 next 指针设置为指向当前头并将其分配为列表的新头。 将旧磁头的previous指针设置为新磁头。这就是head.next.prev = head 声明的作用。

【讨论】:

【参考方案2】:

是的,你是对的,但是代码完全按照你说的做(只是一个错误),也许如果我们使用括号它会变得更清晰:

(head.next).prev = head;

我们将刚刚创建的节点分配给下一个节点。或者换句话说:我们将旧头的 prev 引用更新为新头,这是必要的,因为

head = new DLLNode(n, null, head);

创建一个新的head,previous指向null,next是旧的head,但是旧head的previous的引用仍然是null

您在构造函数中的元素顺序错误(或在创建新头部的调用中)。

public DLLNode(int i, DLLNode p, DLLNode n) 

而且它有效。

【讨论】:

以上是关于java-双向链表逻辑的主要内容,如果未能解决你的问题,请参考以下文章

Java-链表(单向链表双向链表)

JAVA数据结构--LinkedList双向链表

03-java实现双向链表

双向链表的原理与实现

双向链表

线性链表的双向链表——java实现