数据结构与算法之链表

Posted simpul

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法之链表相关的知识,希望对你有一定的参考价值。

链表

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

单向链表

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

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

技术图片

//  节点类
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;
    
双向链表

技术图片

//  节点类
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 属性指向它本身,这样插入节点都会使得链表的尾节点都指向头节点,形成一个循环链表。

技术图片

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

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

//  节点类
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;
    

以上是关于数据结构与算法之链表的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之链表

数据结构与算法之链表

JAVA数据结构与算法之链表

java数据结构与算法之链表找环入口

02_数据结构与算法之链表

02_数据结构与算法之链表