js 数据结构和算法 -链表

345 阅读4分钟

今天来聊聊数据结构中的算法结构-链表

相较于之前学习的 栈/队列 只关心 栈顶/首尾 的模式,链表更加像是数组。链表和数组都是用于存储有序元素的集合,但有几点大不相同

链表不同于数组,链表中的元素在内存中并不是连续放置的 链表添加或移除元素不需要移动其他元素 数组可以直接访问任何一个位置的元素,链表必须从表头开始迭代到指定位置访问。

  • 链表几乎可以用在任何可以使用一维数组的情况中。如果需要随机访问,数组仍然是更好的选择

和数组相反。因为链表是不连续的内存空间,插入和删除会非常的快

数据查询

链表要想随机访问第 k 个元素,就没有数组那么高效了。因为链表中的数据并非连续存储的,所以无法像数组那样,根据首地址和下标,通过寻址公式就能直接计算出对应的内存地址,而是需要根据指针一个结点一个结点地依次遍历,直到找到相应的结点。
时间复杂度为O(n)

代码实现

var Node = function (el) {
    this.el = el
    this.next = null
}

首先要定义描述每个节点的node,他的属性描述了下个节点的链接

我们先来实现他的添加功能的方法(这里先贴代码了)

var likedlist=function(){
    var head = null
        var length = 0
        var Node = function (el) {
            this.el = el
            this.next = null
        }
     // 链表添加元素
    this.append = function (el) {
        var node = new Node(el)
        if (head == null) {
            head = node
        }
        else {
            var current = head
            while (current.next) {
                current = current.next
            }
    // while循环执行完已经是最后一项了 
        current.next = node
        }
        length++
    }
}
先实例化一个节点对象,对象都有一条指向下一个节点的链接状态,是null 还是 下个节点node,这个先判断链头有没有元素,没有的话,就把第一个添加进来的node当做head头,当添加第二个已经有head,这时用while循环遍历对象的next属性,这个next就是链接两个node的纽带,只要添加下个node时,就先看看上个next的状态是不是为null,如果是的话,就把下个节点的引用给到上个节点的next,每添加一个都会进行这样的状态。这样我们就完成了添加的操作

插入的操作

再来添加插入的操作

this.insert = function (position, el) {
               if (position > -1 && position < length) {
                   var node = new Node(el)
                   if (position === 0) {
                       var current = head
                       head = node
                       head.next = current
                   }
                   else {
                       var index = 0
                       var current = head
                       var previous = null
                       while (index === position) {
                           previous = current
                           current = current.next
                           index++
                       }
                       previous.next = node
                       node.next = current
                   }
                   length++
               }
           }

第一块先要判断临界值,判断是否在链表的范围内及是否添加链表头部,如果不是的话 添加元素到position 后面

删除节点

this.removeAt = function (position) {
                if (position > -1 && position < length) {
                    if (position === 0) {
                        var current = head
                        head = current.next
                    }
                    else {
                        var current = head,
                            privious = null,
                            index = 0
                        //循环列表,找到position位置的元素和前一个元素
                        while (index < position) {
                            privious = current
                            current = current.next
                            index++
                        }
                        //跳出循环的时候,index===position
                    }
                    index--
                    return current
                }
                return
    }

获取链表头

    this.getHead = function () {
        return head
    }

判断链表是否为空

    this.isEmpty = function () {
        return !!length
    }

最后贴下代码

 //链表 
        //每个元素都带有下个元素的位置,链表就像火车,每个车厢不仅会有自己的乘客,而且还与链节下节车厢
        var likedlist = function () {
            var head = null
            var length = 0
            var Node = function (el) {
                this.el = el
                this.next = null
            }
            // 链表添加元素
            this.append = function (el) {
                var node = new Node(el)
                if (head == null) {
                    head = node
                }
                else {
                    var current = head
                    while (current.next) {
                        current = current.next
                    }
                    // while循环执行完已经是最后一项了 
                    current.next = node
                }
                length++
            }
            this.insert = function (position, el) {
                if (position > -1 && position < length) {
                    var node = new Node(el)
                    if (position === 0) {
                        var current = head
                        head = node
                        head.next = current
                    }
                    else {
                        var index = 0
                        var current = head
                        var previous = null
                        while (index === position) {
                            previous = current
                            current = current.next
                            index++
                        }
                        previous.next = node
                        node.next = current
                    }
                    length++
                }
            }
            this.isEmpty = function () {
                return !!length
            }
            this.removeAt = function (position) {
                if (position > -1 && position < length) {
                    if (position === 0) {
                        var current = head
                        head = current.next
                    }
                    else {
                        var current = head,
                            privious = null,
                            index = 0
                        while (index < position) {
                            privious = current
                            current = current.next
                            index++
                        }
                        //跳出循环的时候,index===position
                    }
                    index--
                    return current
                }
                return
            }

            this.getHead = function () {
                return head
            }
        }

总结:

要存储多个元素,数组可能是最常用的数据结构。但是,如果要存储数据,并且会有移除或者添加大量数据时候,链表比数组更实用。