JavaScript数据结构与算法——链表详解(上)

注:与之前JavaScript数据结构与算法系列博客不同的是,从这篇开始,此系列博客采用es6语法编写,这样在学数据结构的同时还能对ECMAScript6有进一步的认识,如需先了解es6语法请浏览http://es6.ruanyifeng.com/

1、链表定义

链表是一组节点组成的集合。每个节点都使用一个对象的引用指向它的后继,指向另一个节点的引用叫做链。
之前我们介绍过列表,如需回顾请点击这里,我们都知道列表数据结构的底层数据结构是数组。在JavaScript中,数组被实现成了对象,相对于其他语言(比如Java)的数组相比,效率很低。链表相对数组而言,效率更高,能使用一维数组解决的情景链表几乎都可以解决。当然,如果需要对数据随机访问的话,使用数组更好。

2、链表实现解析

这里写图片描述
以上是一个链表,与数组不同的是,数组元素依靠它们的位置进行引用,链表元素则靠相互间的关系引用。比如以上链表结构,我们应该说JavaScript在Java后边,PHP在JavaScript后边,而不是说XXX是第几个元素。注意:链表的尾元素指向NULL节点,遍历链表时,不包含头节点,头节点只是作为链表的接入点。怎么才能遍历完整整个链表?我们可以做出以下修改:
这里写图片描述
这样就实现了一个有头节点的链表。

向列表中插入一个节点很方便,只需要将待插入节点的前节点指向待插入节点,同时将待插入节点指向指向前节点原本的后续节点即可。感觉有点模糊的话,看看图就更清晰了:
这里写图片描述
理解了插入元素,从链表中删除一个元素就很简单了,只需要改变节点的指向即可。如图,删除节点JavaScript
这里写图片描述

3、JS实现链表数据结构

我们将实现两个类,Node类用于表示节点,LinkedList类用于提供操作链表的一系列方法,比如插入、删除节点等。

3.1、实现Node类
// Created by xiaoqiang on 23/04/2018.
class Node {
  constructor (element) {
    this.element = element
    this.next = null
  }
}

解释:element用于保存节点上的数据,next用于保存下一个节点的链接。

3.2、实现LinkedList类
class LinkedList {
  constructor () {
    this.header = new Node('header')        // 头节点
  }
  // 查找元素
  find (item) {
    let currNode = this.header
    while (currNode.element !== item) {
      currNode = currNode.next
    }
    return currNode
  }
  // 插入节点
  insert (item, newElement) {
    let newNode = new Node(newElement)
    let current = this.find(item)
    newNode.next = current.next
    current.next = newNode
  }
  // 删除节点
  display () {
    let currNode = this.header
    while(currNode.next !== null) {
      console.log(currNode.next.element)
      currNode = currNode.next
    }
  }
  // 显示链表
  findPrevious (item) {
    let currNode = this.header
    while (currNode.next !== null && currNode.next.element !== item) {
      currNode = currNode.next
    }
    return currNode
  }
  // 查找前一个元素
  remove (item) {
    let prevNode = this.findPrevious(item)
    if (prevNode.next !== null) {
      prevNode.next = prevNode.next.next
    }
  }
}

解释:理解了2中的原理图的话,应该理解起来不是太困难,唯一注意的移除元素时,需要先知道前一个元素,这样才能改变指向,所以需要findPrevious函数。

3.3、测试用例
let books = new LinkedList()
console.log('开始插入操作')
books.insert('header', 'JavaScript')
books.insert('JavaScript', 'PHP')
books.insert('PHP', 'Nodejs')
console.log('插入后的链表数据为:')
books.display()
console.log('开始进行移除操作')
books.remove('PHP')
console.log('移除后PHP后的链表的数据为:')
books.display()
3.4、完整代码:
// Created by xiaoqiang on 23/04/2018.
class Node {
  constructor (element) {
    this.element = element
    this.next = null
  }
}

class LinkedList {
  constructor () {
    this.header = new Node('header')        // 头节点
  }
  // 查找元素
  find (item) {
    let currNode = this.header
    while (currNode.element !== item) {
      currNode = currNode.next
    }
    return currNode
  }
  // 插入节点
  insert (item, newElement) {
    let newNode = new Node(newElement)
    let current = this.find(item)
    newNode.next = current.next
    current.next = newNode
  }
  // 显示链表
  display () {
    let currNode = this.header
    while(currNode.next !== null) {
      console.log(currNode.next.element)
      currNode = currNode.next
    }
  }
  // 查找前一个元素
  findPrevious (item) {
    let currNode = this.header
    while (currNode.next !== null && currNode.next.element !== item) {
      currNode = currNode.next
    }
    return currNode
  }
  // 删除节点
  remove (item) {
    let prevNode = this.findPrevious(item)
    if (prevNode.next !== null) {
      prevNode.next = prevNode.next.next
    }
  }
}

let books = new LinkedList()
console.log('开始插入操作')
books.insert('header', 'JavaScript')
books.insert('JavaScript', 'PHP')
books.insert('PHP', 'Nodejs')
console.log('插入后的链表数据为:')
books.display()
console.log('开始进行移除操作')
books.remove('PHP')
console.log('移除后PHP后的链表的数据为:')
books.display()

3.5、运行及结果
使用Node 运行以上js文件,我的文件名是LinkedList.js,使用node LinkedList.js运行结果如下:
这里写图片描述
JavaScript数据结构与算法——链表详解(上)完结,有错误欢迎指出,晚安~

猜你喜欢

转载自blog.csdn.net/fabulous1111/article/details/80045161