JS实现单链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点(链表中每一个元素称为节点)组成,节点可以在运行时动态生成。每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
数组的长度是预先设定好的,想要额外添加元素或者删除元素是一件比较困难的事。那么使用链表的话恰恰就解决了这些问题,对于链表来说删除或添加一个元素是非常方便的,除了数据的随机访问(可以实现但是比较麻烦,比如可以通过添加和操作索引值来实现)
一般的链表都会额外添加一个头节点(作为辅助)和尾节点,例如:
在这里插入图片描述
数组元素靠它们的位置进行引用,链表元素则是靠相互之间的关系进行引用。在上图中,我们说男人跟在人类后面,而不说男人是链表中的第二个元素。遍历链表,就是跟着链接,从链表的首元素一直走到尾元素(但这不包含链表的头节点,头节点常常用来作为链表的接入点)。上图中另外一个值得注意的地方是,链表的尾元素指向一个null节点。
插入新元素
向单链表中插入一个节点,只需要修改它前面的节点(前驱),使其指向新加入的节点,而新加入的节点则指向原来前驱指向的节点。上图演示了如何在帅哥后加入吕小布。
删除元素
从链表中删除一个元素也很简单,只需要将待删除元素的前驱节点指向待删除元素的后继节点。上图展示了从单链表中删除男神。

用JS设计一个单链表

我们需要设计两个类,Node 类用来表示节点,LinkedList类提供插入节点、删除节点、显示列表元素的方法,以及其他一些辅助方法。

Node类:
// 存储节点
function Node(element){
  this.element = element
  this.next = null
}
LinkedList类:
function LinkedList(item){
  this.head = new Node('head')  // 头节点
}
用LinkedList的原型对象存储操作链表的方法:
LinkedList.prototype = {
  // 查找某一节点
  find: function(item){
    var currentNode = this.head
    while (currentNode.element !== item) {
      currentNode = currentNode.next
    }
    return currentNode
  },
  // 往某一节点后面插入新节点
  insert: function(newItem, item){
    var newNode = new Node(newItem)
    var currentNode = this.find(item)
    newNode.next = currentNode.next
    currentNode.next = newNode  // 这句很重要,是整个链表连接起来的关键
  },
  // 查找某一节点的前节点(前驱)
  findPrevious: function(item){
    var currentNode = this.head
    while (!(currentNode.next === null) && currentNode.next.element !== item) {
      currentNode = currentNode.next
    }
    return currentNode
  },
  // 删除某一节点
  remove: function(item){
    var previousNode = this.findPrevious(item)
    if (previousNode.next !== null) {
      previousNode.next = previousNode.next.next
    }
  },
  // 修改某一节点的数据
  edit: function(item, newItem){
    var currentNode = this.find(item)
    currentNode.element = newItem
  },
  // 打印所有节点
  display: function(){
    var currentNode = this.head
    while (currentNode.next !== null) {
      console.log(currentNode.next.element)
      currentNode = currentNode.next
    }
  }
}
测试:
const classify = new LinkedList()
classify.insert('human', 'head')  // 往头节点后面插入human节点
classify.insert('man', 'human')  // 往human节点后面插入man节点
classify.insert('shuaige', 'man')  // 往man节点后面插入shuaige节点
classify.insert('nanshen', 'shuaige')  // 往shuaige节点后面插入nanshen节点
classify.display()
/*human
  man
  shuaige
  nanshen*/
console.log(classify.find('human'))  // {element: 'human', next: Node(下一个节点)}
console.log(classify.findPrevious('nanshen')) // {element: 'shuaige', next: Node(下一个节点)}
classify.remove('man')  // 删除man节点
classify.display()
/*human
  shuaige
  nanshen*/
classify.edit('nanshen', 'lvxiaobu')  // 把nanshen节点改成lvxiaobu
classify.display()
/*human
  shuaige
  lvxiaobu*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端吕小布

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值