707. 设计链表
707. 设计链表
/**
* 双链表
* 使用虚拟表头是为了简化对实际结点的操作,将所有操作会统一为在链表中间修改结点
*/
class MyLinkedList {
head = new LinkNode(null); // 表头。虚拟表头
tail = new LinkNode(null); // 表尾。虚拟表尾
len = 0; // 链表的长度
constructor() {
// 将两个虚拟头尾相连,即默认的空链表
this.head.next = this.tail;
this.tail.prev = this.head;
}
getNode(index: number): LinkNode {
// 如果超过了链表长度
// 因为 index 从 0 开始,所以是 >= len
// 返回 -1
if (index >= this.len) {
return null;
}
// 获取 index 处的 node
let currentNode = this.head;
for (let i = 0; i <= index; i += 1) {
currentNode = currentNode.next;
}
return currentNode;
}
get(index: number): number {
const node = this.getNode(index)
if (!node) {
return -1;
}
return node.val;
}
addAtHead(val: number): void {
const oldHead = this.head.next; // 旧的头结点
this.insertBefore(oldHead, val);
}
addAtTail(val: number): void {
const oldTail = this.tail; // 虚拟尾结点
this.insertBefore(oldTail, val)
}
addAtIndex(index: number, val: number): void {
// 如果大于链表长度
// 不处理
if (index > this.len) {
return;
}
// 等于链表长度
// 插入尾部
if (index === this.len) {
this.addAtTail(val);
} else {
const nextNode = this.getNode(index); // 旧的结点
this.insertBefore(nextNode, val)
}
}
deleteAtIndex(index: number): void {
const oldNode = this.getNode(index); // 旧的结点
// 如果能获取到结点说明有效,开始删除
if (oldNode) {
const prevNode = oldNode.prev
const nextNode = oldNode.next
// 将 oldNode 的指针置为 null
oldNode.prev = null;
oldNode.next = null;
// 将 prevNode 和 nextNode 连起来
prevNode.next = nextNode
nextNode.prev = prevNode
this.len -= 1
}
}
/**
* 在前面插入
*/
insertBefore(nextNode: LinkNode, val: number) {
const prevNode = nextNode.prev; // 上一个结点
const newNode = new LinkNode(val); // 新插入的结点
// 在旧的结点之前插入
nextNode.prev = newNode;
newNode.next = nextNode;
// 调整上一个结点的指针
prevNode.next = newNode;
newNode.prev = prevNode;
this.len += 1
}
}
/**
* 链表结点
*/
class LinkNode {
val = null; // 当前结点
next = null; //下一个结点
prev = null; // 上一个结点
constructor(val: number) {
this.val = val;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* var obj = new MyLinkedList()
* var param_1 = obj.get(index)
* obj.addAtHead(val)
* obj.addAtTail(val)
* obj.addAtIndex(index,val)
* obj.deleteAtIndex(index)
*/