js 实现单链表

最近在 leetcode 刷题时发现需要用到链表,但是 js 中没有链表这种数据类型,故自己实现一个简单的单链表。

先科普一下链表:

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。

总结一下:数组查询快增删慢(插入元素时需要移动其他元素),链表查询慢(需要从头开始遍历)增删快。

链表实现类:

// 节点类
function Node (val) {
  this.val = val
  this.next = null
}

// 链表类
function NodeList () {
  this.head = null
  this.length = 0
  // 向链表末尾追加元素
  this.push = push
  // 在值为 val 的节点后面添加一个值为 newVal 的节点
  this.insertAfter = insertAfter
  // 在链表中查找值为 val 的节点
  this.find = find
  // 在链表中查找值为 val 的节点的前一个节点
  this.findPrev = findPrev
  // 删除链表中值为 val 的节点
  this.remove = remove
  // 将值为 val 的节点修改为 newVal
  this.update = update
  // 打印链表
  this.toString = toString
}

function push (val) {

  let node = new Node(val)
  // 第一个节点
  if (this.head === null) {
    this.head = node
  } else {
    let current = this.head
    // 找到最后一个节点
    while (current.next !== null) {
      current = current.next
    }
    // 最后一个节点后面追加节点
    current.next = node
  }
  this.length++

}

function insertAfter (val, newVal) {

  let current = this.find(val)
  if (current === null) return -1
  let node = new Node(newVal)
  // 先将当前节点的指向给到新节点的指向
  node.next = current.next
  // 再将当前节点指向新节点
  current.next = node
  this.length++

}

function find (val) {

  // 空链表
  if (this.head === null) return null
  let current = this.head
  // 查找到最后一个节点之前
  while (current.next !== null) {
    if (current.val === val) return current
    current = current.next
  }
  // 判断最后一个节点
  if (current.val === val) return current
  return null

}

function findPrev (val) {

  // 空链表或者查找第一个节点的前一个节点均查不到
  if (this.head === null || this.head.val === val) return null
  let current = this.head
  // 最后一个节点不进循环,最后一个节点不可能是某个节点的前一个节点
  while (current.next !== null) {
    if (current.next.val === val) return current
    current = current.next
  }
  return null

}

function remove (val) {

  let current = this.find(val)
  if (current === null) return -1
  else {
    let prev = this.findPrev(val)
    if (prev !== null) {
      prev.next = current.next
    } else {
      this.head = current.next
    }
  }
  this.length--

}

function update (val, newVal) {

  let current = this.find(val)
  if (current === null) return -1
  current.val = newVal

}

function toString () {

  let current = this.head
  let str = ''
  let index = 0
  while (current !== null) {
    // str += index + current.val + (current.next ? ' -> ' : '')
    str += `(${index}) ${current.val}${current.next ? ' -> ' : ''}`
    current = current.next
    index++
  }
  console.log(str)

}

测试代码:

let nodeList = new NodeList()

nodeList.push('1st element')
nodeList.push('2nd element')
nodeList.push('3rd element')
nodeList.push('4th element')

console.log('find', nodeList.find('1st element'))
console.log('find', nodeList.find('2nd element'))
console.log('find', nodeList.find('3rd element'))
console.log('find', nodeList.find('4th element'))

console.log('findPrev', nodeList.findPrev('1st element'))
console.log('findPrev', nodeList.findPrev('2nd element'))
console.log('findPrev', nodeList.findPrev('3rd element'))
console.log('findPrev', nodeList.findPrev('4th element'))

nodeList.remove('4th element')
console.log('length', nodeList.length, 'nodeList', nodeList)

nodeList.insertAfter('2nd element', '2nd element 2')
console.log('length', nodeList.length, 'nodeList', nodeList)

nodeList.update('2nd element', '2nd element update')
console.log('length', nodeList.length, 'nodeList', nodeList)

nodeList.toString()

代码详情请戳 ===> NodeList

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值