链表和数组和列表的区别
在C++中,数组(Array)、**链表(LinkedList)和列表(List,通常指std::list
或std::vector
)**是常用的数据结构,但它们的实现和特性有很大区别。下面我将详细解释它们的区别,并用表格总结。
1. 数组(Array)
数组是一种连续内存存储的静态数据结构,大小固定,支持随机访问。
C++ 示例
int arr[5] = {1, 2, 3, 4, 5}; // 静态数组
std::array<int, 5> stdArr = {1, 2, 3, 4, 5}; // C++11 std::array
特点:
- 内存连续,访问速度快(O(1))。
- 大小固定,不能动态增长。
- 插入/删除效率低(需要移动元素,O(n))。
2. 链表(LinkedList)
链表是一种非连续内存存储的动态数据结构,通过指针连接节点,支持高效插入/删除。
C++ 示例(单链表)
struct Node {int data;Node* next;
};Node* head = new Node{1, new Node{2, new Node{3, nullptr}}};
特点:
- 内存不连续,访问需要遍历(O(n))。
- 动态大小,可以随时增删节点。
- 插入/删除高效(O(1),如果已知位置)。
3. 列表(List / Vector)
在C++中,std::list
(双向链表)和std::vector
(动态数组)是两种不同的“列表”实现:
(1) std::vector
(动态数组)
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
特点:
- 底层是动态数组,内存连续,支持随机访问(O(1))。
- 自动扩容(但扩容时可能涉及数据拷贝)。
- 尾部插入/删除高效(O(1)),中间/头部操作较慢(O(n))。
(2) std::list
(双向链表)
#include <list>
std::list<int> lst = {1, 2, 3, 4, 5};
特点:
- 底层是双向链表,内存不连续,不支持随机访问(O(n))。
- 任意位置插入/删除高效(O(1))。
- 占用更多内存(存储前后指针)。
4. 三者的对比(表格总结)
特性 | 数组(Array) | 链表(LinkedList) | std::vector | std::list |
---|---|---|---|---|
内存布局 | 连续内存 | 非连续内存(指针连接) | 连续内存(动态) | 非连续内存(双向链表) |
访问方式 | 随机访问(O(1)) | 顺序访问(O(n)) | 随机访问(O(1)) | 顺序访问(O(n)) |
插入/删除效率 | O(n)(需移动元素) | O(1)(已知位置) | 尾部O(1),中间O(n) | O(1)(任意位置) |
动态扩容 | 不支持 | 支持 | 支持(自动扩容) | 支持 |
内存开销 | 最小(仅数据) | 较大(存储指针) | 较小(可能预留空间) | 较大(前后指针) |
C++标准库实现 | std::array | 需手动实现或std::list | std::vector | std::list |
5. 如何选择?
- 需要快速随机访问? →
std::vector
(动态数组)。 - 频繁在中间插入/删除? →
std::list
(链表)。 - 固定大小且需高性能? → 原生数组或
std::array
。