鏈表是由一組節點組成的集合,每個節點使用一個對象的引用指向它的后繼,指向另一個節點的引用就是鏈。在 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 著