JavaScript實現單向鏈表

JavaScript 自己提供了十分好用的數據類型,以知足你們的平常使用。單靠 Array  和 Object 也的確足夠應付平常的絕大部分需求,這也致使了不少前端er對數據結構這一塊不是十分的瞭解。html

數據結構是 CS 的必修科目,前端這個圈子非科班的童鞋比例較高,相信不少人對數據結構的瞭解並很少。雖然本人大學讀的也是 CS,但那時候上課基本都在睡覺,數據結構也是學得一塌糊塗,如今也基本上全忘了。前端

那下面咱們來了解一下,如何用 JavaScript 來實現一個 單向鏈表數組

 

維基百科中,對鏈表的描述以下:數據結構

鏈表(Linked list)是一種常見的基礎數據結構,是一種線性表,可是並不會按線性的順序存儲數據,而是在每個節點裏存到下一個節點的指針(Pointer)。因爲沒必要須按順序存儲,鏈表在插入的時候能夠達到O(1)的複雜度,比另外一種線性表順序錶快得多,可是查找一個節點或者訪問特定編號的節點則須要O(n)的時間,而順序表相應的時間複雜度分別是O(logn)和O(1)。this

 

由此能夠知道,鏈表和數據相比,會具備一下優勢:spa

  1. 不須要預先分配內存(在靜態語言中,數組是須要預先分配內存空間的,空間分配後不能再改變​​)
  2. 插入和刪除元素不須要移動其他元素,效率更高

JavaScript 做爲一門動態語言,其中的數組也是動態數組,不須要預先分配內存的。在使用過程當中還能夠動態增減數組長度,這直接讓 Array 類型的適用範圍擴大了很多。prototype

數組在進行插入和刪除元素時,是十分麻煩的事情,而這方面倒是鏈表的優點。在查找元素的效率方面,鏈表就比不上數組那麼方便快捷了。設計

 

單向鏈表,是鏈表中最簡單的一種,其特色是鏈表的連接方向是單向的,對鏈表的訪問要經過順序讀取從頭部開始。3d

下面咱們看看 單向鏈表 的圖示:指針

能夠看到,鏈表中每個 item(元素) 都有兩個部分組成:data 和 next。其中 data 用於存儲數據,是真正的存儲區。而 next 用於存放地址,用於指向下一個 item。

 

下面咱們看看怎麼設計一個單向列表。

通常的單向列表,都具備如下的屬性和方法:

  • first:指向第一個 item
  • last:指向最後一個 item
  • length:鏈表的 item 數量
  • get():獲取指定位置的 item
  • set():修改指定位置的 item
  • add():插入一個新的 item 到指定位置
  • remove():移除指定位置的 item
  • clear():清空全部 item

爲了方便實用,還提供了部分語法糖:

  • addFirst():插入一個新的 item 到鏈表頭部
  • addLast():插入一個新的 item 到鏈表尾部
  • removeFirst():移除第一個 item
  • removeLast():移除最後一個 item
  • toString():列表以 "10 -> a -> [1,2] -> 3.14" 方式輸出

 

下面是 SinglyLinkedList 的類:

var SinglyLinkedList = function () {

    function SinglyLinkedList() {
        this.length = 0;
        this.first = null;
        this.last = null;
    }

    /**
     * 根據索引獲取 item
     * @param   {Number}    index   鏈表索引
     * @returns {*}
     */
    SinglyLinkedList.prototype.get = function (index) {
        if (typeof index !== 'number' || index < 0 || index >= this.length) {
            return undefined;
        }

        var item = this.first;
        for (var i = 0; i < index; i++) {
            item = item.next;
        }
        return item;
    };

    /**
     * 根據索引設置 item 的內容
     * @param   {Number}    index   鏈表索引
     * @param   {*}         value   須要設置的值
     * @returns {*}
     */
    SinglyLinkedList.prototype.set = function (index, value) {
        if (typeof index !== 'number' || index < 0 || index >= this.length) {
            return false;
        }

        var item = this.get(index);
        item.data = value;
        return item;
    };

    /**
     * 根據索引位置插入新的 item
     * @param   {Number}    index   鏈表索引
     * @param   {*}         value   須要設置的值
     * @returns {*}
     */
    SinglyLinkedList.prototype.add = function (index, value) {
        if (typeof index !== 'number' || index < 0 || index > this.length || index === undefined) {
            return false;
        }

        var item = {
            data: value,
            next: null
        };

        if (this.length > 0) {
            if (index === 0) {
                item.next = this.first;
                this.first = item;
            } else if (index === this.length) {
                this.last.next = item;
                this.last = item;
            } else {
                var prevItem = this.get(index - 1),
                    nextItem = this.get(index);
                item.next = nextItem;
                prevItem.next = item;
            }
        } else {
            this.first = item;
            this.last = item;
        }

        this.length++;
        return item;
    };

    /**
     * 根據索引刪除 item
     * @param   {Number}    index   鏈表索引
     * @returns {boolean}
     */
    SinglyLinkedList.prototype.remove = function (index) {
        if (typeof index !== 'number' || index < 0 || index >= this.length) {
            return false;
        }

        var item = this.get(index);

        if (this.length > 1) {
            if (index === 0) {
                this.first = item.next;
            } else if (index === this.length - 1) {
                this.last = this.get(this.length - 2);
                this.last.next = null;
            } else {
                this.get(index - 1).next = item.next;
            }
        } else {
            this.first = null;
            this.last = null;
        }

        item = null;
        this.length--;
        return true;
    };

    /**
     * 清空整個單鏈表
     * @returns {boolean}
     */
    SinglyLinkedList.prototype.clear = function () {
        this.first = null;
        this.last = null;
        this.length = 0;
        return true;
    };

    SinglyLinkedList.prototype.addFirst = function (value) {
        return this.add(0, value);
    };

    SinglyLinkedList.prototype.addLast = function (value) {
        return this.add(this.length, value);
    };

    SinglyLinkedList.prototype.removeFirst = function () {
        return this.remove(0);
    };

    SinglyLinkedList.prototype.removeLast = function () {
        return this.remove(this.length - 1);
    };

    SinglyLinkedList.prototype.toString = function () {
        var arr = [],
            item = {};

        if (this.length) {
            do {
                item = item.next || this.get(0);
                arr.push(typeof item.data === 'object' ? JSON.stringify(item.data).replace(/\"/g, '') : item.data);
            } while (item.next);
        }

        return arr.join(' -> ');
    };

    return SinglyLinkedList;
}();

 

使用方法很簡單:

var sList = new SinglyLinkedList();
sList.addLast('a');
sList.addFirst(10);
sList.addLast(3.14);
sList.add(2, [1, 2]);
sList.addLast({a: 1, b: 2});
console.log(sList.toString());  // "10 -> a -> [1,2] -> 3.14 -> {a:1,b:2}"
console.log(sList.length);   // 5
sList.removeFirst();
sList.removeLast();
console.log(sList.toString());  // "a -> [1,2] -> 3.14"
console.log(sList.length);   // 3

 

 

 

參考資料:

http://zh.wikipedia.org/wiki/%E9%93%BE%E8%A1%A8

http://www.cnblogs.com/skywang12345/p/3561803.html#a33

 

 

本文做者:Maple Jan

本文連接:http://www.cnblogs.com/maplejan/p/3903749.html

相關文章
相關標籤/搜索