链表

逐步演示 C++ 指针实现的单向链表。

所有内容均在此浏览器中模拟,不会发送到任何服务器。

值

创建新节点

创建新节点

n_ = 0
游离节点
42
0x1010指针
cabeza_
nullptr — 空链表
  • 当前
  • 指针

第 1 / 46 步

代码

#include <iostream>
using namespace std;
class Nodo { // 节点保存数据和指向下一个节点的指针
private: // 私有属性:只有方法可以访问
int dato;
Nodo* siguiente;
public:
Nodo(int d) : dato(d), siguiente(nullptr) {}
int getDato() const { return dato; }
Nodo* getSiguiente() const { return siguiente; }
void setDato(int d) { dato = d; }
void setSiguiente(Nodo* s) { siguiente = s; }
};
class Lista {
Nodo* cabeza_; // 链表的第一个节点
int n_; // 节点数量
public:
Lista() : cabeza_(nullptr), n_(0) {}
// Constructor de copia (no se anima)
Lista(const Lista& otra) : cabeza_(nullptr), n_(0) {
for (Nodo* p = otra.cabeza_; p != nullptr; p = p->getSiguiente())
insertarFinal(p->getDato());
}
// Destructor (no se anima)
~Lista() {
while (cabeza_ != nullptr) {
Nodo* temp = cabeza_;
cabeza_ = cabeza_->getSiguiente();
delete temp;
}
}
void insertarElemento(int valor) { // 头部插入:O(1)
Nodo* nuevo = new Nodo(valor); // 创建节点
nuevo->setSiguiente(cabeza_); // 新节点指向原来的头节点
cabeza_ = nuevo; // cabeza_ 现在指向新节点
n_++;
}
void insertarFinal(int valor) { // 尾部插入:O(n)
Nodo* nuevo = new Nodo(valor); // 创建节点
if (cabeza_ == nullptr) { // 链表为空?
cabeza_ = nuevo;
} else {
Nodo* actual = cabeza_;
while (actual->getSiguiente() != nullptr) { // 遍历到尾节点
actual = actual->getSiguiente();
}
actual->setSiguiente(nuevo); // 将新节点链接到尾节点之后
}
n_++;
}
// Devuelve la posición (0-based) o -1 si no existe
int buscar(int valor) const {
Nodo* actual = cabeza_;
int indice = 0;
while (actual != nullptr) {
if (actual->getDato() == valor) return indice; // 比较数据
actual = actual->getSiguiente();
indice++;
}
return -1; // 未找到
}
void eliminarNodo(int indice) {
if (indice < 0 || indice >= n_) return; // 校验索引
Nodo* anterior = nullptr;
Nodo* actual = cabeza_;
for (int i = 0; i < indice; i++) {
anterior = actual;
actual = actual->getSiguiente();
}
if (anterior == nullptr)
cabeza_ = actual->getSiguiente(); // 它是头节点
else
anterior->setSiguiente(actual->getSiguiente()); // 跳过该节点
delete actual; // 释放内存
n_--;
}
void invertirLista() {
Nodo* anterior = nullptr;
Nodo* actual = cabeza_;
while (actual != nullptr) {
Nodo* siguiente = actual->getSiguiente(); // 保存下一个节点
actual->setSiguiente(anterior); // 反转链接
anterior = actual;
actual = siguiente;
}
cabeza_ = anterior; // 最后一个节点成为头节点
}
void imprimirLista() const {
for (Nodo* p = cabeza_; p != nullptr; p = p->getSiguiente()) { // 遍历链表
cout << p->getDato();
if (p->getSiguiente() != nullptr) cout << " -> "; // 值之间的分隔符
}
cout << endl;
}
};
int main() {
Lista lista;
lista.insertarElemento(3);
lista.insertarElemento(6);
lista.insertarElemento(9);
lista.imprimirLista(); // 9 -> 6 -> 3
lista.insertarFinal(1);
lista.eliminarNodo(lista.buscar(6));
lista.imprimirLista(); // 9 -> 3 -> 1
lista.invertirLista();
lista.imprimirLista(); // 1 -> 3 -> 9
return 0;
}

这个链表可视化工具展示由C++节点和指针构成的单链表是如何真正工作的。你可以生成最多12个节点的链表,把插入、删除、查找、反转或打印等操作加入队列,并逐步回放。每一步都会高亮对应的C++代码行,标出当前节点,并画出指针,包括 nullptr 以及重新链接时被分离出来的节点。它有助于理解从头节点开始的遍历、反转时链接如何变化,以及头插与尾插的区别。一切都在你的浏览器中模拟。

使用方法

  1. 选择节点数量,点击“新建链表”生成带随机值的链表。
  2. 选择一种操作,如需数值就输入;插入时选择放在头部还是尾部。
  3. 点击“添加”把操作作为标签加入队列,然后可继续添加任意多个。
  4. 点击“播放”或逐步前进,一边调整速度,一边跟随高亮的代码行。

常见问题

它展示的是哪种链表?
单链表:每个节点保存一个值和指向下一个节点的指针,链表会记录头节点和节点计数。
可以模拟哪些操作?
在头部或尾部插入、删除、查找某个值、反转链表以及打印。你可以串联多个操作,观察每个操作的效果。
代码用什么语言显示?
代码面板显示C++,并在动画的每一步高亮正在执行的行。

相关工具