返回

深度剖析STL List底层实现,教你如何轻松使用它

后端

揭秘 STL List:C++ 中高效链表的深入解析

STL List 简介

STL (Standard Template Library) 中的 List 是一个强大的双向链表,提供了一系列高效操作来管理数据集合。它以其插入、删除和查找的效率而闻名,使其成为广泛应用场景的理想选择。

结点类实现

List 底层采用带头双向循环链表结构。结点类是链表的基本构建块,包含三个成员:数据(data)、指向下一个结点(next)和指向前一个结点(prev)的指针。

template <typename T>
struct Node {
  T data;
  Node* prev;
  Node* next;
  
  Node(const T& val) : data(val), prev(nullptr), next(nullptr) {}
};

迭代器类实现

为了方便遍历链表元素,List 提供了迭代器类。它允许您以线性方式访问元素,并提供诸如前进、后退、解引用和取地址等操作。

template <typename T>
struct Iterator {
  Node<T>* node;
  
  Iterator(Node<T>* node) : node(node) {}
  
  Iterator& operator++() {
    node = node->next;
    return *this;
  }
  
  Iterator& operator--() {
    node = node->prev;
    return *this;
  }
  
  T& operator*() {
    return node->data;
  }
  
  T* operator->() {
    return &node->data;
  }
};

函数接口

List 提供了一系列函数接口,涵盖了各种操作:

  • 插入: push_front() 在链表开头插入元素,push_back() 在链表末尾插入元素,insert() 在指定位置插入元素。
  • 删除: pop_front() 删除链表开头元素,pop_back() 删除链表末尾元素,erase() 删除指定位置元素。
  • 访问: front() 返回链表开头元素,back() 返回链表末尾元素,size() 返回链表元素数量,empty() 检查链表是否为空。

应用示例

以下代码示例演示了如何使用 List:

#include <list>

int main() {
  // 创建一个 List
  std::list<int> myList;
  
  // 插入元素
  myList.push_back(1);
  myList.push_front(2);
  
  // 遍历链表
  for (int& x : myList) {
    std::cout << x << " ";
  }
  std::cout << "\n";
  
  // 删除元素
  myList.pop_front();
  myList.erase(myList.begin());
  
  // 再次遍历链表
  for (int& x : myList) {
    std::cout << x << " ";
  }
  std::cout << "\n";
  
  return 0;
}

输出:

2 1 
1

总结

STL List 是一个功能强大的链表实现,提供了高效的数据管理操作。了解它的底层实现可以帮助您充分利用它的优势,编写出高效且优雅的代码。

常见问题解答

  1. List 和 Vector 有什么区别?
    List 是一个双向链表,在插入和删除方面比 Vector 更有效。然而,Vector 在随机访问和顺序遍历方面更快。

  2. 何时应该使用 List?
    List 适用于需要频繁插入和删除元素的场景,例如 LRU 缓存或双向队列。

  3. 如何遍历 List?
    可以通过迭代器或 range-based for 循环遍历 List。

  4. List 是否支持并发访问?
    STL List 不支持并发访问。如果您需要并发访问,请考虑使用 std::concurrent_list

  5. List 中的元素是如何分配内存的?
    List 中的元素在堆上分配内存,并通过指针访问。