JavaScript链表结构的实现
简述
链表:就类似于火车一样,一节一节的链接起来,从火车头链接到火车尾,添加数据时只能在链表尾部添加,获取想要的数据时(查找也是只能从头部到尾部一节一节的查找,不能跳节)
简单实现常用链表方法
append(node){}
insert(pos, node) { }
get(pos) { }
indexOf(node) { }
update(pos,node) { }
removeAt(pos) { }
remove(node) { }
node 节点
我们先定义一个 node 节点,用来存放的数据
class Node {
constructor(node){
this.node = node;
// 默认创建的节点 next 指向空
this.next = null;
}
链表 Linked 实现
创建 Linked 类
class Linked {
// 初始化时默认为空,没有数据,定义一个 head 及 length 长度为 0
construcrot() {
this.__head = null
this.__length = 0
}
}
append 方法实现
/**
* 向列表后添加
* @param {*} node 节点
*/
append(node) {
// 1.创建节点
const newNode = new Node(node)
// 判断当前链表是否是第一个节点
if (this.isEmpty()) {
this.__head = newNode
} else {
// 找最后一个节点
let currentNode = this.__head
while (currentNode.next) {
currentNode = currentNode.next
}
// 最后一个节点的 next 指向最新节点
currentNode.next = newNode
}
// 节点长度++
this.__length++
}
insert 方法实现
/**
* 链表插入数据
* @param {number} pos 要插入的位置 0 - 当前链表长度
* @param {*} node 要插入的节点
*/
insert(pos, node) {
// 对下标判断
if (pos < 0 || pos > this.size()) { return false }
// 创建节点
const newNode = new Node(node)
// 根据位置插入数据 区分为 0 跟不为 0
// - 0:将新节点的 next 指向下一个节点,修正 head 指向新节点
// - 1:分别定义变量接收当前节点跟上一个节点,新节点的 next 指向当前节点,前一个节点指向新节点
if (pos === 0) {
newNode.next = this.__head
this.__head = newNode
} else {
let index = 0
let currentNode = this.__head
let prevNode = null
while (index++ < pos) {
prevNode = currentNode
currentNode = currentNode.next
}
newNode.next = currentNode
prevNode.next = newNode
}
this.__length++
return true
}
get方法实现
通过下标位置查找对应的节点信息
/**
* 返回指定下标的节点
* @param {number} pos 链表下标
*/
get(pos) {
// 临界值判断
if (pos < 0 || pos >= this.size()) { return null }
// 定义变量接收当前节点信息
let currentNode = this.__head
// 遍历获取到符合条件的节点信息
let index = 0
while (index++ < pos) {
currentNode = currentNode.next
}
return currentNode.node
}
indexOf 方法实现
/**
* 根据节点信息返回下标值
* @param {*} node 节点信息
*/
indexOf(node) {
let currentNode = this.__head
// 定义下标
let index = 0
// 遍历节点相等时 返回对应的下标
while (currentNode) {
if (currentNode.node === node) {
return index
}
currentNode = currentNode.next
index++
}
}
update方法的实现
/**
* 修改链表指定下标
* @param {number} pos 要修改的下标
* @param {*} node 修改传递的值
* @returns 修改后的值
*/
update(pos, node) {
// 越界判断
if (pos < 0 || pos >= this.size()) { return false }
let currentNode = this.__head
let index = 0
// 遍历找到对应下标的数据
while (index++ < pos) {
currentNode = currentNode.next
}
// 更新数据并返回
return currentNode.node = node
}
removeAt 方法实现
/**
* 删除给定下标的数据
* @param {number} pos 要删除的下标指针
*/
removeAt(pos) {
// 临界值判断
if (pos < 0 || pos >= this.size()) { return null }
let currentNode = this.__head
// 为 0 时 直接操作 head 即可
if (pos === 0) {
this.__head = currentNode.next
} else {
// 不为 0 时 需要记录当前的及上一个数据
let prevNode = null
let index = 0
while (index++ < pos) {
prevNode = currentNode
currentNode = currentNode.next
}
// 将上一个数据的 next 指向当前的 next
prevNode.next = currentNode.next
}
// 删除成功后 长度 -1
this.__length -= 1
// 返回被删除的数据
return currentNode.node
}
remove方法实现
/**
* 删除给定数据
* @param {*} node 传递的节点信息
*/
remove(node) {
return this.removeAt(this.indexOf(node))
}
其他方法
// 是否为空
isEmpty() {
return this.__length === 0
}
// 当前链表大小
size() {
return this.__length
}
// 字符串输出
toString() {
let currentNode = this.__head
let result = ''
while (currentNode) {
result += currentNode.node + ' '
currentNode = currentNode.next
}
return result
}
下面附上完整的
/**
* 节点
*/
class Node {
constructor(node) {
this.node = node;
this.next = null
}
}
class Linked {
constructor() {
this.__head = null
this.__length = 0
}
/**
* 向列表后添加
* @param {*} node 节点
*/
append(node) {
// 1.创建节点
const newNode = new Node(node)
// 判断当前链表是否是第一个节点
if (this.isEmpty()) {
this.__head = newNode
} else {
// 找最后一个节点
let currentNode = this.__head
while (currentNode.next) {
currentNode = currentNode.next
}
// 最后一个节点的 next 指向最新节点
currentNode.next = newNode
}
// 节点长度++
this.__length++
}
/**
* 指定位置插入节点
* @param {number} pos 要插入的位置 0 - 当前链表长度
* @param {*} node 要插入的节点
*/
insert(pos, node) {
// 对下标判断
if (pos < 0 || pos > this.size()) { return false }
// 创建节点
const newNode = new Node(node)
// 根据位置插入数据 区分为 0 跟不为 0
if (pos === 0) {
newNode.next = this.__head
this.__head = newNode
} else {
let index = 0
let currentNode = this.__head
let prevNode = null
while (index++ < pos) {
prevNode = currentNode
currentNode = currentNode.next
}
newNode.next = currentNode
prevNode.next = newNode
}
this.__length++
return true
}
/**
* 返回指定下标的节点
* @param {number} pos 链表下标
*/
get(pos) {
// 临界值判断
if (pos < 0 || pos >= this.size()) { return null }
let currentNode = this.__head
let index = 0
while (index++ < pos) {
currentNode = currentNode.next
}
return currentNode.node
}
/**
* 根据节点信息返回下标值
* @param {*} node 节点信息
*/
indexOf(node) {
let currentNode = this.__head
let index = 0
while (currentNode) {
if (currentNode.node == node) {
return index
}
currentNode = currentNode.next
index++
}
}
/**
* 修改链表指定下标
* @param {number} pos 要修改的下标
* @param {*} node 修改传递的值
* @returns 修改后的值
*/
update(pos, node) {
// 越界判断
if (pos < 0 || pos >= this.size()) { return false }
let currentNode = this.__head
let index = 0
// 遍历找到对应下标的数据
while (index++ < pos) {
currentNode = currentNode.next
}
// 更新数据并返回
return currentNode.node = node
}
/**
* 删除给定下标的数据
* @param {number} pos 要删除的下标指针
*/
removeAt(pos) {
// 临界值判断
if (pos < 0 || pos >= this.size()) { return null }
let currentNode = this.__head
// 为 0 时 直接操作 head 即可
if (pos === 0) {
this.__head = currentNode.next
} else {
// 不为 0 时 需要记录当前的及上一个数据
let prevNode = null
let index = 0
while (index++ < pos) {
prevNode = currentNode
currentNode = currentNode.next
}
// 将上一个数据的 next 指向当前的 next
prevNode.next = currentNode.next
}
// 删除成功后 长度 -1
this.__length -= 1
// 返回被删除的数据
return currentNode.node
}
/**
* 删除给定数据
* @param {*} node 传递的节点信息
*/
remove(node) {
return this.removeAt(this.indexOf(node))
}
isEmpty() {
return this.__length === 0
}
size() {
return this.__length
}
toString() {
let currentNode = this.__head
let result = ''
while (currentNode) {
result += currentNode.node + ' '
currentNode = currentNode.next
}
return result
}
}