用JavaScript實現基於對象的單項鍊表

用JavaScript實現基於對象的單項鍊表

單向鏈表介紹

何爲單向鏈表

單向鏈表圖示

與數組的索引: 值(可以直接在數組層面對值進行修改)不同,鏈表各個值的關係偏向去中心化。

見上圖,每個節點可分爲兩部分:1. 節點的值;2. 下一個節點的指向,即下一個節點是誰。例如:上圖鏈表中的第一個節點,它的值是milk,它的下一個節點是值爲Bread的節點。

單向鏈表優點

當我們需要組織數據時,數組不總是最佳的數據結構(對於大多數編程語言而言),緣於它有兩個顯著的缺點:1. 數組的長度是固定的,當數組已被數據填滿時,加入新數據會顯得很麻煩;2. 當我們插入、或刪除數組中的某個值時,需要把數組中的其它值向後、或向前移動,以反映數組被進行了增刪操作。

所以當我們需要頻繁的對數據進行增刪操作時,選擇數組不是那麼地明智,這時我們可以使用鏈表來實現對數據的增刪功能。鏈表的增刪會方便很多,當增加數據時,只需要更改它的節點指向和上一級節點的節點指向;當刪除數據時,只需把待刪除節點的節點指向賦給上一級節點即可,此時待刪除節點便在鏈表中消失了(因爲無法通過節點與節點的關係再找到它,便可視爲消失了)。

例如:如果我們在milk和bread中增加sandwich數據,只需把milk的節點指向改爲sandwich,把指向bread的節點指向賦給sandwich即可;當需要刪除sandwich時,只需把指向bread的節點指向賦給milk即可,此時sandwich便自動消失了。

構建鏈表

當我們需要組織某一類的數據時,只需先建一個相應的構造器(構造函數)即可,這個構造器應包含以下的屬性和方法:頭節點;增,刪,查等。

節點構造器

我們可以先做頭節點的構造器;

//我們可以把一個節點視爲一個盒子,這個盒子被分爲兩部分,一部分盛放的是該節點的值,另一部分盛放的則是指向下一個節點的節點指向。
function Node(element) {
  this.element = element;
  this.next = null;
}

鏈表構造器

某類數據的鏈表構造器

function LList() { //LList: linkedList鏈表
  //新建值爲head的節點(表頭),便可一生二二生三三生萬物了,下面的操作都要基於表頭。
  this.head = new Node("head");
  
  //查找方法,給find一個值,便可查到相應的節點
  this.find = find;
  
  //插入方法,可以實現在哪插入、插入什麼數據的功能
  this.insert = insert;
  
  //展示打印功能,傳入想要查詢的節點的元素,該節點便能被打印出來,包括的指向的下一節點
  this.display = display;

  //如果要刪除某一節點,則需要找到它的前一節點,修改它的節點指向
  this.findPrevious = findPrevious;
 
  //刪除方法,傳入想要刪除的元素,即可實現刪除功能
  this.remove = remove; 
}

find()方法

find()方法展示瞭如何在鏈表上進行移動。首先,新創一個節點,並將表頭賦給這個新創的節點。然後在鏈表上進行循環,如果如果當前節點的element屬性和我們要查找的值不一樣,就從當前節點移到下一節點,如果查找成功,返回包含該數據的節點,失敗,返回null

function find(item) {
  
  //將表頭賦給新創的節點
  var currNode = this.head;
  
  //循環,如果當前節點的值與我們想要查找的值不一樣,移動到下一節點。知道找到目標或移到null
  while (currNode.element !== item) {
    currNode = currNode.next;
  }
  
  //返回相應節點或null
  return currNode;
}

insert()方法

insert()實現插入功能,傳入新節點的值newElement和待插位置item,並修改新節點和待插位置的節點指向,完成插入。

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

display()

display()顯示鏈表中的元素

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

findPrevious()

findPrevious()查找到待刪除的前一節點

function findPrevious(item) {
  var currNode = this.head;
  while ((currNode.next !== null) && (currNode.next.element !== item)) {
    currNode = currNode;
  }
  return currNode;
}

remove()方法

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

完整代碼

function Node(element) {
  this.element = element;
  this.next = null;
}

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

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 currNode = this.find(item);
  newNode.next = currNode.next;
  currNode.next = newNode;
}

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

function findPrevious(item) {
  var currNode = this.head;
  while ((currNode.next.element !== item) && (currNode.next !== null)) {
    currNode = currNode.next;
  }
  return currNode;
}

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

測試

向鏈表中寫入數據

var cities = new LList();
cities.insert("beijing", "head");
cities.insert("shanghai", "beijing");
cities.insert("guangzhou", "shanghai");
cities.insert("shenzhen", "guangzhou");

展示鏈表

cities.display();

數據展示

刪除"shanghai"後,再次展示

cities.remove("shanghai");
cities.display();

刪除"shanghai"之後的鏈表

刪除成功!

Reference

Michael McMillan, (2014). Data Structures & Algorithms with JavaScript. Beijing: O’Reilly Media, Inc. and Posts & Telecom Press.

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