线性数据结构——链表

线性数据结构——链表

链表是一个线性结构,同时也是一个天然的递归结构。链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
在这里插入图片描述

  • js模拟链表
// 节点 (构成链表)
class Node {
  constructor (v, next) {
    this.value = v
    this.next = next
  }
}

// 链表的管理, 增删改查
class LinkList {
  constructor () {
    // 链表的长度
    this.size = 0
    // 初始化的值
    this.initNode = new Node(null, null)
  }
  // 查询的是要删除或插入的下个节点
  _find (header, index, currentIndex) {
    // 递归查找
    if (index === currentIndex) return header
    return this._find(header.next, index, currentIndex)
  }

  // 检测index是否存在
  _checkIndex (index) {
    if (index < 0 || index > this.size) throw new Error('index错误');
  }

  /**
   * @description:
   * @param {type} v 节点的值
   * @param {type} v index 插入节点的位置
   * @return:
   */
  insertNode (v, index) {
    // 检测index是否存在
    this._checkIndex(index)
    // 查找当前的节点
    // 传入一个初始化的空节点
    let prev = this._find(this.initNode, index, 0)
    // 当往链表的末尾插入的时候,prev.next为空
    // 其他情况的时候,因为我们要插入节点,所以插入节点的next应该是prev.next
    // 然后设置prev.next 为插入的节点
    prev.next = new Node(v, prev.next)
    this.size++
    return prev.next
  }

  /**
  * @description:
  * @param {type} index 插入节点的位置
  * @return: 
  */
  removeNode (index) {
    // 检测index是否存在
    this._checkIndex(index)
    // 先找到需要删除的节点
    let prev = this._find(this.initNode, index, 0)
    // 当前需要操作的节点
    let node = prev.next
    prev.next = ndoe.next
    ndoe.next = null
    // size 减一
    this.size--
    return node
    
  }

  /**
  * @description:
  * @param {number} index 插入节点的位置
  * @return: 
  */
  getNode(index) {
    // 检测index是否存在
    this._checkIndex(index)
    if (this.isEmpty()) return 
    // 查找上一个节点next等价于当前节点
    return this._find(this.initNode, index, index, 0).next
  }

  // 探空
  isEmpty () {
    return this.size === 0
  }
  // 获取链表的长度
  getSize () {
    return this.size
  }
}
export default LinkList

  • 链表的应用(力扣)

反转一个单链表
示例:
输入:1->2->3->4->5->null
输出:5->4->3-2->1->null

  • 算法流程
  1. 创建两个变量,一个是未反转的链表指针,另一个是反转后的链表
  2. 递归遍历未反转的链表
  3. 修改next指针,并且当前链表指针向前遍历,直到next等于null
let reverseList = function(head) {
  let cur = head
  let prev = null
  while(cur) {
    const temp = cur.next
    cur.next = prev
    prev = cur
    cur = temp
  }
  return prev
}

环形链表

  • 环形链表(循环链表)是一种链式储存结构,它的最后一个节点指向头节点,形成了一个环
    在这里插入图片描述
  • 环形链表的特点是:从环形链表中的任何一个节点出发都能找到任何其他节点

双向链表

双向链表以类似的方式工作,但还有一个引用字段称为prev。有了这个额外的字段,就能够知道当前节点的前一个节点。

  • 双向链表的特点:
    • 比起单链表,双链表需要更多指针用于指向前驱节点,所以需要储存空间比单链表多一点
    • 双链表需要同时维护next和prev两个指针
    • 双链表中的元素访问需要通过顺序访问,即要通过遍历的方式来寻找元素
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值