[我的心得]數據結構之雙鏈表

維基百科node

  • 雙向鏈表也叫雙鏈表,是鏈表的一種,它的每一個數據結點中都有兩個指針,分別指向直接後繼和直接前驅。因此,從雙向鏈表中的任意一個結點開始,均可以很方便地訪問它的前驅結點和後繼結點。通常咱們都構造雙向循環鏈表。

圖片描述


又上面可知,雙向鏈表與單鏈表的區別在於,雙向鏈表的每一個節點都有一個指向前一個的指針(previous)。
想了解單鏈表,能夠看看我上一遍寫的單鏈表git

1.先建立節點的類。github

class Node {
  constructor (element) {
    this.elememt = element;
    this.previous = null;  // 這個是指向前一個的指針。
    this.next = null;
  }
}

2.再建立雙向鏈表的類。算法

class DoubleLinkedList {
  constructor () {
    this.head = null;
    this.length = 0;
  }
}

接下來給雙向聯表添加一些方法(一下方法都是在雙向鏈表類裏面寫的)。segmentfault

  • Append
/**
   * 
   * @param element 用來實例節點的數據,什麼數據類型都行. 
   */
  append (element) {
    let node = new Node(element), current;

    if (!this.length) {                 // 長度爲0,則是新的鏈表。
      this.head = node;                 // 鏈表的頭指向新的node。
    } else {
      current = this.head;              // current得到指向第一個節點的指針。

      while (current.next) {           // 當前node.next存在。
        current = current.next;        // 若是當前節點(current)的next不爲null,那麼current.next這個指針就給了current。
      }                                // current的下一個爲null的時候,退出循環。
      current.next = node;             // current.next爲null退出循環(即已到了最後一個節點),那麼它的next爲node
      node.previous = current;         // 新加入的node的前一個就是current。
    }
    this.length++;                     // 長度加一,別忘咯。
    console.log('Append successfully!');
}
  • InsertNode
/**
   * @param element
   * @param {Number} position 要插入的某個位置. 
   */
  insertNode (element, position) {
    if (position >= 0 && position <= this.length) {
    
      let node = new Node(element),
        front,
        index = 0,
        current = this.head;

      if (!position) {                 // 若是插入的位置爲 0 。
        this.head = node;
        node.next = current;           // node的後一個是以前head所指的,便是current。
      } else {
      
        while (index++ < position) {
          front = current;             // 當前變爲前一個。
          current = current.next;      // 下一個就變爲當前
        }
        
        front.next = current.previous = node; // 前一個的next 和 當前的previous 是node。
        node.previous = front;         // 插入的node的前一個爲front。
        node.next = current;           // 插入的node的後一個是current。
      }
      
      this.length++;
      console.log('Insert successfully!');
    } else {
      throw new Error('插入的位置有誤啊!');
    }
}
  • RemoveNode
/**
   * @param {Number} position 
   */
  removeNode (position) {
    if (position > -1 && position < this.length) {
    
      let current = this.head, front, index = 0;

      if (!position) {                           // 位置爲 0 。
        this.head = current.next;
        current.next.previous = this.previous;
      } else {
      
        while (index++ < position) {
          front = current;
          current = current.next;
        }
        
        if (current.next) {                      // 這裏判斷當前node的下一個是否爲 null。(例如要刪除最後一個是node.next是null的)
          current.next.previous = front;         // 當前node的下一個的previous爲front。(有點繞口)
        }
        
        front.next = current.next;               // 前一個的下一個爲current的下一個。 (...繞口)
      }
      this.length--;
      console.log('Remove successfully!');
    } else {
      throw new Error('移除的位置有誤啊!');
    }
}
  • Print
print () {
    let arr = [this.head];
    let node = this.head;
    
    while (node.next) {
      node = node.next;
      arr.push(node);
    }
    
    arr.map( (x, index) => console.log(`第${index + 1}個節點是`, x));
}

圖片描述

附上我的源碼

循環鏈表 ----(維基百科)app

  • 循環鏈表是一種鏈式存儲結構,它的最後一個結點指向頭結點,造成一個環。所以,從循環鏈表中的任何一個結點出發都能找到任何其餘結點。循環鏈表的操做和單鏈表的操做基本一致,差異僅僅在於算法中的循環條件有所不一樣。

1.單向循環鏈表
圖片描述this

2.雙向循環鏈表
圖片描述spa

  • 單向循環鏈表是在單鏈表基礎上,將最後一個節點的next指針指向鏈表頭(head)
  • 雙向循環鏈表是在雙向鏈表基礎上,將最後一個節點的next指針指向鏈表頭(head)

就寫到這裏咯。你問我怎麼不實現循環鏈表?這個就...大家實現吧,程序猿嘛,要多動手,多動手。
謝謝你們。3d

相關文章
相關標籤/搜索