前端必備數據結構——鏈表

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰算法

鏈表的優點

鏈表相對於數組的優勢在於:數組

  • 內存空間不是必須連續的,能夠充分利用計算機的內存,實現靈活的內存動態管理。
  • 鏈表不須要再建立的時候就肯定大小,而且它的大小能夠無限的延伸下去。
  • 鏈表在插入和刪除數據時,時間複雜度(即執行算法所須要的計算工做量)能夠達到O(1),相對數組效率高許多。

鏈表相對於數組的缺點在於:瀏覽器

  • 鏈表訪問任何一個位置的元素時,都須要從頭開始訪問
  • 沒法像數組同樣經過下標值訪問元素,須要從頭開始訪問,直到找到對應的元素

封裝鏈表

鏈表的每一個元素由一個存儲元素自己的節點和一個指向下一個元素的引用組成。也就是說每個節點本身有一個data,而且有一個指向下一個節點的指針next,next的指向默認爲null。markdown

function LinkList() {
    function Node(data) {
        this.data = data;
        this.next = null;
    }
    this.head = null;
    this.length = 0;    // 記錄鏈表節點的個數
}
複製代碼

鏈表的常見操做

  • append(element):向列表尾部添加一個新的元素
  • insert(position, element):向列表的某個位置插入一個新的元素
  • get(position):獲取對應位置的元素
  • indexOf(element):返回元素在列表中的索引。若是沒有該元素則返回-1
  • update(position, data):修改某個位置的元素的data值
  • removeAt(position):從列表的某個位置移除一個元素
  • remove(data):從列表中移除一個元素
  • isEmpty():若是鏈表中沒有元素,返回true。不然返回false
  • size():返回鏈表中包含的元素個數,和數組的length屬性相似
  • toString():鏈表中元素是Node類,須要重寫toString方法,方便輸出打印元素的值。

1. append(data)方法

若是添加的是第一個節點的話,須要多作一個步驟——把head指針指向第一個節點。若是添加的不是第一個節點的話,就要把最後一個節點的指針指向新建立的節點。app

查找方法:從this.head開始查找,若是當前指針指向的下一個current.next不爲空,將下一個節點的指針current.next賦值給當前指針current;直到current.next爲空,那麼這個指針所在的節點就是鏈表中的最後一個節點,將這個指向空的指針指向新建立的節點便可。post

LinkList.prototype.append = function (data) {
    var newNode = new Node(data);
    if (this.length == 0) {
        this.head = newNode;
    } else {
        var current = this.head;
        while (current.next) {
            current = current.next;
        }
        current.next = newNode;
    }
    this.length += 1;
}
複製代碼

2. insert(position, data)方法

在某個位置中插入一個元素。我在這裏的設置,傳入的position不能小於0,所以小於0時return false,並且插入的位置也不可以大於此時鏈表的長度,在這種狀況下也return false。接下來,插入元素存在兩種狀況:this

第一種:將元素插到第一個節點,即position的值爲0,此時要修改建立節點的指針指向,應該指向原來this.head指向的元素,再讓this.head指向這個新建立的元素,便可完成插入。spa

第二種,將元素插到中間或者末尾,即0 < position < this.length,先找到要插入的位置的上一個節點。而後跟第一種方法的思路是差很少的,將建立的節點指針指向當前節點指向的元素newNode.next = current.next,而後讓當前節點指針指向新建立的元素current.next = newNodeprototype

LinkList.prototype.insert = function (position, data) {
    var newNode = new Node(data);
    if (position < 0 || position > this.length) return false;
    if (position === 0) {
        newNode.next = this.head;
        this.head = newNode;
    } else {
        var current = this.head;
        for (var i = 0; i < position - 1; i++) {
            current = current.next;
        }
        newNode.next = current.next;
        current.next = newNode;
    }
    this.length += 1;
}
複製代碼

3. get(position)方法

獲取某個位置的元素,查找到這個位置,讓current指向當前位置,返回當前位置的data值便可。指針

LinkList.prototype.get = function (position) {
    if (position < 0 || position >= this.length) return null;
    var current = this.head;
    for (var i = 0; i < position; i++) {
        current = current.next;
    }
    return current.data;
}
複製代碼

4. update(position, data)方法

修改某個位置的元素值。這個跟get方法實際上是差很少的,只不過get只是拿到這個位置的data值,可是update是要咱們將這個data值改爲傳進來的data。這個就不用代碼呈現了。

5. indexOf(element)方法

在鏈表中查找某一個元素的值(data),當找到這個元素的時候就這個元素的索引號(即位於哪一個位置)。若是沒有找到這個數據的話就會返回-1。遍歷鏈表,將每個元素的data和要查找的element進行比較,若是相同就返回它的索引值。

LinkList.prototype.indexOf = function (element) {
    var current = this.head;
    var index = 0;
    while (current) {
        if (current.data == element) {
            return index;
        }
        current = current.next;
        index += 1;
    }
    return -1;
}
複製代碼

6. removeAt(position)方法

從某個位置移除一個元素。有兩種狀況:

1)刪除position = 0的元素;雖然此時刪除的元素仍是指向第二個元素,可是此時雖然它有指向別人,可是沒有人指向它,瀏覽器會自動把這些沒用的對象回收。

2)刪除position > 0的元素;查找元素,直到要刪除元素位置的上一個位置,即currentcurrent.next本來指向的就是這個要刪除的元素,對它的指向從新賦值爲current.next.next,即指向刪除元素的下一個元素位置。最後再返回刪除元素的data值。

LinkList.prototype.removeAt = function (position) {
    var current = this.head;
    if (position < 0 || position >= this.length) return false;
    if (position == 0) {
        this.head = this.head.next
    } else {
        for (var i = 0; i < position - 1; i++) {
            current = current.next;
        }
        current.next = current.next.next;
    }
    this.length -= 1;
    return current.data;
}
複製代碼

7. remove(data)方法

移除data等於傳入的data的元素。1)用indexOf獲取data在鏈表中的位置;2)根據位置信息刪除節點,返回刪除的數據。

LinkList.prototype.remove = function (data) {
    var position = this.indexOf(data);
    return this.removeAt(position);
}
複製代碼

8. toString()方法

這個方法只是方便咱們查看鏈表中的數據。實現方法:遍歷鏈表,將鏈表中的每個節點的值都取出來放到一個字符串中,再做爲返回值返回,

LinkList.prototype.toString = function () {
    var current = this.head;
    var listString = '';
    while (current) {
        listString += current.data + ' ';
        current = current.next;
    }
    return listString;
}
複製代碼

\

相關文章
相關標籤/搜索