简介
本文基于理解JavaScript中的数据结构(链表)一文,进行改造完善。对于对应方法的理解可参考该文中的图解。
实现的链表方法和属性
- headNode: 头节点
- endNode: 尾节点
- length: 长度
- append(val): 末尾添加值
- preAppend(val): 链表开头添加值
- getIndexVal(index): 根据索引查询值
- insert(val, index): 插入
- remove(index): 删除
- reverse(): 反转
声明节点类及链表类
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class LinkedList {
constructor() {
/** 初始值头节点 */
this.headNode = null;
/** 初始值尾节点 */
this.endNode = null;
/** 初始值长度 */
this.length = 0;
}
}
工具方法
/**
* 得指定index node和前一个node
* @param {*} index 当前index
* @param {*} that 对象实例
* @returns
*/
static getPreAndCurrent(index, that) {
let preNode = null;
let currNode = null;
if (index <= that.length) {
if (index !== 0) {
preNode = that.getIndexVal(index - 1);
}
currNode = that.getIndexVal(index);
}
return {
preNode,
currNode,
};
}
/**
* 超界
* @param {*} index 当前index
* @param {*} that 对象实例
*/
static IndexOut(index, that) {
if (index < 0 || index >= that.length) {
throw new Error("下标超出");
}
}
功能方法
append(val) {
const node = new Node(val);
/**
* 链表为空时,头和尾都是当前添加的node
* 链表不为空时,尾节点添加next为当前节点,然后设置新的尾节点尾当期节点
*/
if (!this.headNode) {
this.headNode = node;
this.endNode = node;
} else {
this.endNode.next = node;
this.endNode = node;
}
this.length++;
}
preAppend(val) {
const node = new Node(val);
node.next = this.headNode;
this.headNode = node;
this.length++;
}
/**
* 根据索引的值
*/
getIndexVal(index) {
let count = 0;
let currentNode = this.headNode;
while (count < index) {
currentNode = currentNode.next;
count++;
}
return currentNode;
}
/** 插入 */
insert(val, index) {
if (index >= this.length) {
this.append(val);
} else {
const node = new Node(val);
const { preNode, currNode } = LinkedList.getPreAndCurrent(index, this);
if (index === 0) {
this.headNode = node;
} else {
preNode.next = node;
}
node.next = currNode;
this.length++;
}
}
/** 删除 */
remove(index) {
LinkedList.IndexOut(index, this);
const { preNode } = LinkedList.getPreAndCurrent(index, this);
const nextNode = this.getIndexVal(index + 1);
if (index === 0) {
this.headNode = nextNode;
} else {
preNode.next = nextNode;
}
this.length--;
/** index为之前的被删除的,this.length已经--,现在this.length等于传入的index */
if (index === this.length) {
/** 取新链表的最后一个 */
this.endNode = this.getIndexVal(this.length - 1);
}
}
/** 反转 */
reverse() {
let previousNode = null;
let currentNode = this.headNode;
while (currentNode !== null) {
let nextNode = currentNode.next;
currentNode.next = previousNode;
previousNode = currentNode;
currentNode = nextNode;
}
this.headNode = previousNode;
}
完整代码
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class LinkedList {
constructor() {
this.headNode = null;
this.endNode = null;
this.length = 0;
}
static getPreAndCurrent(index, that) {
let preNode = null;
let currNode = null;
if (index <= that.length) {
if (index !== 0) {
preNode = that.getIndexVal(index - 1);
}
currNode = that.getIndexVal(index);
}
return {
preNode,
currNode,
};
}
/**
* 超界
* @param {*} index 当前index
* @param {*} that 对象实例
*/
static IndexOut(index, that) {
if (index < 0 || index >= that.length) {
throw new Error("下标超出");
}
}
append(val) {
const node = new Node(val);
/**
* 链表为空时,头和尾都是当前添加的node
* 链表不为空时,尾节点添加next为当前节点,然后设置新的尾节点尾当期节点
*/
if (!this.headNode) {
this.headNode = node;
this.endNode = node;
} else {
this.endNode.next = node;
this.endNode = node;
}
this.length++;
}
preAppend(val) {
const node = new Node(val);
node.next = this.headNode;
this.headNode = node;
this.length++;
}
/**
* 根据索引的值
*/
getIndexVal(index) {
let count = 0;
let currentNode = this.headNode;
while (count < index) {
currentNode = currentNode.next;
count++;
}
return currentNode;
}
/** 插入 */
insert(val, index) {
if (index >= this.length) {
this.append(val);
} else {
const node = new Node(val);
const { preNode, currNode } = LinkedList.getPreAndCurrent(index, this);
if (index === 0) {
this.headNode = node;
} else {
preNode.next = node;
}
node.next = currNode;
this.length++;
}
}
/** 删除 */
remove(index) {
LinkedList.IndexOut(index, this);
const { preNode } = LinkedList.getPreAndCurrent(index, this);
const nextNode = this.getIndexVal(index + 1);
if (index === 0) {
this.headNode = nextNode;
} else {
preNode.next = nextNode;
}
this.length--;
/** index为之前的被删除的,this.length已经--,现在this.length等于传入的index */
if (index === this.length) {
/** 取新链表的最后一个 */
this.endNode = this.getIndexVal(this.length - 1);
}
}
/** 反转 */
reverse() {
let previousNode = null;
let currentNode = this.headNode;
while (currentNode !== null) {
let nextNode = currentNode.next;
currentNode.next = previousNode;
previousNode = currentNode;
currentNode = nextNode;
}
this.headNode = previousNode;
}
}
const testLinked = new LinkedList();
testLinked.append(2);
testLinked.append(4);
testLinked.preAppend(1);
testLinked.insert("insert", 4);
testLinked.remove(2);
console.log(testLinked);
console.log(testLinked.getIndexVal(3), testLinked.endNode);