链表的定义
链表 :用链式存储实现的线性表。
链式存储:在内存中,不仅存储当前元素的信息,还存储前继或后继结点的地址。通过地址实现元素与元素之间的关系。
单链表、带头链表(头结点链表)、双向链表、循环链表的基础定义
1. 单链表(Singly Linked List)
定义 :每个节点包含数据域和一个指向后继节点的指针,最后一个节点的指针为nullptr。特点:只能从表头向表尾遍历,插入 / 删除需修改前驱节点的指针。
// 节点结构
template <typename T>
struct SinglyNode {
T data; // 数据域
SinglyNode<T>* next; // 指向后继节点的指针
// 构造函数
SinglyNode(const T& val) : data(val), next(nullptr) {}
};
// 单链表类(不带头节点)
template <typename T>
class SinglyLinkedList {
private:
SinglyNode<T>* head; // 头指针(指向第一个节点)
public:
SinglyLinkedList() : head(nullptr) {}
// 其他成员函数(插入、删除、遍历等)
};
2. 带头链表(头结点链表,Singly Linked List with Head Node)
定义 :在单链表的基础上增加一个头结点 (不存储实际数据),头指针指向头结点,头结点的next指向第一个实际节点。特点:统一空表和非空表的操作逻辑(无需特殊处理头指针),简化插入 / 删除代码。
// 节点结构(同单链表)
template <typename T>
struct HeadNode {
T data; // 头结点可闲置或存长度等信息
HeadNode<T>* next;
HeadNode() : next(nullptr) {} // 头结点默认构造
};
// 带头链表类
template <typename T>
class HeadLinkedList {
private:
HeadNode<T>* head; // 头指针(指向头结点)
public:
HeadLinkedList() {
head = new HeadNode<T>(); // 初始化头结点
}
// 其他成员函数
};
3. 双向链表(Doubly Linked List)
定义 :每个节点包含数据域、指向后继节点的指针(next)和指向前驱节点的指针(prev)。特点:可双向遍历,插入 / 删除时需同时修改前驱和后继的指针,但操作更灵活。
// 节点结构
template <typename T>
struct DoublyNode {
T data; // 数据域
DoublyNode<T>* prev; // 指向前驱节点
DoublyNode<T>* next; // 指向后继节点
DoublyNode(const T& val) : data(val), prev(nullptr), next(nullptr) {}
};
// 双向链表类(可带头结点,此处示例带头结点)
template <typename T>
class DoublyLinkedList {
private:
DoublyNode<T>* head; // 头指针(指向头结点)
public:
DoublyLinkedList() {
head = new DoublyNode<T>(T()); // 头结点
head->prev = head->next = head; // 若为循环双向链表则指向自身
}
// 其他成员函数
};
4. 循环链表(Circular Linked List)
定义 :最后一个节点的指针不指向nullptr,而是指向表头(单循环)或头结点(带头循环),形成闭环。双向循环链表中,头结点的prev指向尾节点。特点:可从任意节点遍历整个链表,适合实现环形队列等场景。
(1)单循环链表(带头结点)
template <typename T>
struct CircSinglyNode {
T data;
CircSinglyNode<T>* next;
CircSinglyNode(const T& val) : data(val), next(nullptr) {}
};
template <typename T>
class CircSinglyLinkedList {
private:
CircSinglyNode<T>* head; // 头结点
public:
CircSinglyLinkedList() {
head = new CircSinglyNode<T>(T());
head->next = head; // 头结点next指向自身(空表)
}
// 插入节点后,尾节点next需指向head
};
(2)双向循环链表(带头结点)
// 节点结构同双向链表的DoublyNode
template <typename T>
class CircDoublyLinkedList {
private:
DoublyNode<T>* head;
public:
CircDoublyLinkedList() {
head = new DoublyNode<T>(T());
head->prev = head; // 头结点prev指向自身
head->next = head; // 头结点next指向自身
}
// 尾节点next指向head,head->prev指向尾节点
};
核心区别总结
| 类型 | 指针方向 | 尾节点指针 | 核心优势 |
|---|---|---|---|
| 单链表 | 单向(next) | nullptr | 结构简单,内存开销小 |
| 带头链表 | 单向(next) | nullptr | 统一操作逻辑,简化代码 |
| 双向链表 | 双向(prev+next) | nullptr | 双向遍历,插入删除更灵活 |
| 循环链表 | 单向 / 双向 | 指向表头 / 头结点 | 环形遍历,适合循环场景 |
单链表的功能实现
定义

头插

遍历

按值查找

删除任意位置之后的元素

双向链表

头插

按值查找

任意位置之后插入元素
