javascript中的鏈表結構


1.定義

  很多編程語言中數組的長度是固定的,就是定義數組的時候需要定義數組的長度,所以當數組已經被數據填滿的時候,需要再加入新的元素就很困難。只能說在部分變成語言中會有這種情況,在javascript中和php中數組的長度是可以任意增加的。在數組中添加和刪除元素也是比較麻煩,因為要將數組中其他元素向前或者向后平移,這個在javascript中也不是問題,javascript中有一個很方便的方法splice()方法很方便的就可以添加或刪除元素。

  但是凡是都是相對的,javascript中的數組也有自己的問題,他們被是成了對象,與其他語言(比如c++和java)相比它的效率很低。

  如果在實際的使用中發現數組的效率很慢,就可以考慮使用鏈表來代替。數組還有個優勢是可以根據鍵值很方便的訪問數組的值,除此之外,鏈表在任何場合都可以代替數組。如果需要隨機地訪問元素,數組仍然是更好的選擇。

  鏈表是由一組節點組成的集合。每一個節點都使用一個對象的引用指向它的后續借點。指向另外一個借點的引用叫做鏈。

  數組元素靠它們的位置進行引用,鏈表元素則是靠相互之間的關系進行引用。在數組中會說這個元素是數組中的第幾個元素,但是在鏈表中就說這個元素是某個元素的后面一個元素。遍歷鏈表就是跟着鏈表從鏈表的頭元素(head)一直走到尾元素(但是不包含鏈表的頭借點,頭通常用來作為鏈表的接入點)。還有一個問題,鏈表的尾元素指向一個null節點。如下圖1

圖1

  許多鏈表的實現都在鏈表前面有一個特殊的節點,叫做頭節點。最后一個節點指向null,所有最后再加上一個null節點。如下圖2

圖2

  在鏈表中插入一個節點的效率很高。向鏈表中插入一個節點,需要修改它前面的節點,使其指向新加入的節點,而新加入的節點則指向前面指向的節點。如下圖展示的是在eggs后面加上cookies節點。如下圖3.

圖3

   從鏈表中刪除一個節點也很簡單,將待刪除的元素的前驅節點指向待刪除的后續節點,同時將待刪除元素指向null來釋放。下圖是一個巧合刪除是的null元素前面的一個元素。如下圖4

圖4

2.代碼實現

  在下面的鏈表實現中有兩個類。node類用來標識節點,LinkedList類提供插入節點,刪除節點,顯示鏈表節點元素的方法,以及一些其他的輔助方法。

  Node類包含兩個屬性,element用來保存節點上的數據,next用來保存指向下一個節點的鏈接。我們使用一個構造函數來創建節點,改構造函數設置了這兩個屬性的值。如下:

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

  LinkedList類提供了對鏈表進行操作的方法,該類的功能包含插入節點,在鏈表中查找給定的節點。該類也有一個構造函數,鏈表只有一個屬性,那就是使用一個node對象來保存該鏈表的頭結點,代碼如下:

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

  head節點的next屬性被初始華為null,當有新元素插入時,next會指向新的元素。

  插入節點的方法是insert,該方法向鏈表中插入新節點的時候,需要明確指出在那個節點的前面或者后面插入。這里先討論在一個已知節點的后面插入元素。在元素后面插入元素的時候不,需要先找到“后面”的節點。為此創建一個輔助方法find(),該方法遍歷鏈表,查找指定的數據,如果找到該數據,就返回保存該數據的節點,find()方法的實現的代碼如下:

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

  find()方法演示了如何在鏈表上移動。首先創建一個新節點,並將鏈表的頭節點賦給這個新創建的節點。然后再鏈表上進行循環,如果當前節點的element屬性和我們要找的信息不符合,就從當前節點移動到下一個節點。如果查找成功個,該方法返回包含該數據的節點,否則返回null。

  一旦找到“后面”的節點,就可以將新節點插入鏈表了。首先,將新節點的next屬性設置為“后面”節點對應的值,然后設置“后面”節點的next屬性指向新的節點,insert()定義如下:

//插入一個元素
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)){
        document.write(currNode.next.element + ' ');
        currNode = currNode.next;
    }
}

  這個方法首先將鏈表的頭賦給一個變量,然后循環遍歷鏈表,當前節點的next屬性為null的時候循環結束。為了只顯示包含數據的節點,我們使用currNode.next.element表達式來訪問節點中的數據。

  最后我們用下面的代碼來測試鏈表。在鏈表中保存幾個美國城市"Conway","Russellville","Alma"並將他們打印出來,完整代碼如下:

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 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)){
        document.write(currNode.next.element + ' ');
        currNode = currNode.next;
    }
}


//測試程序
var cities = new LList();
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.insert("Alma", "Russellville");
cities.display();

最后輸出的結果如下:

 


免責聲明!

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



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