容器是一个存储特定类型对象集合的对象。例如,如果我们想存储名字列表,我们可以使用vector
。
C++ STL 根据我们的需求提供不同类型的容器。
C++ 中 STL 容器的类型
在 C++ 中,通常有 3 种 STL 容器
- 顺序容器
- 关联容器
- 无序关联容器
1. C++ 中的顺序容器
在 C++ 中,顺序容器允许我们存储可以按顺序访问的元素。
在内部,顺序容器实现为数组或链表数据结构。
顺序容器的类型
- 数组
- Vector
- 双端队列
- List
- Forward List
示例:C++ 顺序容器(vector)
在本例中,我们将使用vector
类来演示顺序容器的工作原理。
#include <iostream>
#include <vector>
using namespace std;
int main() {
// initialize a vector of int type
vector<int> numbers = {1, 100, 10, 70, 100};
// print the vector
cout << "Numbers are: ";
for(auto &num: numbers) {
cout << num << ", ";
}
return 0;
}
输出
Numbers are: 1, 100, 10, 70, 100,
在上面的示例中,我们使用vector
类创建了顺序容器numbers。
vector<int> numbers = {1, 100, 10, 70, 100};
在这里,我们使用范围 for 循环来打印容器的每个元素。
在输出中,我们可以看到数字按照初始化的顺序显示。
// output numbers
1, 100, 10, 70, 100,
2. C++ 中的关联容器
在 C++ 中,关联容器允许我们将元素按排序顺序存储。顺序不取决于元素的插入时间。
在内部,它们实现为二叉树数据结构。
关联容器的类型
- 集合
- Map
- Multiset
- Multimap
示例:C++ 关联容器(set)
在本例中,我们将使用set
类来演示关联容器的工作原理。
#include <iostream>
#include <set>
using namespace std;
int main() {
// initialize a set of int type
set<int> numbers = {1, 100, 10, 70, 100};
// print the set
cout << "Numbers are: ";
for(auto &num: numbers) {
cout << num << ", ";
}
return 0;
}
输出
Numbers are: 1, 10, 70, 100,
在上面的示例中,我们使用set
类创建了一个关联容器。
我们用无序整数以及重复值100初始化了一个名为numbers的 set。
set<int> numbers = {1, 100, 10, 70, 100};
然后我们使用范围 for 循环打印 set 的内容。
在输出中,我们看到数字按升序排序,并删除了重复数字。最初,100重复了两次,但 set 删除了重复的数字100。
// output numbers
1, 10, 70, 100
3. C++ 中的无序关联容器
在 C++ 中,STL 无序关联容器提供了关联容器的无序版本。
在内部,无序关联容器实现为哈希表数据结构。
无序关联容器的类型
- Unordered Set
- Unordered Map
- Unordered Multiset
- Unordered Multimap
示例:C++ 无序关联容器(unordered_set)
在本例中,我们将使用unordered_set
类来演示无序关联容器的工作原理。
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
// initialize an unordered_set of int type
unordered_set<int> numbers = {1, 100, 10, 70, 100};
// print the set
cout << "Numbers are: ";
for(auto &num: numbers) {
cout << num << ", ";
}
return 0;
}
输出
Numbers are: 70, 10, 100, 1,
在上面的示例中,我们使用unordered_set
类创建了一个关联容器。
我们用无序整数以及重复值100初始化了无序 set numbers。
unordered_set<int> numbers = {1, 100, 10, 70, 100};
然后我们使用基于范围的 for 循环打印 set 的内容。
在输出中,我们看到重复的数字100被删除,但它没有按升序排序。
// output numbers
70, 10, 100, 1,
C++ 中的容器适配器
在 C++ 中,容器适配器会接受现有的 STL 容器,并提供受限的接口,使其表现不同。例如,
栈是容器适配器,它使用顺序容器deque
并提供受限的接口,仅支持push()
和pop()
操作。
容器适配器的类型
- 栈
- 队列
- 优先队列
示例:C++ 容器适配器(stack)
在本例中,我们将使用stack
类来演示容器适配器的工作原理。
#include <iostream>
#include <stack>
using namespace std;
int main() {
// create a stack of ints
stack<int> numbers;
// push into stack
numbers.push(1);
numbers.push(100);
numbers.push(10);
cout << "Numbers are: ";
// we can access the element by getting the top and popping
// until the stack is empty
while(!numbers.empty()) {
// print top element
cout << numbers.top() << ", ";
// pop top element from stack
numbers.pop();
}
return 0;
}
输出
Numbers are: 10, 100, 1,
在上面的示例中,我们使用stack
类创建了一个容器适配器。
stack <int> numbers;
与其他容器不同,我们不能直接向此容器初始化值。这是因为容器适配器限制直接向容器赋值。
这就是为什么我们使用push()
操作将元素插入栈。
同样,我们不允许直接迭代这个容器。所以,我们使用了一个迭代直到栈为空的循环。
while (!numbers.empty()) {
cout << numbers.top() << ", ";
numbers.pop();
}
这里,
numbers.empty()
- 检查stack
是否为空numbers.top()
- 返回stack
顶部的元素numbers.pop()
- 删除stack
的顶部元素