JS中數據結構之鏈表


1、鏈表的基本介紹

數組不總是組織數據的最佳數據結構,在很多編程語言中,數組的長度是固定的,所以當數組已被數據填滿時,再要加入新的元素就會非常困難。在數組中,添加和刪除元素也很麻煩,因為需要將數組中的其他元素向前或向后平移。

鏈表是由一組節點組成的集合。每個節點都使用一個對象的引用指向它的后繼。許多鏈表的實現都在鏈表最前面有一個特殊節點,叫做頭節點。如下圖:

2、鏈表的實現

2.1、基於對象的鏈表的實現

Node 類用來表示節點,包含兩個屬性:element 用來保存節點上的數據,next 用來保存指向下一個節點的鏈接。

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

LList 類提供了對鏈表進行操作的方法。該類的功能包括插入刪除節點、在列表中查找給定的值。

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

find() 方法遍歷鏈表,查找給定數據。如果找到數據,該方法就返回保存該數據的節點。如果查找成功,該方法返回包含該數據的節點;否則,返回 null。

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

insert() 方法在一個已知節點后面插入元素

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

display() 方法用來顯示鏈表中的元素

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

 findPrevious() 方法找到待刪除節點前面的節點。找到這個節點后,修改它的 next 屬性,使其不再指向待刪除節點,而是指向待刪除節點的下一個節點。

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

remove() 方法從鏈表中刪除節點。

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

 

2.2、雙向鏈表

給 Node 對象增加一個屬性,該屬性存儲指向前驅節點的鏈接,這使得鏈表從后向前遍歷變得簡單

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

insert() 方法

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

remove() 方法比單向鏈表的效率更高,因為不需要再查找前驅節點。

function remove(item) {
  var currNode = this.find(item);
  if (!(currNode.next == null)) {
    currNode.previous.next = currNode.next;
    currNode.next.previous = currNode.previous;
    currNode.next = null;
    currNode.previous = null;
  }else {
    currNode.previous.next = null;
    currNode.next = null;
    currNode.previous = null;
  }
}

findLast() 方法查找鏈表中的最后一個節點,避免了從前往后遍歷鏈表

function findLast() {
  var currNode = this.head;
  while (!(currNode.next == null)) {
    currNode = currNode.next;
  }
  return currNode;
}

dispReverse() 方法反序顯示雙向鏈表中的元素。

function dispReverse() {
  var currNode = this.head;
  currNode = this.findLast();
  while (!(currNode.previous == null)) {
    console.log(currNode.element);
    currNode = currNode.previous;
  }
}

 

2.3、循環鏈表

循環鏈表和單向鏈表相似,節點類型都是一樣的。唯一的區別是,在創建循環鏈表時,讓其頭節點的 next 屬性指向它本身,即鏈表的尾節點指向頭節點,形成了一個循環鏈表。如下圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM