• 数据结构与算法之链表


    链表

    JS中数组被实现成了对象,对比其他语言的数组效率很低。因此可以考虑使用链表来替代。除了对数据的随机访问,链表几乎可以用在任何使用以为数组的情况中。如果需要随机访问,数组仍然是更好的选择。

    单向链表

    链表是由一组节点组成的集合。 每个节点都使用一个对象的引用指向它的后继。 指向另一
    个节点的引用叫做链。

    遍历链表, 就是跟着链接, 从链表的首元素一直走到尾元素,下面最前面的节点叫做头节点,在最后面的尾元素指向一个null节点。

    1555743953692

    //  节点类
    function Node(element){
        this.element = element;
        this.next = null;
    }
    
    //  LinkedList类,建立一个新的链表
    function LList(){
        this.head = new Node("head");
    }
    LList.prototype = {
        constructor: LList,
        find(element){
            var node = this.head;
            while(node.element != element){
                if(node.next){
                    node = node.next;
                }else{
                    return null;
                }
            }
            return node;
        },
        insert(newElement, item){  //在item后面插入新元素
            var current = this.find(item);
            var newNode = new Node(newElement);
            newNode.next = current.next;
            current.next = newNode;
        },
        remove(item){
            var preNode = this.findPrevious(item);
            if(preNode.next !== null){
                preNode.next = preNode.next.next;     
            }
        },
        display(){  //不显示头节点
            var current = this.head;
            while(current.next !== null){
                console.log(current.next.element);
                current = current.next;
            }
        },
        findPrevious(item){  //用来查找该值节点的前一个节点
            var current = this.head;
            while(current.next.element !== item){
                if(current.next !== null){
                    current = current.next;
                }else{
                    return null;
                }
            }
            return current;
        }
    }
    
    双向链表

    1555746606695

    //  节点类
    function Node(element){
        this.element = element;
        this.next = null;
        this.previous = null;
    }
    
    //  LinkedList类,建立一个新的链表
    function LList(){
        this.head = new Node("head");
    }
    LList.prototype = {
        constructor: LList,
        find(element){
            var node = this.head;
            while(node.element != element){
                if(node.next){
                    node = node.next;
                }else{
                    return null;
                }
            }
            return node;
        },
        insert(newElement, item){  //在item后面插入新元素
            var current = this.find(item);
            var newNode = new Node(newElement);
            newNode.next = current.next;
            newNode.previous = current;
            current.next = newNode;
        },
        remove(item){  //双向链表删除节点效率更高了,因为不需要再查找前驱节点了
            var removeNode = this.find(item);
            if(removeNode){
                removeNode.previous.next = removeNode.next;
                removeNode.next.previous = removeNode.previous;
                removeNode.next = null;
                removeNode.previous = null;
            }
        },
        display(){  //不显示头节点
            var current = this.head;
            while(current.next !== null){
                console.log(current.next.element);
                current = current.next;
            }
        },
        findLast(){  //查找链表的最后一项
            var current = this.head;
            while(current.next !== null){
                current = current.next;
            }
            return current;
        },
        dispReverse(){
            var current = this.findLast();
            while(current.previous !== null){
                console.log(current.element);
                current = current.previous;
            }
        },
    }
    
    循环链表

    循环链表和单向链表相似, 节点类型都是一样的。 唯一的区别是, 在创建循环链表时, 让其头节点的 next 属性指向它本身,这样插入节点都会使得链表的尾节点都指向头节点,形成一个循环链表。

    1555760081924

    如果你希望可以从后向前遍历链表, 但是又不想付出额外代价来创建一个双向链表, 那么就需要使用循环链表。 从循环链表的尾节点向后移动, 就等于从后向前遍历链表。

    避免无限循环,需要对方法进行修改:

    //  节点类
    function Node(element){
        this.element = element;
        this.next = null;
    }
    
    //  LinkedList类,建立一个新的链表
    function LList(){
        this.head = new Node("head");
        this.head.next = this.head;
    }
    LList.prototype = {
        constructor: LList,
        find(element){
            var node = this.head;
            while(node.element != element){
                if(node.next === this.head){
                    return null;
                }
                node = node.next;
            }
            return node;
        },
        insert(newElement, item){  //在item后面插入新元素
            var current = this.find(item);
            var newNode = new Node(newElement);
            newNode.next = current.next;
            current.next = newNode;
        },
        remove(item){
            var preNode = this.findPrevious(item);
            preNode.next = preNode.next.next;     
        },
        display(){  //不显示头节点
            var current = this.head;
            while(current.next !== this.head){
                console.log(current.next.element);
                current = current.next;
            }
        },
        findPrevious(item){  //用来查找该值节点的前一个节点
            var current = this.head;
            while(current.next.element !== item){
                if(current.next === this.head){
                    return null;
                }
                current = current.next;
            }
            return current;
        }
    }
    
  • 相关阅读:
    周学习笔记(04)——大三下
    进度(3)
    进度(2)
    进度(1)
    周学习笔记(03)——大三下
    《信息领域热词分析》之在代码层实现可用性战术
    周学习笔记(02)——大三下
    cf1041E
    cf1067b
    cf1131D
  • 原文地址:https://www.cnblogs.com/simpul/p/11027177.html
Copyright © 2020-2023  润新知