數據結構與算法之循環鏈表

  1. 循環鏈表的介紹
    在單向鏈表和雙向鏈表中,都採用null作爲鏈表的結束,然而,循環鏈表沒有結束標誌。
    注意 與單向鏈表不同,循環鏈表沒有next指針爲null的點,循環鏈表在某些情況下非常有用。 比如在進程的循環調度中。
  2. 循環鏈表的創建

public class Node<E> {

    // 節點對象 對象應該包含儲蓄的數據和指向下一個節點對象
    // 利用泛型 將儲存的數據類型交給使用者來選擇,大大提升靈活性
    // 儲存的數據
    private E data;
    // 下一個節點
    private Node<E> next;

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }

    public Node<E> getNext() {
        return next;
    }

    public void setNext(Node<E> next) {
        this.next = next;
    }

}

3.循環鏈表的插入


    // 在鏈表表尾增加鏈表節點
    public void add(E obj) {
        Node<E> node = new Node<>();
        node.setData(obj);
        // 如果鏈表爲空 則首尾節點都指向第一個節點
        if (headNode == null) {
            headNode = node;
            endNode = node;
            //循環鏈表的尾節點指向頭結點
            endNode.setNext(headNode);
        } else {
            // 不爲空 將尾節點指向新增節點
            endNode.setNext(node);
            //新增節點指向頭節點
            node.setNext(headNode);
            // 尾節點後移
            endNode = node;
        }
    }

    // 在指定中間位置增加節點
    public void add(int index, E element) {
        Node<E> node = new Node<>();
        node.setData(element);

        if (headNode == null) {
            throw new NullPointerException("空鏈表");
        }
        // 判斷位置是否超出界限
        else if ((index < 0) || (index > this.size())) {
            throw new ArrayIndexOutOfBoundsException("超出範圍");
        } else {
            // 首節點插入
            if (index == 0) {
                node.setNext(headNode);
                endNode.setNext(node);
                headNode = node;
            }
            // 尾節點插入
            else if (index == this.size()) {
                endNode.setNext(node);
                node.setNext(headNode);
                endNode = node;
            }
            // 中間插入
            else {
                Node<E> hnode = headNode;
                // 將首節點移動到插入節點的前一個節點
                for (int i = 1; i <= index - 1; i++) {
                    hnode = hnode.getNext();
                }
                node.setNext(hnode.getNext());
                hnode.setNext(node);
            }
        }
    }

4.循環鏈表的刪除


    // 移除此列表中指定位置上的元素
    public void remove(int index) {

        if (headNode == null) {
            throw new NullPointerException("空鏈表");
        } else if ((index < 0) || (index >= this.size())) {
            throw new ArrayIndexOutOfBoundsException("超出範圍");
        } else {
            // 保護頭結點
            Node<E> hnode = headNode;
            // 刪除首節點
            if (index == 0) {
                //更新首節點 
                headNode = headNode.getNext();
                //更新尾節點
                endNode.setNext(headNode);
                // System.out.println(index + "號:" + hnode.getData().toString()
                // + "移除成功");
            }
            // 刪除尾節點
            else if (index == (this.size() - 1)) {
                while (hnode.getNext() != endNode) {
                    hnode = hnode.getNext();
                }
                hnode.setNext(headNode);
                // System.out.println(index + "號:" + endNode.getData() + "
                // 移除成功");
                endNode = hnode;
            }
            // 刪除中間節點
            else {
                for (int i = 1; i < index; i++) {
                    hnode = hnode.getNext();
                }
                // E data = hnode.getNext().getData();
                hnode.setNext(hnode.getNext().getNext());
                // System.out.println(index + "號:" + data.toString() + " 移除成功");
            }
        }
    }

5.循環鏈表的其他操作

// 返回此列表中指定位置上的元素。
    public E get(int index) {
        if (headNode == null) {
            throw new NullPointerException("空鏈表");
        } else {
            // 遍歷不到尾節點
            for (Node<E> node = headNode; node.getNext() != headNode; node = node.getNext()) {
                if (index == 0) {
                    return node.getData();
                }
                index--;
            }
            // 尾節點單獨檢測 爲什麼是0因爲index多運行了一次
            if (index == 0) {
                return endNode.getData();
            } else
                throw new ArrayIndexOutOfBoundsException("超出範圍");
        }

    }

    // 返回此列表的元素數。
    public int size() {
        //判斷是否爲空
        if (headNode == null) {
            return 0;
        } else {
            Node<E> node = headNode;
            int count = 0;
            //循環鏈表沒有節點next爲空
            while (node.getNext() != headNode) {
                node = node.getNext();
                count++;
            }
            return count + 1;
        }
    }

    // 用指定的元素替代此列表中指定位置上的元素。
    public E set(int index, E element) {
        // 刪除指定位置的元素
        this.remove(index);
        // 插入指定位置元素
        this.add(index, element);
        return element;
    }

循環鏈表的基本操作就此結束

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章