乐趣区

关于javascript:javascript数据结构之链表

链表数据结构

要贮存多个元素,js 中数组可能是最罕用的数据结构,然而从数组的终点或两头插入或者移除项的老本很高,因为须要挪动元素。
链表存储有序的元素汇合,但不同于数组,链表中的元素在内存中并不是间断搁置,而是每个元素由一个存储元素自身的节点和指向下一个元素的援用组成,这是失常的链表,双向链表比失常的多了一个指向前一个的元素援用,循环链表能够是单向援用,也能够是双向援用,循环链表的最初一个元素指向下一个元素的指针不是 undefined 而是第一个元素 head.

画的图有点渣,这是一个双向的循环链表。
创立一个最简略的链表

function defaultEquals(a,b){return a===b;}
class Node{constructor(el){
        this.el = el;
        this.next = undefined;
    }
}
class LinkedList{// 单向链表
    constructor(equals = defaultEquals){
        this.count = 0;
        this.head = undefined;
        this.equalsFn = equals;
    }
    push(el){const node = new Node(el);
        let current;
        if(!this.head){this.head = node;}else{
            current = this.head;
            while(current.next){current = current.next;}
            current.next = node;
        }
        this.count++;
    }
    getElAt(index){// 依据地位获取元素
         if(index>=0 && index<this.count){
            let current = this.head;
            for(let i=0;i<index && current;i++){current = current.next;}
            return current;
         }
         return undefined;
    }
    removeAt(index){// 依据地位移除
        if(index>=0 && index<this.count){
            let current = this.head;
            if(index===0){this.head = current.next;}else{let previous=this.getElAt(index-1);// 获取前一个
                current = previous.next;         
                previous.next = current.next;
            }
            this.count--;
            return current.el;
        }
        return undefined;
    }
    insert(el,index){// 任意地位插入
        if(index>=0 && index<=this.count){const node = new Node(el);
            if(index===0){
                const current = this.head;
                node.next = current;
                this.head = node;
            }else{const previous = this.getElAt(index-1);
                const current = previous.next;
                node.next = current;
                previous.next = node;
            }
            this.count++;
            return true;
        }
        return false;
    }
    indexOf(el){
        let current = this.head;
        for(let i=0;i<this.count;i++){if(this.equalsFn(current.el,el)){return i;}
            current = current.next;
        }
        return -1;
    }
    remove(el){let index = this.indexOf(el);
        return this.removeAt(index);
    }
    size(){return this.count;}
    isEmpty(){return this.size() === 0;
    }
    getHead(){return this.head;}
    toString(){if(!this.head){return '';}
        let str = `${this.head.el}`;
        let current = this.head.next;
        for(let i=0;i<this.size() && current;i++){str=`${str}${current.el}`;
            current = current.next;
        }
        return str;
    }
}

双向链表,减少一个指向前一个元素的援用

class DoublyNode extends Node{constructor(el,next,prev){super(el);
        this.prev = prev;
    }
}
class DoublyLinkedList extends LinkedList{constructor(equals = defaultEquals){super(equals);
       this.tail = undefined;
    }
     push(el){const node = new DoublyNode(el);
        let current;
        if(!this.head){this.head = node;}else{
            current = this.head;
            while(current.next){current = current.next;}
            current.next = node;
            node.prev = current;
        }
        this.tail = node;
        this.count++;
    }
}

该内容借鉴与学习 javascript 数据结构与算法

退出移动版