js實現資料結構--單連結串列

陽光下的冷靜發表於2018-11-26

單連結串列的概念:

單連結串列是一種鏈式存取的資料結構,用一組地址任意的儲存單元存放線性表中的資料元素。每個元素由一個儲存元素本身的節點和一個指向下一個元素的引用(也稱指標或連結)組成。下圖展示了一個單連結串列的結構圖:

單連結串列結構圖

單連結串列的特點:

  1. 每個元素除了由元素本身的節點還有指向下一個元素的指標構成
  2. 從連結串列中新增或者刪除元素不需要移動其他的元素
  3. 訪問連結串列中間的一個元素,需要從表頭開始迭代列表直到找到所需的元素

生活中單連結串列的案例:

生活中的單連結串列很典型也很常見。例如尋寶遊戲,你有一條線索,這條線索是指向尋找下一條線索的地點的指標,你可以順著這條連結去下一個地方,得到另一條指向下一處的線索,如果想得到列表中間的線索的唯一辦法就是從起點(第一條線索)順著列表尋找。另一個案例就是火車,還有其他的案例這裡就不一一列舉了。

js定義單連結串列以及一些基本方法:

首先建立一個類似於類的結構定義單連結串列,宣告一些基本的屬性,程式碼如下:

//定義單連結串列
    function LinkedList() {
        let Node = function (element) {
            this.element =element;
            this.next = null;
        }
        let length = 0;
        let head = null;

同時在該類中定義並宣告單連結串列的一些基本方法,程式碼如下:

 //向列表尾部新增一個新的項
        this.appendNode =  function (element) {
            let node = new Node(element);
            let current;//current變數是對列表中第一個元素的引用
            if (head === null){
                head = node;
            } else {
                current = head;
                //迴圈列表,直到找到最後一項
                while (current.next){
                    current = current.next;
                }
                //找到最後一項,將其next賦為node,建立連結
                current.next = node;
            }
            length++;//更新列表的長度
        } ;


        //向列表的特定位置插入一個新的項
        this.insertNode =  function (pos,ele) {
            if(pos > -1 && pos <= length){
                let node = new Node(ele),
                    index = 0,
                    current = head,//current變數是對列表中第一個元素的引用
                    previous;
                if (pos === 0) {//在列表的起點新增元素
                    node.next = head;
                    head = node;
                }else{//在列表的中間或者尾部新增一個元素
                    while(index++ < pos){
                        //迴圈訪問列表,找到目標位置
                        previous = current;
                        current = current.next;
                    }
                    //找到位置後,current就是對想要插入新元素的位置之後一個元素的引用
                    //previous是對想要插入新元素的位置之前一個元素的引用
                    previous.next = node;
                    node.next = current;
                };
                length++;
                return true;
            }else{
                return false;
            }
        };


        //移除列表某位置的元素
        this.removeAt =  function (pos){
            //檢查越界值
            if (pos >-1 && pos < length){
                let current = head,
                    //current 是對列表中第一個元素的引用
                    previous, index = 0;
                //第一種情況,移除第一項
                if (pos === 0){
                    head = current.next;
                } else {
                    while (index++ <pos){
                        previous = current;
                        current = current.next;
                    }
                    //將previous與current的下一項鍊接起來,跳過current,從而移除它
                    previous.next = current.next;
                }
                length--;
                return current.element;
            } else {
                return null;
            }

        } ;


       //返回某個元素在列表中的索引,指定元素下標從-1開始
        this.indexOf =function (ele){
            let current = head ,
                index = -1;
            while (current){
                if (ele === current.element){
                     return index;
                }
                index++;
                current = current.next;
            }
            return -1;
        };


        //從列表中移除某個元素
        this.remove =  function (element) {
            var current = head,
                previous,
                indexCheck = 0;
            while (current && indexCheck < length) {
                if (current.element === element) {
                    if (indexCheck == 0) {
                        head = current.next;
                        length--;
                        return true;
                    } else {
                        previous.next = current.next;
                        length--;
                        return true;
                    }
                } else {
                    previous = current;
                    current = current.next;
                    indexCheck++;
                }
            }
            return false;
        }


        //另一種移除指定位置的元素的方法
         this.remove = function (element){
           let index = this.indexOf(element);
               return this.removeAt(index);
        }



        //判斷列表是否為空,沒有元素
        this.isEmpty = function  () {
            return length === 0;
        } ;


        //返回連結串列包含的元素個數
        this.size =  function  () {
            return length;
        };


        //輸出連結串列元素的值
        this.toString =  function  (){
            let current = head,
                string = '',
                indexCheck = 0;
            while (current && indexCheck < length){
                string += current.element +((current.next ? '-':''));
                current = current.next;
                indexCheck++;
            }
            return string;
        }
        //反轉單連結串列
        this.reverse = function () {
            var headNode = this.head;
            if (headNode === null || headNode.next === null) {
                return;
            }
            var p = headNode, q = p.next;
            while (q) {
                var r = q.next;
                q.next = p;
                p = q;
                q = r;
            }
            headNode = p;
        }
}

使用單連結串列:

首先定義一個單連結串列,並向連結串列新增兩個元素,程式碼如下:

 let list = new LinkedList();
    //向連結串列的尾部新增兩個元素
    list.appendNode(15);
    list.appendNode(10);

呼叫宣告的方法,檢視結果,程式碼如下:

console.log("連結串列目前所有的元素構成的字串為:"+list.toString());//輸出15-10
console.log("連結串列中的元素個數是:"+ list.size());//輸出2
console.log(list.isEmpty());//判斷連結串列是否為空,false

呼叫其他的方法,如檢視元素索引,在指定位置插入元素,移除元素,程式碼如下:

console.log('元素10在連結串列中的索引是:'+list.indexOf(10));//輸出0
list.appendNode(20);
//向連結串列的index為1的位置新增一個元素
console.log(list.insertNode(1,'33'));//輸出true
//刪除連結串列某個位置的元素
console.log(list.removeAt(0));//輸出15
//刪除某個特定的元素
console.log(list.remove(10));//輸出true

 

相關文章