javascript数据结构之链表

链表数据结构

要储存多个元素,js中数组多是最经常使用的数据结构,可是从数组的起点或中间插入或者移除项的成本很高,由于须要移动元素。
链表存储有序的元素集合,但不一样于数组,链表中的元素在内存中并非连续放置,而是每一个元素由一个存储元素自己的节点和指向下一个元素的引用组成,这是正常的链表,双向链表比正常的多了一个指向前一个的元素引用,循环链表能够是单向引用,也能够是双向引用,循环链表的最后一个元素指向下一个元素的指针不是undefined而是第一个元素head.
image
画的图有点渣,这是一个双向的循环链表。
建立一个最简单的链表javascript

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;
    }
}

双向链表,增长一个指向前一个元素的引用java

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++;
    }
    insert(el,index){
        if(index>=0 && index<=this.count){
            const node = new DoublyNode(el);
            let current = this.head;
            if(index===0){
                if(!this.head){
                    this.head = node;
                    this.tail = node;
                }else{
                    node.next = current;
                    current.prev = node;
                    this.head = node;
                }
            }else if(index === this.count){
                current = this.tail;
                node.prev = current;
                current.next = node;
                this.tail = node;
            }else{
                const previous = this.getElAt(index-1);
                current = previous.next;
                previous.next = node;
                node.prev = previous;
                node.next = current;
                current.prev = node;
            }
            this.count++;
            return true;
        }
        return false;
    }
    removeAt(index){
        if(index>=0 && index<this.count){
            let current = this.head;
            if(index===0){
                this.head = current.next;
                if(this.count===1){
                    this.tail=undefined;
                }else{
                    this.head.prev = undefined;
                }
            }else if(index===this.count-1){
                current = this.tail;
                this.tail = current.prev;
                this.tail.next = undefined;
            }else{
                current = this.getElAt(index);
                const previous = current.prev;
                previous.next = current.next;
                current.next.prev = previous;
            }
            this.count--;
            return curren.el;
        }
        return undefined;
    }
}

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

相关文章
相关标签/搜索