數據結構之鏈表

鏈表是由一組節點組成的集合,每個節點使用一個對象的引用指向它的后繼,指向另一個節點的引用就是鏈。在 JavaScript 中,數組也可以存儲元素,但是數組說到底也是一個對象,與其他語言相比效率比較低,因此出現了鏈表,它可以更方便地代替數組來實現同樣的數據存儲與移動效果。

定義鏈表

為了更形象地表示鏈表,我從網上找了一張表示圖,如下


圖片來自網絡

每個鏈表都有一個頭結點,頭結點通常作為鏈表的接入點,它不參與鏈表的遍歷,同樣還會有一個尾元素,指向一個 null 結點。在 JavaScript 中,實現一個基于對象的鏈表,使用兩個類,一個類用來表示所有的結點,另一個類用來表示一些鏈表的基本方法。

Node 類

function Node(element) {
  this.element = element;   // 保存節點上的數據
  this,next = null;      // 保存指向下一個節點的鏈接
}

LinkedList 類

function LList() {
  this.head = new Node("head");
  this.find = find;
  this.insert = insert;
  this.remove = remove;
  this.display = display;
}

實現插入節點

插入一個節點,首先要明確是在某個節點的前面或后面插入,假設在一個已知節點后面插入元素,則需要先找到該節點“后面”的節點,然后將新節點的 next 屬性設置為“后面”節點的 next 屬性對應的值,然后設置“后面” 的節點的 next 屬性指向新節點。

// 定義一個 find 來找到 “后面” 的節點
function find(item) {
  var currNode = this.head;
  while(currNode.element != item) {
    currNode = currNode.next;
  }
  return currNode;
}

function insert(newElement,item) {
  var newNode = new Node(newElement);
  var current = this.find(item);
  newNode.next = current.next;
  current.next = newNode;
}

現在插入新節點的方法已經完成,我們緊接著定義一個方法用于展示鏈表中的元素

function display() {
  var currNode = this.head;
  while(!(currNode.next ==  null)) {
    console.log(currNode.next.element);
    currNode = currNode.next;
  }
}

刪除節點

刪除鏈表中的一個元素,我們首先要找到該元素所在的節點,然后找到它前面的節點,使其的 next 屬性指向待刪除節點的下一個節點,這樣就可以把節點 remove 掉。

// 定義 findPrevious 方法尋找前面節點
function findPrevious(item){
  var currNode = this,head;
  while(!(currNode.next == null) && (currNode.next.element != item)){
    currNode = currNode.next;
  }  
  return currNode;
}

function remove(item) {
  var prevNode = this.findPrevious(item);
  if(!(prevNode.next == null)) {
    prevNode.next = prevNode.next.next;
  }
}

這里的prevNode.next = prevNode.next.next;就是使前面的節點直接指向待刪除節點后面的節點。

完整代碼

最后放上完整的代碼,包含 Node 類、LList 類和測試代碼;

function Node(element) {
  this.element = element;   
  this,next = null;      
}
function LList() {
  this.head = new Node("head");
  this.find = find;
  this.insert = insert;
  this.remove = remove;
  this.display = display;
}
function remove(item) {
  var prevNode = this.findPrevious(item);
  if(!(prevNode.next == null)) {
    prevNode.next = prevNode.next.next;
  }
}
function findPrevious(item){
  var currNode = this.head;
  while(!(currNode.next == null) && (currNode.next.element != item)){
    currNode = currNode.next;
  }  
  return currNode;
}
function display() {
  var currNode = this.head;
  while(!(currNode.next ==  null)) {
    console.log(currNode.next.element);
    currNode = currNode.next;
  }
}
function find(item) {
  var currNode = this.head;
  while(currNode.element != item) {
    currNode = currNode.next;
  }
  return currNode;
}
function insert(newElement,item) {
  var newNode = new Node(newElement);
  var current = this.find(item);
  newNode.next = current.next;
  current.next = newNode;
}

var city = new LList();
city.insert("Guangzhou","head");
city.insert("Shenzhen","Guangzhou");
city.insert("Shantou","Shenzhen");
city.insert("Zhuhai","Shantou");
city.display();
city.remove("Shenzhen");
city.display();

參考資料:Data Structure and Algorithms Using JavaScript, Michael McMillan 著

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一些概念 數據結構就是研究數據的邏輯結構和物理結構以及它們之間相互關系,并對這種結構定義相應的運算,而且確保經過這...
    Winterfell_Z閱讀 5,900評論 0 13
  • 鏈表是線性表的一種。線性表是最基本、最簡單、也是最常用的一種數據結構。 線性表中數據元素之間的關系是一對一的關系,...
    騎摩托馬斯閱讀 666評論 0 3
  • 順序表結構的存儲方式非常容易理解,操作也十分方便,但是順序結構有如下缺點: 1.在插入或刪除時,往往需要移動大量數...
    雨飛飛雨閱讀 566評論 0 2
  • 有個人從小就天資聰穎,展露出不同于常人的智慧,從小到大成績也是極為突出。而后找工作也是步步為營,終于在一個...
    oilyne閱讀 218評論 0 0
  • 榆錢落,綠起紅散留殘萼。春短情長徒悵惘,閑愁似水長。 無聊生腳翻心墻,也學孫猴樹上。本想與天近兩丈,哪知天高無望。
    f48eb16762bf閱讀 349評論 1 2