javascript数据结构之链表

时间:2020-9-10 作者:admin

链表数据结构

要储存多个元素,js中数组可能是最常用的数据结构,但是从数组的起点或中间插入或者移除项的成本很高,因为需要移动元素。
链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置,而是每个元素由一个存储元素本身的节点和指向下一个元素的引用组成,这是正常的链表,双向链表比正常的多了一个指向前一个的元素引用,循环链表可以是单向引用,也可以是双向引用,循环链表的最后一个元素指向下一个元素的指针不是undefined而是第一个元素head.

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

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

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数据结构与算法

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。