1. STL容器有哪些?插入、查找和删除的平均时间复杂度是多少,为什么?
1.1 STL容器有哪些?
C++ STL(Standard Template Library)提供了一系列容器,用于在程序中存储和操作数据。下面是一些常见的 STL 容器:
vector
:动态数组,支持快速随机访问,尾部插入和删除。deque
:双端队列,支持在两端进行插入和删除操作。list
:双向链表,支持在任意位置进行插入和删除操作。forward_list
:单向链表,支持在链表头进行插入和删除操作,但不支持在链表尾进行插入和删除操作。set
:集合,内部元素自动排序,且不能包含重复元素。multiset
:多重集合,与 set 类似,但可以包含重复元素。unordered_set
:无序集合,内部元素不排序,且不能包含重复元素。unordered_multiset
:无序多重集合,与 unordered_set 类似,但可以包含重复元素。map
:映射表,内部元素自动排序,由键值对组成,且键不能重复。multimap
:多重映射表,与 map 类似,但键可以重复。unordered_map
:无序映射表,内部元素不排序,由键值对组成,且键不能重复。unordered_multimap
:无序多重映射表,与 unordered_map 类似,但键可以重复。以上容器都属于STL提供的序列容器,除此之外,STL还提供了关联容器、容器适配器等。
1.2 插入、查找和删除的平均时间复杂度是多少,为什么?
vector
:
插入: O(n),
insert()
; O(1),push_back()
查找:O(1), 下标访问operator
; 迭代器访问O(1),begin()
end()
;O(n),find()
删除: O(n),erase()
;O(1),pop_back()
原因:因为vector 实现是一个连续的动态数组,元素在内存连续存放,删除和插入时需要将后面元素向前、向后移动。
deque
:
插入:O(n),
insert()
; O(1),push_back()
push_front()
查找: O(1), 下标访问operator
; 迭代器访问O(1),begin()
end()
;O(n),find()
删除: O(n),erase()
; O(1),pop_back()
pop_front()
原因:因为 deque 采用双端队列实现,元素在内存连续存放,删除和插入时需要将后面元素向前、向后移动。
list
:
插入:O(1),
insert()
push_back()
push_front()
查找: O(n),find()
begin()
end()
删除: O(1),erase()
pop_back()
pop_front()
原因:因为 list 内部实现是一个双向链表,查找需要遍历整个链表,删除和插入只需要修改前后节点的指针即可。
set/multiset
:
插入:O(log n),
insert()
查找: O(log n),find()
删除: O(log n),erase()
原因:因为 set/multiset 内部实现是一个红黑树,每个节点最多有两个子节点,插入,查找和删除都可以通过二分查找实现。
map/multimap
:
插入:O(log n),
insert()
查找: O(log n),find()
删除: O(log n),erase()
原因这是因为 map/multimap 内部实现是一个红黑树,每个节点都有 key 和 value,插入,查找和删除都可以通过 key 的比较实现。
unordered_set/unordered_multiset
:
插入:O(1),
insert()
查找: O(1),find()
删除: O(1),erase()
原因:因为 unordered_set/unordered_multiset 内部实现是一个哈希表,插入查找和删除只需要计算哈希值即可。
unordered_map/unordered_multimap
:
插入:O(1),
insert()
查找: O(1),find()
删除: O(1),erase()
原因:因为 unordered_map/unordered_multimap 内部实现是一个哈希表,插入,查找和删除只需要计算哈希值即可。
总结一下:
容器 | 实现 | 插入 | 删除 | 查找 |
---|---|---|---|---|
vector | 动态数组 | O(n) | O(n) | O(1) |
deque | 双端队列 | O(n) | O(n) | O(1) |
list | 双向列表 | O(1) | O(1) | O(n) |
set/multiset | 红黑树 | O(log n) | O(log n) | O(log n) |
map/multimap | 红黑树 | O(log n) | O(log n) | O(log n) |
unordered_set/unordered_mulset | 哈希表 | O(1) | O(1) | O(1) |
unordered_map/unordered_nultimap | 哈希表 | O(1) | O(1) | O(1) |
需要注意的是,以上时间复杂度仅代表平均情况下的时间复杂度,最坏情况下可能会更高。此外,除了 vector 和 deque,其他容器的大小是动态调整的,因此实际上查找和删除的时间复杂度可能会更好。