单向链表
/**
* @desc 单向链表
*/
class Node { // 链表节点
constructor(element) {
this.data = element // 节点数据
this.next = null // 下一个节点的指针
}
}
class NodeList { // 链表
constructor(item) {
this.head = new Node(item); //初始化链表的头节点
}
/**
* @descript 插入元素
* @param {需要插入的元素} newItem
* @param {插入到某一个元素之后} beforeItem
*/
insertInNext(newItem, beforeItem) {
let newNode = new Node(newItem)
if(beforeItem) {
let currNode = this.find(beforeItem)
newNode.next = currNode.next
currNode.next = newNode
} else {
let lastNode = this.findLastNode()
lastNode.next = newNode
}
}
/**
* @description 删除元素
* @param {删除的元素} newItem
*/
remove(item) {
let preNode = this.findPreNode(item)
if(preNode.next != null) {
preNode.next = preNode.next.next
}
}
/**
* @description 查找元素的节点
* @param {查找的元素} item
*/
find(item) { // 根据元素查找节点
let currNode = this.head;
while (currNode.element !== item && currNode) {
if (currNode.next) {
currNode = currNode.next;
} else {
currNode = null;
}
}
return currNode;
}
/**
* @description 查找最后一个节点
*/
findLastNode() {
let currNode = this.head
while(currNode.next) {
currNode = currNode.next
}
return currNode
}
/**
* @description 查找元素的前一个节点
* @param {查找的元素} item
*/
findPreNode(item) {
let currNode = this.head
while(currNode && currNode.next.element !== item) {
if(currNode.next) {
currNode = currNode.next
} else {
currNode = null
}
}
return currNode
}
toString() {
let currNode = this.head
let strList = []
while(currNode.next) {
strList.push(JSON.stringify(currNode.element))
currNode = currNode.next
}
strList.push(JSON.stringify(currNode.element))
return strList.join('->')
}
}
let ming = { name: '小明', score: 100 },
hongs = { name: '小红', score: 88 },
jun = { name: '小军', score: 66 },
li = { name: '小李', score: 50 };
let nList = new NodeList(ming);
// nList.insertInNext(hongs);
// nList.insertInNext(li);
// nList.insertInNext(jun, hongs);
console.log(nList);
双向链表
class Node {
constructor(data) {
// data为当前节点所储存的数据
this.data = data
// next指向下一个节点
this.next = null
// prev指向前一个节点
this.prev = null
}
}
class DoublyLinkedList {
constructor() {
// 双向链表的开头
this.head = null
// 双向链表的结尾
this.tail = null
}
add(item) {
// 实例化一个节点
let node = new Node(item)
// 如果当前链表还没有头
if(!this.head) {
this.head = node
this.tail = node
}
// 如果当前链表已经有了头,则只需要在尾部加上该节点
else {
node.prev = this.tail
this.tail.next = node
this.tail = node
}
}
addAt(index, item) {
let current = this.head
let counter = 1
let node = new Node(item)
// 如果在头部插入
if(index === 0) {
this.head.prev = node
this.next = this.head
this.head = node
}
// 如果在非头部插入,则需要从头开始找寻插入位置
else {
while(current) {
current = current.next
if(counter === index) {
node.prev = current.prev
current.prev.next = node
node.next = current
current.prev = node
}
counter++
}
}
}
remove(item) {
let current = this.head
while(current) {
// 找到了目标节点
if(current.data === item) {
// 目标链只有当前目标项,即目标节点既是链表头又是链表尾
if(current == this.head && current == this.tail) {
this.head = null
this.tail = null
}
// 目标节点为链表头
else if(current == this.head) {
this.head = this.head.next
this.head.prev = null
}
// 目标节点为链表尾
else if(current == this.tail) {
this.tail = this.tail.prev
this.tail.next = null
}
// 目标节点在链表首尾之间,即中部
else {
current.prev.next = current.next
current.next.prev = current.prev
}
}
current = current.next
}
}
removeAt(index) {
// 都是从头开始遍历
let current = this.head
let counter = 1
// 删除链表头部
if(index === 0) {
this.head = this.head.next
this.head.prev = null
}
else {
while(current) {
current = current.next
// 如果目标节点在链表尾部
if(curent == this.tail) {
this.tail = this.tail.prev
this.tail.next = null
}
else if(counter === index) {
current.prev.next = current.next
current.next.prev = current.prev
break
}
counter++
}
}
}
reverse() {
let current = this.head
let prev = null
while(current) {
let next = current.next
// 前后倒置
current.next = prev
current.prev = next
prev = current
current = next
}
this.tail = this.head
this.head = prev
}
swap(index1, index2) {
// 使index1始终小于index2,方便后面查找交换
if(index1 > index2) {
return this.swap(index2, index1)
}
let current = this.head
let counter = 0
let firstNode
while(current !== null) {
// 找到第一个节点,并储存起来
if(counter === index1) {
firstNode = current
}
// 找到第二个节点,并进行数据交换
else if(counter === index2) {
// ES提供了更简洁的交换数据的方式,这里用传统方式实现更为直观
let temp = current.data
current.data = firstNode.data
firstNode.data = temp
}
current = current.next
counter++
}
return true
}
isEmpty() {
return this.length() < 1
}
length() {
let current = this.head
let counter = 0
while(current !== null) {
counter++
current = current.next
}
return counter
}
traverse(fn){
let current = this.head
while(current !== null) {
fn(current)
current = current.next
}
return true
}
search(item) {
let current = this.head
let counter = 0
while(current) {
if(current.data == item) {
return counter
}
current = current.next
counter++
}
return false
}
}
参考:
单向链表
[前端开发核心知识进阶]