1. 程式人生 > >資料結構與演算法(五)-線性表之雙向連結串列與雙向迴圈連結串列

資料結構與演算法(五)-線性表之雙向連結串列與雙向迴圈連結串列

前言:前面介紹了迴圈連結串列,雖然迴圈連結串列可以解決單鏈表每次遍歷只能從頭結點開始,但是對於查詢某一節點的上一節點,還是頗為複雜繁瑣,所以可以在結點中加入前一個節點的引用,即雙向連結串列

一、簡介

  雙向連結串列:在連結串列中,每一個節點都有對上一個節點和下一個節點的引用或指標,即從一個節點出發可以有兩條路可選擇。   雙向連結串列也叫雙鏈表,是連結串列的一種,它的每個資料結點中都有兩個指標或引用,分別指向直接後繼和直接前驅。所以,從雙向連結串列中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。一般我們都構造雙向迴圈連結串列。   特性:
  • 遍歷可逆性:可以反向遍歷;
  • 相比於單鏈表,迴圈單鏈表無論是插入還是遍歷,更便利,更快捷;
  • 雙向連結串列可以有效的提高演算法的時間效能,說白了就是用空間換時間;

二、雙向連結串列實現

  1、建立節點類Node,其中有三個屬性pre、object、next,pre為上一個節點的引用,也叫作前驅節點,object儲存資料,next為下一個節點的引用,也叫作後繼節點
public class BothwayLoopChain<T> {

    //頭結點直接引用
    private Node<T> head;

    //鏈長度
    private Integer size;

    
//初始化 BothwayLoopChain() { head = new Node<T>(); head.setNext(null); size = 0; } class Node<T> { private Node<T> pre; private Object object; private Node<T> next; public Node<T> getPre() {
return pre; } public void setPre(Node<T> pre) { this.pre = pre; } public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } public Node<T> getNext() { return next; } public void setNext(Node<T> next) { this.next = next; } } }
BothwayLoopChain.java   2、獲取位置的結點:
    public T get(Integer index) throws Exception {
        return (T) getNode(index).getObject();
    }

    private Node<T> getNode(Integer index) throws Exception {
        if (index > size || index < 0) {
            throw new Exception("index outof length");
        }
        Node<T> p = head;
        for (int i = 0; i < index; i++) {
            p = p.next;
        }
        return p;
    }
  3、插入節點:
    //在尾節點後插入節點
    public void add(T t) throws Exception {
        this.add(t,size);
    }

    //在index位置後插入一個節點
    public void add(T t, Integer index) throws Exception {
        //建立新節點
        Node<T> p = new Node<>();
        p.setObject(t);
        //獲取該位置的節點
        Node<T> s = getNode(index);
        p.setPre(s);
        if (s.getNext() != null) {
            //將本節點的next節點放入新節點的next節點
            p.setNext(s.getNext());
            s.getNext().setPre(p);
        } else {
            p.setNext(null);
        }
        size++;
    }
  4、移除節點:
    //移除節點並返回
    public Node<T> remove(Integer index) throws Exception {
        //獲取該位置的節點
        Node<T> s = getNode(index);
        //獲取該位置節點的下一個節點
        Node<T> next = s.getNext();
        //將本節點的pre節點的next節點設定為next
        s.getPre().setNext(next);
        next.setPre(s.getPre());
        return s;
    }
  至此,雙向連結串列的基本實現已完成,其實它就是用空間換時間來提高效能的;   之前瞭解了單鏈表的迴圈結構即單向迴圈連結串列,舉一反三,雙向連結串列也有迴圈結構,即雙向迴圈連結串列;

三、雙向連結串列擴充套件—雙向迴圈連結串列

在雙向連結串列的基礎上進行改造:
  • 尾節點的next指向頭結點;
  • 頭結點的pre指向尾節點;
     除了插入方法,其他方法可保持不變:
    //在index位置後插入一個節點
    public void add(T t, Integer index) throws Exception {
        //建立新節點
        Node<T> p = new Node<>();
        p.setObject(t);
        //獲取該位置的節點
        Node<T> s = getNode(index);
        p.setPre(s);
        //將本節點的next節點放入新節點的next節點
        p.setNext(s.getNext());
        s.getNext().setPre(p);
        size++;
    }

 本系列參考書籍:

  《寫給大家看的演算法書》

  《圖靈程式設計叢書 演算法 第4版》