C++ 手写 List 容器:从零开始构建节点类与迭代器
·
以下是从零开始实现 C++ List 容器的完整指南,包含节点类与迭代器实现:
1. 节点类 (ListNode)
链表的基础单元,包含数据和前后指针:
template <typename T>
struct ListNode {
T data; // 存储的数据
ListNode* prev; // 前驱节点指针
ListNode* next; // 后继节点指针
// 构造函数
explicit ListNode(const T& val = T())
: data(val), prev(nullptr), next(nullptr) {}
};
2. 迭代器类 (ListIterator)
实现 STL 兼容的迭代器功能:
template <typename T>
class ListIterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
explicit ListIterator(ListNode<T>* node = nullptr) : current(node) {}
// 解引用操作符
reference operator*() const {
return current->data;
}
// 成员访问操作符
pointer operator->() const {
return &(current->data);
}
// 前置++
ListIterator& operator++() {
current = current->next;
return *this;
}
// 后置++
ListIterator operator++(int) {
ListIterator temp = *this;
++(*this);
return temp;
}
// 前置--
ListIterator& operator--() {
current = current->prev;
return *this;
}
// 后置--
ListIterator operator--(int) {
ListIterator temp = *this;
--(*this);
return temp;
}
// 比较操作符
bool operator==(const ListIterator& other) const {
return current == other.current;
}
bool operator!=(const ListIterator& other) const {
return !(*this == other);
}
private:
ListNode<T>* current; // 当前节点指针
};
3. List 容器实现
整合节点和迭代器完成链表容器:
template <typename T>
class List {
public:
using iterator = ListIterator<T>;
// 构造函数
List() : size_(0) {
// 创建头尾哨兵节点
head = new ListNode<T>();
tail = new ListNode<T>();
head->next = tail;
tail->prev = head;
}
// 析构函数
~List() {
clear();
delete head;
delete tail;
}
// 迭代器访问
iterator begin() { return iterator(head->next); }
iterator end() { return iterator(tail); }
// 插入元素
void push_back(const T& value) {
insert(end(), value);
}
iterator insert(iterator pos, const T& value) {
ListNode<T>* newNode = new ListNode<T>(value);
ListNode<T>* current = pos.current;
newNode->prev = current->prev;
newNode->next = current;
current->prev->next = newNode;
current->prev = newNode;
++size_;
return iterator(newNode);
}
// 删除元素
void pop_back() {
erase(--end());
}
iterator erase(iterator pos) {
ListNode<T>* toDelete = pos.current;
iterator nextIter(toDelete->next);
toDelete->prev->next = toDelete->next;
toDelete->next->prev = toDelete->prev;
delete toDelete;
--size_;
return nextIter;
}
// 清空链表
void clear() {
while (begin() != end()) {
erase(begin());
}
}
// 容器大小
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
private:
ListNode<T>* head; // 头哨兵节点
ListNode<T>* tail; // 尾哨兵节点
size_t size_; // 元素数量
};
4. 使用示例
int main() {
List<int> myList;
// 添加元素
myList.push_back(10);
myList.push_back(20);
myList.push_back(30);
// 遍历输出
for (auto it = myList.begin(); it != myList.end(); ++it) {
std::cout << *it << " ";
}
// 输出: 10 20 30
// 删除元素
auto it = myList.begin();
++it; // 指向第二个元素
myList.erase(it);
// 使用范围for循环
for (int val : myList) {
std::cout << val << " ";
}
// 输出: 10 30
}
关键设计要点
- 哨兵节点技术:头尾哑节点简化边界条件处理
- 双向链表结构:支持双向遍历
- 迭代器分类:符合
std::bidirectional_iterator要求 - 内存管理:
- 节点动态内存分配
- 析构函数自动释放内存
- 时间复杂度:
- 插入/删除:$O(1)$
- 遍历:$O(n)$
此实现遵循 STL 设计规范,可通过添加 const_iterator 和反向迭代器进一步扩展功能。
更多推荐
所有评论(0)