常用数据结构(四)链表

链表是在存储空间上具有一定优势的线性结构。

  • 它的有序性是通过指针来实现的,即每个元素都有一个指向下一个元素的指针(链表末端元素可能指向 null),所以它不需要连续的内存空间,从而可以节省内存的占用。
  •  React.js 的 Fiber 算法就是基于链表实现的。

下面的代码实现了一个基础的链表,包括链表的查找、新增和删除功能。

function LinkedList() {

  // 声明并定义头结点
  var head = {
    value: 'head',
    next: null
  }

  // 查找节点
  this.find = function(item) {
    var currNode = head
    while (currNode.value !== item) {
      currNode = currNode.next
    }
    return currNode
  }

  // 插入节点
  this.insert = function (value, pre) {
    var newNode = {
      value,
      next: null
    }
    var currNode = this.find(pre)
    newNode.next = currNode.next
    currNode.next = newNode
  }

  // 移除节点
  this.remove = function (item) {
    var prevNode = this.findPrev(item)
    var currNode = this.find(item)
    if (prevNode.next !== null) {
      prevNode.next = prevNode.next.next
      currNode.next = null
    }
  }

  // 查找前一个节点
  this.findPrev = function (item) {
    var currNode = head
    while (currNode.next !== null && currNode.next.value !== item) {
      currNode = currNode.next
    }
    return currNode
  }
}

栈、队列由于操作受限,无法像数组一样通过下标来访问,查找某个元素时只能逐个进行操作,操作效率并不算高。

链表由于指针的存在,使得在操作效率方面有很大的提升空间。

从指针的方向上考虑,既可以单向也可以双向,那么就可以形成具有两个指针的双向链表,还可以让指针的头尾相连,形成双向循环链表。在一个双向循环链表中查找元素,就可以同时往两个方向查找,这使得在查找速度方面会略优于单向循环链表。libuv 中就使用到了双向循环链表来管理任务。

从指针的数量上考虑,还可以通过增加指针的方式来提升操作效率,跳跃表就是这样一种基于链表的数据结构。

下面是一个跳跃表实现原理的例子,在一个链表中建立了 3 层指针。最下一层指针,跨 1 个元素链接;中间一层指针,跨 2 个元素链接;上层指针,跨 4 个元素链接。

1---------->5---------->9->null

1---->3---->5---->7---->9->null

1->2->3->4->5->6->7->8->9->null

假设现在要在链表中找到数字 8,对于简单链表而言,需要查找 8 次。而在上述跳跃表中,只需要 5 步:

  1. 使用上层指针,找到 5,8 比 5 大,继续;
  2. 继续使用上层指针,找到 9,8 比 9 小,回退到 5,并且指针层数下移;
  3. 使用中层指针,找到 7,8 比 7 大,继续;
  4. 使用中层指针,找到 9,8 比 9 小,回退到 7,并且指针层数下移;
  5. 使用下层指针,找到 8。

总的来说,跳跃表通过增加链表元素的冗余指针,使用了空间换时间的方式来提升操作效率。在缓存数据库 Redis 中就使用了跳跃表这种数据结构。

参考:《前端高手进阶》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值