代码初学者可以看看这样可不可以快速理解链表

Posted hello,是翠花呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码初学者可以看看这样可不可以快速理解链表相关的知识,希望对你有一定的参考价值。

如果用js来模拟链表操作,我们应该怎样理解?网上大部分就是贴一下概念,一张图,一篇代码,但是对于小白来说还是很抽象。什么指针?什么next?为什么一会儿next=值一会儿next=next?

令很多初学代码的人很困惑,而且javascript是弱类型语言,没有“指针”这一概念,导致对很多文章里说的指针不太不理。

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

在我们用JavaScript表示指针时,可以把它当做是一个小推车。

“小明有一个小推车(小推车里有小梅)” ->“小梅有一个小推车(小推车里有小虎)”-> “小虎有一个小推车(小推车里有小丽)”

单向

我们假设工厂有个工作流水线,最开始流水线上没有人:

class Liushuixian 
  constructor()
    this.head = null
  

以“人”为一个节点,一个人带有一些信息 还有一个推车,车里没有东西

class People 
  constructor(people) 
    this.people = people
    this.next = null
  

假如我们招来第一个人:

class Liushuixian 
  constructor()
    this.head = null
  

  // 添加人
  appendRen(people) 
    // 入职
    let newPeople = new People(people)
    this.head = newPeople
  

  // 打印结果
  print() 
    let str = ''
    let current = this.head
    while(current) 
      str += current.people
      current = current.next
    

    console.log(str)
  


let l = new Liushuixian();

l.appendPeople("小明-车-->"); // 小明-车-->

如果招很多人:

class Liushuixian 
  constructor()
    this.head = null
  

  // 添加人
  appendPeople(people) 
    // 入职
    let newPeople = new People(people)

    // 如果流水线上没有人
    if (this.head === null) 
      this.head = newPeople
     else 
      // 否则遍历,让他在线尾工作
      let current = this.head
      // 如果当前这个人小推车里有人,我们就到下一个人那里
      while(current.next) 
        current = current.next
      
      // 直到这个人小推车里没有人,就往当前这个人小推车里加上新人
      current.next = newPeople
    
  

  // 打印结果
  print() 
    let str = ''
    let current = this.head
    while(current) 
      str += current.people
      current = current.next
    

    console.log(str)
  

往流水线里添加几个人,然后打印一下结果:

let l = new Liushuixian();

l.appendPeople("小明-车-->");
l.appendPeople("小梅-车-->");
l.appendPeople("小虎-车-->");
l.appendPeople("小丽-车-->");
l.print(); // 小明-车-->小梅-车-->小虎-车-->小丽-车-->

我们辞退某一个人,假如辞退小虎,那么小虎的工作小丽接了,小梅直接与小丽对接:

 deletePeople(item) 
    // 如果item等于0,头节点为下一个节点
    if (item === 0) 
      this.head = this.head.next; // 假设前一个节点为头结点
     else 
      // 从第一个人开始查找
      let index = 0;
      let prev = this.head;
      while (prev) 
        index++;
        if (index === item) 
          prev.next = prev.next.next // 前节点直接指向后第二位
         else 
          prev = prev.next;
        
      
    
  

  // 。。。
  // 辞退小梅
  l.deletePeople(1); // 小明-车-->小虎-车-->小丽-车-->
  // 然后辞退小丽
  l.deletePeople(2); // 小明-车-->小虎-车-->
  // 辞退小明
  l.deletePeople(0); // 小虎-车-->
  // 辞退小虎
  l.deletePeople(0); //

这里需要处理一下临界,当我们删除的item大于链总长时,应停止操作:

//  while (prev) 
  index++;
  if (item > index) 
    console.error('error: 超出链表长度')
    return
  
// ...

辞退某一个人后,我们想再招一个人插入到工作链路中。假设我们招来小芬,插入到小明后面小梅前面:

insertPeople(people, item) 
    let newPeople = new People(people);
    let head = this.head

    // 如果在头部插入,新头结点就等于新员工,新员工的小推车里是老头结点
    if (item === 0) 
      this.head = newPeople
      newPeople.next = head
     else 
      let prev = head
      let index = 0
      while(prev) 
        index ++

        if (index === item) 
          newPeople.next = prev.next
          prev.next = newPeople
         else 
          prev = prev.next
        
      
    
  

// ...
l.insertPeople('小芬-车-->', 1)  // 小明-车-->小芬-车-->小梅-车-->小虎-车-->小丽-车-->
结尾

上述next属性只我们说的小推车也就是指针域People构造函数代表节点,里面的people是携带的数据信息。current.next = newPeople 可以表示把新的节点newPeople赋值给了next,此时next就是携带了数据信息的属性(引用newPeople的地址),next指针域有指向newPeople地址的指针。js层面明眼儿说,就是一个承载newPeople值的属性。

以上是关于代码初学者可以看看这样可不可以快速理解链表的主要内容,如果未能解决你的问题,请参考以下文章

代码初学者可以看看这样可不可以快速理解链表

代码初学者可以看看这样可不可以快速理解链表

C#泛型

java加减乘除计算器界面编程?

用代码带你“深入”理解90%的初学者都没理解清楚的Java基础知识——流程控制

C++手写快读详解(快速读入数字)