当前位置: 首页 > 知识库问答 >
问题:

Java:当我用头伪节点插入到我的循环双链表中时,我的伪节点会被打乱。为什么?

郁博学
2023-03-14

我写了一个循环双链接列表,前面有一个虚拟节点。在初始化DLL类的过程中,我创建了虚拟节点。当我在jGrasp中使用调试器并使用可视化工具时,在插入几个数字后,我的虚拟节点会四处移动,不会停留在最前面。我不明白我是如何修改我的链表的。作为前言,我的节点类有一个整数val和两个名为prev和next的指针。我注意到的一件事是,在赋值语句curr=dummy之后,dummy节点被洗牌到上一次插入的curr。

public class DLL {

    Node curr;
    Node help;
    Node dummy = new Node(null, null, -1);

    public DLL() {
        this.curr = curr;
        this.help = help;
        dummy.next = dummy;
        dummy.prev = dummy;
    }

    public boolean isEmpty() {
        if (dummy.next == dummy && dummy.prev == dummy) {
            return true;
        }
        return false;
    }

    public void push(int elem) {
        if (isEmpty()) {
            Node sec = new Node(dummy, dummy, elem);
            dummy.next = sec;
            dummy.prev = sec;
        } else {
            curr = dummy;
            while (curr.next != dummy) {
                curr = curr.next;
            }
            Node n = new Node(curr, dummy, elem);
            curr.next = n;
            dummy.prev = n;
        }
    }

    public void reverse() {
        curr = dummy;
        help = dummy;
        while (curr.next != help || curr != help) {
            curr = curr.next; // increment curr
            help = help.prev; // decrement help    
            swap(curr, help); // swap
        }
    }
    public void swap(Node curr, Node help) {
        int temp = curr.val;
        curr.val = help.val;
        help.val = temp;
    }
    public boolean contains(int elem) {
        curr = dummy.next;
        while (curr != dummy && elem != curr.val) {
            curr = curr.next;
            if (curr == dummy) {
                return false;
            }
        }

        return true;
    }
}

以下是我使用的小测试类:

public class testDLL {
    public static void main(String[] args) {
        DLL dlink = new DLL();
        dlink.push(4);
        dlink.push(6);
        dlink.push(3);
        dlink.push(2);
        assert dlink.contains(4) == true;
        assert dlink.contains(6) == true;
        assert dlink.contains(3) == true;
        assert dlink.contains(2) == true;
        dlink.reverse();

    }
}

共有2个答案

屠和洽
2023-03-14

我相信我已经解决了这个问题。我没有设置curr=dummy,而是设置curr=head。在DLL顶部初始化dummy之后,我立即设置head=dummy。这样我就不会在前进中改变头部。

齐昊焱
2023-03-14

欢迎来到SO。我将建议你如何自己解决问题,而不是为你找出问题所在。

您的测试试图一次测试太多。为了让您的测试工作,所有的方法都需要工作。更好的是(尽可能地)孤立地测试每个方法,然后构建以测试更复杂的场景。

所以先试着让这个测试起作用:

DLL list = new DLL();
assertTrue(list.isEmpty());

然后呢

DLL list = new DLL();
list.push(5);
assertTrue(list.contains(5));

很快,你就会发现你需要一种方法来获取不同格式的列表,以便进行测试。这很典型。

DLL list = new DLL();
list.push(5);
list.push(7);
list.push(5);
assertEquals(list.asList(), List.of(5, 7, 5));

DLL list = new DLL();
list.push(5);
list.push(7);
list.reverse();
assertEquals(list.asList(), List.of(7, 5));

等等

这样,在继续之前,您可以检查每个方法是否适用于基本值。

现在有几个设计要点:使用虚拟节点存储头部和尾部是不寻常的。很容易搞乱价值观(就像你所做的那样)。更好的方法是将头部和尾部存储为单独的变量,如果列表为空并指向单个项目的同一个节点,则这些变量为null(或者更好的方法是可选。empty)。

 类似资料:
  • 我尝试实现循环链表的insert方法。我想我取得了一些成功。 问题:当我显示列表时。display方法将循环,因为链接的每个next变量都链接到一个非Null节点对象。所以head永远不会是空对象。根据我对单链表的回忆,head总是指向列表中的第一个节点或其中包含数据的第一个节点。 我对循环链表的概念理解:根据我的理解,循环链表有点像一个单链表,但有一点小的变化:尾部对象的下一个变量指向头部。 来

  • 输出 谁能告诉我这里发生了什么?有什么不同?

  • 我理解得对吗?(从虚拟节点开始) dummy->a->b->c->d->dummy(环绕到dummy节点) 因此,如果我想删除第一个实际的数据段(A),我需要将它分配给一个临时变量。所以Node first=head.next。然后我需要有一个虚拟的头部引用“B”,所以我需要做head.next=first.next。这就是所有需要做的吗? 在从列表中删除任何节点N的情况下(假设它在列表中),这是

  • 我有一个双链接列表,看起来像: 当我使用迭代器和下面的代码遍历列表时,输出会精确打印上面写的内容。 但是,我希望在遍历列表时跳过空节点,以便它只打印: 我无法让我的代码做到这一点。这是我迄今为止所想出的。 问题是我得到了一个NoTouchElementException错误,但我不知道如何修复它。我猜是因为当我到达第二个空虚拟节点时,我试图跳过它,但没有其他节点可以跳到。 我的问题是,如何更改代码

  • 我正在尝试创建一个函数,用于在双链接列表的末尾添加。我无法精确指出为什么它没有打印出任何内容。 当我构建程序时,没有出现错误。 我正在确定。新建节点首先检查头部是否有任何值 在上一个当前指针之后创建 我将前一个节点连接到新节点,新节点指向前一个节点,而新节点指向nullptr作为下一个节点。

  • 问题内容: 我想打印根节点的子元素。这是我的XML文件。 根据我的理解,根节点是“公司”,其子节点必须是“职员”和“职员”(因为存在“职员”节点2次)。但是,当我尝试通过我的Java代码获取它们时,我得到了5个子节点。3个额外的文本节点从哪里来? Java代码: 输出: 为什么三个文本节点要过来? 问题答案: 为什么三个文本节点要过来? 它们是子 元素 之间的空白。如果只需要子元素,则应忽略其他类