数据结构之链表(一)

271 阅读3分钟

这是我参与更文挑战的第13天,活动详情查看:更文挑战

什么是链表

链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。 如下图所示:

链表结构示意图.png

  • 相对于传统的数组,链表的一个好处在于,添加或移除元素的时候不需要移动其他元素。
  • 链表需要使用指针,因此实现链表时需要额外主要。
  • 想要访问链表中间的一个元素时,需要从起点(表头)开始迭代链表直到找到所需的元素。 链表类似于火车的结构,每节车厢都相互连接,很容易的分离一节车厢,改变它的位置,添加或者移除它。

创建链表

实现LinkedList类,LinkedList数据结构需要 一个Node辅助类,用来表示要加入列表的项。它包含一个elemengt属性,即要添加到列表的值,以及一个next属性即指向列表下一个节点项的指针。 LikedList类也有存储列表的数量的length属性(内部私有变量)。此外,我们还需要存储第一个节点的引用,可以将这个引用存储在一个head变量中。链表所需的方法如下:

  • append(element): 向列表尾部添加一个新的项。
  • insert(position, element): 向列表的特定位置插入一个新的项。
  • remove(element): 从列表中移除一项。
  • indexOf(element): 返回元素在列表中的索引。如果列表中没有该元素则返回-1
  • removeAt(position): 从列表的特定位置移除一项。
  • isEmpty(): 如果列表中不包含任何元素,返回true,如果链表的长度大于0则返回false
  • size(): 返回链表中包含的元素个数,与数组的length属性类似。
  • toString(): 由于列表项使用了Node类,就需要重写继承自js对象默认的toString方法,让其只输出元素的值。 实现向链表尾部添加元素
function LikedList () {
    // 节点类
    let Node = function (element) {
           this.element = element
           this.next = null
    }
    // 链表数量
    let length = 0 
    // 第一个节点的引用
    let head = null
    
    // 向列表尾部添加一个新的项
    this.append = function (element) {
        // 尾部添加一个元素时,有两种情况:列表为空,添加的时第一个元素,或者列表不为空,向其追加元素
        let node = new Node(element)
        let current = null;
        if (head === null) {
            head = node
        } else {
            current = node
            // 循环列表,直到找到最后一项
            while(current.next) {
                current = current.next
            }
            // 找到最后一项,将其next赋值为node建立连接
            current.next = node
        }
        length++
    }
    
    // this.insert = function (position, element) {}
    // this.removeAt = function (position) {}
    // this.remove = function (element) {}
    // this.indexOf = function (element) {}
    // this.isEmpty = function () {}
    // this.size = function () {}
    // this.getHead = function () {}
    // this.toString = function () {}
    // this.print = function () {}
}

PS:列表最后一个节点的下一个元素始终是null

上述代码中,实现步骤如下:

  1. 首先将element作为值传入,创建Node项。并记录current
  2. 当新建一个LinkedList对象时,head会指向null,如果head为null则是在向列表添加第一个元素,此时我们要做的就是将上一步创建的node赋值给head
  3. head不为空时,要向列表尾部添加一个元素,那么首先就得找到最后一个元素。
  4. 循环访问列表,直到找到最后一项,此时首先定一个current变量表示循环的当前项,初始值为head,即从头开始循环。
  5. 如果current.next不为nul,说明其不是最后一个元素,那么将current.next赋值给current,即将current循环到下一项。
  6. 如果current.next为null,说明已经找到了最后一项,也就是此时的current,那么将current.next的值指向要添加进来的元素node,即可。
  7. 到第六步结束,我们已经将node添加到了列表的尾部,但是不要忘记了更新长度length
  8. 完美结束。

未完待续。。。 下期更新从链表中移除元素