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

JavaScript数据结构与算法——链表详解(上)中,我们探讨了一下链表的定义、实现原理以及单链表的实现。接下来我们进一步了解一下链表的其他内容。

1、双向链表

双向链表实现原理图:
这里写图片描述
与单向链表不同的是,图中增加了小线部分,每一个节点增加了一个指向前驱节点的属性,这样就实现了双向链表。
双向链表中,删除节点不需要知道待删除节点的前驱节点,只要把待删除节点指向前驱节点的属性指向NULL,同时把前驱节点指向待删除节点的后继节点即可,这样在删除节点时更高效。结合原理图比较好理解一点,双向链表中,删除节点原理如下图:
这里写图片描述
增加节点原理如下图:

2、JS实现双向链表

以下代码基于JavaScript数据结构与算法——链表详解(上)中的代码修改,文章末尾会附上完整代码。
从原理图可知,我们应该先给节点添加previous属性,可通过修改Node类实现:

2.1、Node类修改
// Created by xiaoqiang on 24/04/2018.
class Node {
  constructor (element) {
    this.element = element
    this.next = null
    this.previous = null
  }
}
2.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
  }
  // 用于返回最后一个节点
  findLast () {
    let currNode = this.header
    while (currNode.next !== null) {
      currNode = currNode.next
    }
    return currNode
  }
  // 插入节点
  insert (item, newElement) {
    let newNode = new Node(newElement)
    let current = this.find(item)
    newNode.next = current.next
    newNode.previous = current
    current.next = newNode
  }
  // 删除节点
  remove (item) {
    let currNode = this.find(item)
    if (currNode.next !== null) {
      currNode.previous.next = currNode.next
      currNode.next.previous = currNode.previous
      currNode.next = null
      currNode.previous = null
    }
  }
  // 显示链表
  display () {
    let currNode = this.header
    while(currNode.next !== null) {
      console.log(currNode.next.element)
      currNode = currNode.next
    }
  }
  // 反向显示链表
  displayReverse () {
    let currNode = this.header
    currNode = this.findLast()
    while (currNode.previous !== null) {
      console.log(currNode.element)
      currNode = currNode.previous
    }
  }
}

链表中的方法可根据需要添加。

2.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()
console.log('反向显示链表:')
books.displayReverse()
2.3、双向链表完整代码
// Created by xiaoqiang on 24/04/2018.
class Node {
  constructor (element) {
    this.element = element
    this.next = null
    this.previous = null
  }
}

class LinkedList {
  constructor () {
    this.header = new Node('header')        // 头节点
  }
  // 查找元素
  find (item) {
    let currNode = this.header
    while (currNode.element !== item) {
      currNode = currNode.next
    }
    return currNode
  }
  // 用于返回最后一个节点
  findLast () {
    let currNode = this.header
    while (currNode.next !== null) {
      currNode = currNode.next
    }
    return currNode
  }
  // 插入节点
  insert (item, newElement) {
    let newNode = new Node(newElement)
    let current = this.find(item)
    newNode.next = current.next
    newNode.previous = current
    current.next = newNode
  }
  // 删除节点
  remove (item) {
    let currNode = this.find(item)
    if (currNode.next !== null) {
      currNode.previous.next = currNode.next
      currNode.next.previous = currNode.previous
      currNode.next = null
      currNode.previous = null
    }
  }
  // 显示链表
  display () {
    let currNode = this.header
    while(currNode.next !== null) {
      console.log(currNode.next.element)
      currNode = currNode.next
    }
  }
  // 反向显示链表
  displayReverse () {
    let currNode = this.header
    currNode = this.findLast()
    while (currNode.previous !== null) {
      console.log(currNode.element)
      currNode = currNode.previous
    }
  }
}

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()
console.log('反向显示链表:')
books.displayReverse()
2.4、运行及结果

使用node运行此js文件,结果如下:
这里写图片描述

3、循环链表

循环链表实现原理如下图:
这里写图片描述
原理比双向链表更简单一些,有兴趣可以尝试实现一下,也可以给以上实现的链表类多添加一些方法,加深理解。
至此,JavaScript数据结构与算法——链表详解(下)完结,有错误欢迎指出。

猜你喜欢

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