Java 如何修复自定义双链接列表上的无限循环?

Java 如何修复自定义双链接列表上的无限循环?,java,data-structures,linked-list,Java,Data Structures,Linked List,我已经创建了一个自定义LinkedList,我正在尝试一个基于值对其进行分区的方法。不需要维护顺序,因此我考虑在列表的开头添加小于x的值,在末尾添加等于或大于x的值 尽管如此,仍有一个无限循环作为node.next在检查时从不为null 代码如下: public class LinkedList<T extends Comparable<T>> { private int size = 0; private Node<T> head = nul

我已经创建了一个自定义LinkedList,我正在尝试一个基于值对其进行分区的方法。不需要维护顺序,因此我考虑在列表的开头添加小于x的值,在末尾添加等于或大于x的值

尽管如此,仍有一个无限循环作为node.next在检查时从不为null

代码如下:

public class LinkedList<T extends Comparable<T>> {
    private int size = 0;
    private Node<T> head = null;
    private Node<T> tail = null;

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    /**
     *
     * @param t the new element to be added at the end of the list
     *          NOTE: null items are not allowed
     *
     * @return true if added
     */
    public boolean add(T t) {

        if (t == null) {
            return false;
        }
        // if head is null add as head
        if (head == null) {
            head = new Node<>(t, null, null);
            tail = head;
        } else {
            Node<T> newTail = new Node<>(t, tail, null);
            tail.next = newTail;
            tail = newTail;
        }
        size++;
        return true;
    }

    void partition(T value) {
        Node<T> node = head;

        while (node != null) {
            Node<T> prev = node.previous;
            Node<T> next = node.next;

            if (node.data.compareTo(value) >= 1) {
                // should go to tail
                if (node != tail) {
                    prev.next = node.next;
                    next.previous = node.previous;

                    tail.next = node;
                    node.previous = tail;
                    node.next = null;
                    tail = node;
                }

            } else {
                // should go to head
                if (node != head) {
                    prev.next = node.next;
                    if (null != next) {
                        next.previous = node.previous;
                    }

                    head.previous = node;
                    node.next = head;
                    head = node;
                }
            }

            node = next;
        }

        head.previous = null;
        tail.next = null;
    }

    public T getFirst() {
        return head.data;
    }

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

    public T getLast() {
        return tail.data;
    }


    private static class Node<T extends Comparable<T>>  {
        T data;
        Node<T> previous;
        Node<T> next;

        Node(T data, Node<T> previous, Node<T> next) {
            this.data = data;
            this.previous = previous;
            this.next = next;
        }
    }

}
公共类链接列表{
私有整数大小=0;
私有节点头=null;
私有节点tail=null;
公共整数大小(){
返回大小;
}
公共布尔值为空(){
返回大小==0;
}
/**
*
*@param t要添加到列表末尾的新元素
*注意:不允许使用空项
*
*@如果添加,则返回true
*/
公共布尔加法(T){
如果(t==null){
返回false;
}
//如果head为空,则添加为head
if(head==null){
head=新节点(t,null,null);
尾=头;
}否则{
Node newTail=新节点(t,tail,null);
tail.next=newTail;
尾=新尾;
}
大小++;
返回true;
}
空隙分割(T值){
节点=头部;
while(节点!=null){
Node prev=Node.previous;
Node next=Node.next;
if(node.data.compareTo(value)>=1){
//我们应该走到尽头
如果(节点!=尾部){
prev.next=node.next;
next.previous=node.previous;
tail.next=节点;
node.previous=尾部;
node.next=null;
尾=节点;
}
}否则{
//应该去头部
如果(节点!=头部){
prev.next=node.next;
如果(空!=下一个){
next.previous=node.previous;
}
head.previous=节点;
node.next=头部;
头部=节点;
}
}
节点=下一个;
}
head.previous=null;
tail.next=null;
}
公共T getFirst(){
返回头数据;
}
公共节点getHead(){
回流头;
}
公共T getLast(){
返回tail.data;
}
私有静态类节点{
T数据;
节点前向;
节点下一步;
节点(T数据、上一个节点、下一个节点){
这个数据=数据;
this.previous=先前;
this.next=next;
}
}
}
要复制的测试用例:

import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Arrays;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;


public class LinkedListTest {

    private LinkedList<Integer> linkedList;

    @BeforeMethod
    public void setUp() {
        linkedList = new LinkedList<>();
    }

    @Test
    public void testPartition() {
        linkedList.add(0);
        linkedList.add(9);
        linkedList.add(2);
        linkedList.add(5);
        linkedList.add(4);
        linkedList.add(7);
        linkedList.add(1);

        int[] actual = new int[linkedList.size()];

        linkedList.partition(5);

        for (int i = 0; i < linkedList.size(); ++i) {
            actual[i] = linkedList.get(i);
        }

        System.out.println(Arrays.toString(actual));
    }

}
import org.testng.annotations.AfterMethod;
导入org.testng.annotations.BeforeMethod;
导入org.testng.annotations.Test;
导入java.util.array;
导入静态org.testng.Assert.assertEquals;
导入静态org.testng.Assert.assertTrue;
公共类LinkedListTest{
私有链接列表链接列表;
@预处理法
公共作废设置(){
linkedList=新建linkedList();
}
@试验
公共void testPartition(){
linkedList.add(0);
linkedList.add(9);
添加(2);
linkedList.add(5);
linkedList.add(4);
linkedList.add(7);
添加(1);
int[]实际值=新的int[linkedList.size()];
链接列表分区(5);
对于(int i=0;i
假设您的列表有两项:A->B以及A和B>值(因此“应该转到尾部”)。开始你的代码。节点A>值,因此A放在尾部。所以现在你的列表是B->A,B是“下一个”节点,A现在是尾部

循环的下一次迭代将查看节点B。节点B>值,因此将B放在尾部。现在您的列表是A->B,A是“下一个”节点,B现在是尾部。显然,这是一个无限循环

要本着编写此代码的精神解决此问题,请在开始循环之前执行以下操作:

last_node = tail;
现在,就在您拥有
node=next之前执行以下操作:

if(node == last_node) break;

在上面的示例中,
last\u node
指向B。循环处理A,然后B退出,因为B是
last\u node

请提供AMCVE@RC添加了相关的方法和一个简单的测试用例,希望能帮助人们重现这个问题方法,该方法转储列表中的所有元素并显示连接指向的位置。然后,您可以在循环的每次迭代结束时调用dump(),以便在出现问题时进行故障排除。虽然这在这种特殊情况下有效,但当所有元素都大于或小于传递的值时,代码将失败。我需要仔细考虑一下。无论如何,我会接受你的答案,因为它解决了无限循环的问题。