JavaScript 实现链表的操作
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 实现链表的操作相关的知识,希望对你有一定的参考价值。
JavaScript实现链表 :使用ES6面向对象语法
链表: 数据的一种存储结构,一个链表包含若干个结点,每个结点至少包含一个数据域和一个指针域,指针域指向下一个结点
链表的分类:
- 单向链表:每个结点都只有一个指向其下一个结点的指针域(next)
- 双向链表:每个结点都有一个指向其前一个结点的指针域(prev)和一个指向其下一个结点的指针域(next)
头指针、头结点、首元结点的区别:
- 头结点: 在单链表第一个元素结点之前设置的一个结点, 数据域可以不存任何信息,指针域指向单链表第一个元素的结点。头结点不是链表的必要元素
- 头指针: 指向单链表的第一个结点的指针, 如果单链表有头结点,则头指针指向头结点 ,如果单链表没有头结点,则头指针指向第一个首元结点。头指针不能为空,头指针是链表的必要元素
- 首元结点: 单链表中第一个有数据元素的结点。如果单链表有头结点,则首元结点为头结点的下一个结点,如果单链表没有头结点,则首元结点就是单链表的第一个结点
头结点的优点:
- 减少单链表添加删除时特殊情况的判断
- 减少了程序的复杂性,主要是添加和删除在第一个有元素的结点(首元结点)上有区别,如果链表没有头结点,则删除或添加时都得需要判断一次首元结点,有了头结点以后,首元结点实际为链表的第二个结点,使得所有的元素结点的添加删除更具有统一性
- 对于单链表来说, 头结点可有可无,但为了操作方便,一般情况下单链表都具有头结点
链表的设计:
一个是 Node 类用来表示结点,另一个是 SingleLinked 类提供插入结点、删除结点、遍历结点等一些操作
单链表代码:
//定义单向链表的结点类
class Node {
constructor(data) {
this.data = data //数据域
this.next = null //指针域
}
}
//定义单向链表类
class SingleLinked {
constructor() {
this.size = 0 //用来记录链表结点个数
this.head = new Node('head') //头指针:记录链表的起始地址
//与头结点区分:头结点是指带有数据结点中的第一个结点
this.currNode = ''
}
//判断链表是否为空
isEmpty() {
return this.size === 0
}
//获取链表的长度
getLength() {
return this.size
}
//遍历单链表:不重复访问链表的每一个结点
displayList() {
let list = ''
let currNode = this.head //指向链表的头指针
while (currNode) {
//若当前结点不为空
list += currNode.data
currNode = currNode.next //让指针指向当前结点的下一个结点
if (currNode) {
list += '->'
}
}
console.log(list)
}
// 获取链表的最后一个结点
findLast() {
let currNode = this.head
while (currNode.next) {
currNode = currNode.next
}
return currNode
}
//尾插法 在单链表尾部插入元素
appendNode(element) {
var currNode = this.findLast() //找到链表最后一个结点
var newNode = new Node(element) //创建一个新结点
currNode.next = newNode
newNode.next = null
this.size++ //链表长度+1
}
//查找结点
findNode(element) {
let currNode = this.head
while (currNode && (currNode.data !== element)) {
currNode = currNode.next
}
return currNode
}
//指定元素位置后插入结点
insertNode(item, element) {
let itemNode = this.findNode(item);
if (!itemNode) { //如果item元素不存在
return;
}
let newNode = new Node(element);
newNode.next = itemNode.next; //若currNode为最后一个节点,则currNode.next为空
itemNode.next = newNode;
this.size++;
}
//删除链表的某一个结点
deleteNode(element) {
if (!this.findNode(element)) {
console.log("要删除结点不存在!")
return
}
if ('head' === element) {
console.log("整个链表将被删除")
this.head = null
this.size = 0
return
}
//思想:让currNode结点的next指向下一个结点
let currNode = this.head
while (currNode.next.data !== element) {
currNode = currNode.next
}
currNode.next = currNode.next.next
//与上述删除思想相同
// let currNode = this.head
// while (currNode.next) {
// if (currNode.next.data === element) {
// currNode.next = currNode.next.next
// break
// }
// currNode = currNode.next
// }
//思想:加入一个前驱结点 preNode
// let currNode = this.head
// let preNode = null
// while (currNode.data !== element) {
// currNode = currNode.next
// preNode = currNode
// }
// preNode.next = currNode.next
this.size--
}
}
检测代码:
//创建一个空链表
let slist=new SingleLinked()
//判断链表是否为空
console.log(slist.isEmpty())
//尾插法插入元素
slist.appendNode(0)
//遍历单链表
slist.displayList()
//使用尾插法依次插入数组序列
let arr=[2,4,6,8,10]
for(var i=0;i<arr.length;i++){
slist.appendNode(arr[i])
}
slist.displayList()
//在指定位置插入元素
slist.insertNode(8,9)
slist.displayList()
//输出链表的长度(不包括头结点head)
console.log(slist.getLength())
//删除结点元素
slist.deleteNode(4)
//遍历
slist.displayList()
以上是关于JavaScript 实现链表的操作的主要内容,如果未能解决你的问题,请参考以下文章