定义链表
LinkedList.ts
interface ILinkedList<T> {
indexOf(value: T): number;
append(value: T): void;
remove(value: T): T | null;
insert(value: T, position: number): boolean;
removeAt(position: number): T | null;
get(position: number): T | null;
update(position: number, element: T): boolean;
isEmpty(): boolean;
traverse(): void;
get length(): number;
}
class ListNode<T> {
val: T;
next: ListNode<T> | null;
constructor(val: T, next?: ListNode<T> | null) {
this.val = val;
this.next = next == undefined ? null : next;
}
}
class LinkedList<T> implements ILinkedList<T> {
head: ListNode<T> | null = null;
size: number = 0;
get length(): number {
return this.size;
}
indexOf(value: T): number {
let index = 0;
let current = this.head;
while (current) {
if (current.val == value) {
return index;
}
current = current.next;
index++;
}
return -1;
}
append(value: T): void {
// 创建一个新节点
const newNode = new ListNode<T>(value);
// 将节点追加到链表后
if (!this.head) {
// 如果链表为空
this.head = newNode;
} else {
// 链表不为空,找到最后一个元素(最后一个节点的next为)
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
this.size++;
}
insert(value: T, position: number): boolean {
if (position < 0 || position > this.size) return false;
// 创建节点
const newNode = new ListNode<T>(value);
if (position == 0) {
newNode.next = this.head;
this.head = newNode;
} else {
// 找到position对应节点的前一个节点
let index = 0;
let previous = this.head;
while (index++ < position - 1) {
previous = previous!.next;
}
newNode.next = previous!.next;
previous!.next = newNode;
}
this.size++;
return true;
}
// 空值合并运算符( ?? )是一个逻辑操作符,如果左侧的表达式为 null 或者 undefined 时,返回其右侧表达式,否则返回左侧表达式
removeAt(position: number): T | null {
if (position < 0 || position >= this.size) return null;
let removeVal: T | null = null;
if (position == 0) {
removeVal = this.head?.val ?? null;
this.head = this.head?.next ?? null;
} else {
// 找到position对应节点的前一个节点
let index: number = 0;
let previous = this.head;
while (index++ < position - 1) {
previous = previous!.next;
}
// 因为之前对position进行范围判断,所以previous和previous.next一定存在
removeVal = previous!.next!.val;
previous!.next = previous!.next!.next ?? null;
}
this.size--;
return removeVal;
}
get(position: number): T | null {
if (position < 0 || position >= this.size) return null;
let index = 0;
let current = this.head;
while (index++ < position) {
current = current!.next;
}
return current!.val;
}
update(position: number, element: T): boolean {
if (position < 0 || position >= this.size) return false;
let index = 0;
let current = this.head;
while (index++ < position) {
current = current!.next;
}
current!.val = element;
return true;
}
remove(value: T): T | null {
const index = this.indexOf(value);
return this.removeAt(index);
}
isEmpty(): boolean {
return this.size == 0;
}
traverse(): void {
let values: T[] = [];
let current = this.head;
while (current) {
values.push(current.val);
current = current.next;
}
console.log(values.join("->"));
}
}
// test
const linkedList = new LinkedList<string>();
linkedList.append("aa");
linkedList.append("bb");
linkedList.append("cc");
linkedList.traverse();
linkedList.insert("head", 0);
linkedList.insert("middle", 2);
linkedList.insert("end", 5);
linkedList.traverse();
console.log(linkedList.removeAt(0));
linkedList.traverse();
console.log(linkedList.removeAt(3));
linkedList.traverse();
console.log(linkedList.removeAt(3));
linkedList.traverse();
console.log(linkedList.get(0));
console.log(linkedList.get(1));
console.log(linkedList.get(2));
linkedList.update(1, "11");
linkedList.traverse();
console.log(linkedList.indexOf("11"));
console.log(linkedList.isEmpty());
console.log(linkedList.remove("11"));
console.log(linkedList.remove("aa"));
console.log(linkedList.remove("bb"));
console.log(linkedList.isEmpty());
linkedList.traverse();
应用
链表反转
class ListNode<T> {
val: T;
next: ListNode<T> | null;
constructor(val: T, next?: ListNode<T> | null) {
this.val = val;
this.next = next == undefined ? null : next;
}
}
// 反转链表
function ReverseLinkedList(head: ListNode<number> | null): ListNode<number> | null {
// 一个节点或者无节点可以直接返回
if (head == null || head.next == null) return head;
let cur: ListNode<number> | null = head;
let pre: ListNode<number> | null = null;
while (cur) {
let next = cur.next; // 记录cur的下一个节点
cur.next = pre; // 反方向链接 (以头节点为例,此时头结点已经摘出来,它的下个节点的信息保存在next中)
// 将pre 和 cur依次向后移动
pre = cur;
cur = next;
}
return pre;
}