Реализация циклического связанного списка (Java)

структура данных

1. Введение в циклический связанный список

Круговой связанный список на самом деле является специальнымЕдиный список.

Хвостовой узел односвязного списка указывает на NULL, а хвостовой узел кругового связанного списка указывает на головной узел, образуя кольцо.

2. Вставьте

Вставка кругового связанного списка заключается в изменении указателя соседнего узла. Временная сложность O(1).

Отличие от односвязного списка заключается в том, что при вставке в конец кругового связанного списка вновь вставленный узел должен указывать на головной узел.

как показано на рисунке:

Переведено в код:

  /**
     * 尾部插入
     *
     * @param newNode
     */
    public void insert(Node newNode) {
        if (head == null) {
            // 循环链表为空时,head 指向新的节点
            head = newNode;
        } else {
            Node temp = head;
            // 找到循环链表最后一个节点
            while (temp.next != head) {
                temp = temp.next;
            }
            // 插入新的节点
            temp.next = newNode;
        }
        // 循环链表新的结点指向 NULL
        newNode.next = head;
        // 循环链表长度加 1
        length++;
    }

3. Удалить

Удаление циклического связанного списка такое же, как вставка, и удаление циклического связанного списка может быть завершено путем изменения направления указателя, а временная сложность составляет O (1).

как показано на рисунке:

Переводится в код как:

 /**
     * 删除数据域为指定值的元素
     *
     * @param e
     */
    public void del(int e) {
        Node temp = head;
        while (length >= 0) {
            // 找到数据域为 e 的结点
            if (temp.data == e) {
                if (temp.next == head) {
                    // 第一个节点
                    head = null;
                } else {
                    // 最后一个节点
                    temp.next = temp.next.next;
                }
                // 循环链表长度减 1
                length--;
                return;
            }
            // temp 后移          
            temp = temp.next;
        }
    }

4. Полный код

Node.java

/**
 * @author liyanan
 * @date 2020/1/2 13:44
 */
/**
 * 模拟结点
 */
public class Node {
    /**
     * 存储数据
     */
    public int data;
    /**
     * 指向下一个节点
     */
    public Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }
}

CircleLinkedList.java

/**
 * 循环链表的实现(特殊的单链表)
 *
 * @author liyanan
 * @date 2020/1/2 13:16
 */
public class CircleLinkedList {
    /**
     * 指向循环链表的第一个结点
     */
    private Node head;
    /**
     * 循环链表的长度
     */
    private int length;


    public CircleLinkedList() {
        head = null;
        length = 0;
    }

    public Node getHead() {
        return head;
    }

    public int getLength() {
        return length;
    }

    /**
     * 尾部插入
     *
     * @param newNode
     */
    public void insert(Node newNode) {
        if (head == null) {
            // 循环链表为空时,head 指向新的节点
            head = newNode;
        } else {
            Node temp = head;
            // 找到循环链表最后一个节点
            while (temp.next != head) {
                temp = temp.next;
            }
            // 插入新的节点
            temp.next = newNode;
        }
        // 循环链表新的结点指向 NULL
        newNode.next = head;
        // 循环链表长度加 1
        length++;
    }

    /**
     * 将新的结点插入到指定结点后
     *
     * @param preNode 指定节点
     * @param newNode 新的节点
     */
    public void insert(Node preNode, Node newNode) {
        newNode.next = preNode.next;
        preNode.next = newNode;
        length++;
    }

    /**
     * 删除数据域为指定值的元素
     *
     * @param e
     */
    public void del(int e) {
        Node temp = head;
        while (length >= 0) {
            // 找到数据域为 e 的结点
            if (temp.data == e) {
                if (temp.next == head) {
                    // 第一个节点
                    head = null;
                } else {
                    // 最后一个节点
                    temp.next = temp.next.next;
                }
                // 循环链表长度减 1
                length--;
                return;
            }
            // 找到下一个结点
            temp = temp.next;
        }
    }
    
    /**
     * 随机访问第 k 个结点
     *
     * @param k
     * @return
     */
    public Node find(int k) {
        if (k <= 0) {
            throw new RuntimeException("输入的参数 k 必须大于 0");
        }
        int cnt = 1;
        Node temp = head;
        // 找到第 k 个元素
        while (cnt != k) {
            temp = temp.next;
            cnt++;
        }
        return temp;
    }

    /**
     * 打印循环链表所有有效节点
     *
     * @return
     */
    public String printCircleLinkedList() {
        StringBuilder sb = new StringBuilder();
        int cnt = 0;
        Node temp = head;
        while (head != null && cnt < getLength()) {
            sb.append(temp.data);
            sb.append(" -> ");
            temp = temp.next;
            cnt++;
        }
        sb.append(", length = ");
        sb.append(length);
        return sb.toString();
    }
}