// 定义链表元素类
function Linked_node(val) {
this.val = val;
this.next = null;
}
// 定义链表类
function Linked_list() {
this.length = 0;
this.head = null;
}
// 给链表类添加方法
// 方法一(通过节点的索引查找对应的节点)
Linked_list.prototype.getNodeByIndex = function (index) {
// 先判断错误的值(val不是数字,val小于0,val大于链表的长度)
if((!Number(index) && index != 0) || index < 0 || index >= this.length) return null;
// 定义初始值为头节点
let node = this.head;
// 筛选找到对应的节点
while (index) {
node = node.next;
index -= 1;
}
return node;
}
// 方法二(为链表添加节点)
Linked_list.prototype.addNode = function (val) {
if (Array.isArray(val)) {
// 先把新节点的数据处理一下
let nodeList = [];
// 生成节点列表
val.forEach((item) => {
nodeList.push(new Linked_node(item))
})
// 遍历新节点列表使得他们形成新的链表段
nodeList.forEach((item, i) => {
if (i == nodeList.length - 1) {
item.next = null;
} else {
item.next = nodeList[i+1];
}
})
if(this.head) { // 存在头节点的老链表
let prevNode = this.getNodeByIndex(this.length - 1);
// 连接两个链表
prevNode.next = nodeList[0] || null;
} else { // 新链表
// 只需要给定头节点即可连接整个链表
this.head = nodeList[0] || null;
}
this.length += nodeList.length;
} else {
// 创建新节点
const node = new Linked_node(val);
if(this.head) { // 当链表有值的时候
// 得到当前的最后一个节点
let prevNode = this.getNodeByIndex(this.length - 1);
// 把当前最后一个节点的next值赋值成新添加的节点
prevNode.next = node;
} else { // 当链表没值的时候
// 把当前节点作为头节点,同时也是尾节点
this.head = node;
}
// 每次添加一个新节点的时候链表长度加1
this.length += 1;
}
}
// 方法三(为链表添加节点,index->从哪开始,count->删除几个,newNodes->替换的节点)
Linked_list.prototype.spliceNode = function (index, count = 0, newNodes = []) {
// 先把新节点的数据处理一下
let nodeList = [];
// 生成节点列表
newNodes.forEach((item) => {
nodeList.push(new Linked_node(item))
})
// 遍历新节点列表使得他们形成新的链表段
nodeList.forEach((item, i) => {
if (i == nodeList.length - 1) {
item.next = null;
} else {
item.next = nodeList[i+1];
}
})
// 定义遍历的最终点
let lastIndex = index + count;
let firstPrevNode = this.head;
let lastNode = this.head;
let lastNextNode = this.head;
// 找到要删除节点段的首个节点的上一个节点
firstPrevNode = this.getNodeByIndex(index - 1);
// 找到要删除节点段的最后一个节点
lastNode = this.getNodeByIndex(lastIndex);
// 找到要删除节点段的最后一个节点的后一个节点
lastNextNode = this.getNodeByIndex(lastIndex + 1);
if (nodeList.length) { // 如果有新插入的新节点
// 断开原来的链表的尾节点
lastNode.next = null;
// 让新的节点的首节点连接链表的断处,同时断开原来链表的首节点
firstPrevNode.next = nodeList[0];
// 让新的节点的尾节点连接链表的断处
nodeList[nodeList.length - 1] = lastNextNode;
// 改变链表的长度
this.length = this.length - count + newNodes.length;
} else {
// 如果不删除节点
if(index == lastIndex) return;
// 断开原来的链表的尾节点
lastNode.next = null;
// 断开的链表去除删除的部分收尾再次连接
firstPrevNode.next = lastNextNode;
// 改变链表的长度
this.length = this.length - count;
}
}
// 方法四(通过节点值查找对应节点)
Linked_list.prototype.find = function (val) {
let node = this.head;
while (node) {
if (node.val == val) return node;
node = node.next;
}
return null;
}
// 使用方法
let linkedList = new Linked_list();
linkedList.addNode(10);
linkedList.addNode(20);
linkedList.addNode([5, 7, 9]);
JS 手写单向链表
于 2022-10-24 23:03:31 首次发布