如何在自定义双链表上修复无限循环?

时间:2016-05-06 20:37:20

标签: java data-structures linked-list

我已经创建了一个自定义LinkedList,我正在尝试使用一种基于值对其进行分区的方法。没有必要维护顺序,所以我想到将小于x的值添加到列表的头部并且值等于或大于尾部。

尽管如此,发生了无限循环,因为当检查发生时,node.next永远不会为空。

以下是代码:

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;
        }
    }

}

要重现的测试用例:

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));
    }

}

1 个答案:

答案 0 :(得分:1)

我们说你的清单有两个项目:A-&gt; B和A和B&gt;价值(所以&#34;应该转到尾巴&#34;)。开始你的代码。节点A&gt;价值,所以A放在尾巴上。所以现在你的名单是B-&gt; A和B是&#39; next&#39;节点和A现在是尾巴。

循环的下一次迭代查看节点B.节点B&gt;价值,所以B放在尾巴上。现在你的列表是A-> B,A是&#39; next&#39;节点和B现在是尾巴。显然这是一个无限循环。

为了解释这个代码的编写方式,在开始循环之前,请执行以下操作:

last_node = tail;

现在,就在您node = next;执行此操作之前:

if(node == last_node) break;

在上面的示例中,last_node指向B.循环处理A然后B退出,因为B是last_node