注:与之前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数据结构与算法——链表详解(上)完结,有错误欢迎指出,晚安~