js实现单向链表
单向链表的基本概念
单向链表是一种线性数据结构,由多个节点组成,每个节点包含数据和指向下一个节点的指针。与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针链接起来。
实现单向链表的步骤
定义节点类
每个节点需要存储数据和指向下一个节点的引用。可以使用类或构造函数实现。
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
定义链表类
链表类需要管理节点的添加、删除和遍历等操作。
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
}
添加节点到链表末尾
add(data) {
const node = new Node(data);
if (!this.head) {
this.head = node;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
}
this.size++;
}
在指定位置插入节点
insertAt(data, index) {
if (index < 0 || index > this.size) {
return false;
}
const node = new Node(data);
if (index === 0) {
node.next = this.head;
this.head = node;
} else {
let current = this.head;
let prev;
let i = 0;
while (i < index) {
prev = current;
current = current.next;
i++;
}
node.next = current;
prev.next = node;
}
this.size++;
}
从链表中移除指定位置的节点
removeFrom(index) {
if (index < 0 || index >= this.size) {
return null;
}
let current = this.head;
if (index === 0) {
this.head = current.next;
} else {
let prev;
let i = 0;
while (i < index) {
prev = current;
current = current.next;
i++;
}
prev.next = current.next;
}
this.size--;
return current.data;
}
打印链表中的所有元素
print() {
let current = this.head;
let result = '';
while (current) {
result += current.data + ' -> ';
current = current.next;
}
result += 'null';
console.log(result);
}
完整代码示例
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
add(data) {
const node = new Node(data);
if (!this.head) {
this.head = node;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
}
this.size++;
}
insertAt(data, index) {
if (index < 0 || index > this.size) {
return false;
}
const node = new Node(data);
if (index === 0) {
node.next = this.head;
this.head = node;
} else {
let current = this.head;
let prev;
let i = 0;
while (i < index) {
prev = current;
current = current.next;
i++;
}
node.next = current;
prev.next = node;
}
this.size++;
}
removeFrom(index) {
if (index < 0 || index >= this.size) {
return null;
}
let current = this.head;
if (index === 0) {
this.head = current.next;
} else {
let prev;
let i = 0;
while (i < index) {
prev = current;
current = current.next;
i++;
}
prev.next = current.next;
}
this.size--;
return current.data;
}
print() {
let current = this.head;
let result = '';
while (current) {
result += current.data + ' -> ';
current = current.next;
}
result += 'null';
console.log(result);
}
}
// 使用示例
const list = new LinkedList();
list.add(1);
list.add(2);
list.add(3);
list.print(); // 输出: 1 -> 2 -> 3 -> null
list.insertAt(4, 1);
list.print(); // 输出: 1 -> 4 -> 2 -> 3 -> null
list.removeFrom(2);
list.print(); // 输出: 1 -> 4 -> 3 -> null
单向链表的常见操作
查找节点
find(data) {
let current = this.head;
while (current) {
if (current.data === data) {
return current;
}
current = current.next;
}
return null;
}
判断链表是否为空
isEmpty() {
return this.size === 0;
}
获取链表长度
getSize() {
return this.size;
}
反转链表
reverse() {
let current = this.head;
let prev = null;
let next = null;
while (current) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
this.head = prev;
}
注意事项
- 链表的操作需要注意边界条件,例如空链表或只有一个节点的链表。
- 插入和删除操作需要正确处理指针的指向,避免内存泄漏或丢失节点。
- 链表的遍历通常使用循环实现,注意循环的终止条件。







