目录
[一、stack 栈](#一、stack 栈)
[(1)empty 成员函数](#(1)empty 成员函数)
[(2)pop 成员函数](#(2)pop 成员函数)
[(3)push 成员函数](#(3)push 成员函数)
[(4)size 成员函数](#(4)size 成员函数)
[(5)top 成员函数](#(5)top 成员函数)
[二、queue 队列](#二、queue 队列)
[1. 定义及初始化](#1. 定义及初始化)
[(1)back 成员函数](#(1)back 成员函数)
[(2)empty 成员函数](#(2)empty 成员函数)
[(3)front 成员函数](#(3)front 成员函数)
[(4)pop 成员函数](#(4)pop 成员函数)
[(5)push 成员函数](#(5)push 成员函数)
[(6)size 成员函数](#(6)size 成员函数)
[三、priority queue 优先级队列](#三、priority queue 优先级队列)
[(1)empty 成员函数](#(1)empty 成员函数)
[(2)pop 成员函数](#(2)pop 成员函数)
[(3)push 成员函数](#(3)push 成员函数)
[(4)size 成员函数](#(4)size 成员函数)
[(5)top 成员函数](#(5)top 成员函数)
[3.深入 priority queue](#3.深入 priority queue)
[四、 bitset 位图](#四、 bitset 位图)
前言
本文介绍了C++标准库中的四种容器适配器:1.stack栈(后进先出LIFO),包含初始化方法和常用操作(push/pop/top等);2.queue队列(先进先出FIFO),说明其特点和基本操作(push/pop/front/back等);3.priority_queue优先级队列(自动排序),详细讲解其堆实现原理和自定义比较方法;4.bitset位图(固定大小位集合),介绍位操作方法和转换函数。
一、stack 栈
1.定义及初始化
stack 是一种后进先出(LIFO, Last-In-First-Out)的数据结构,它只允许在栈顶进行插入和删除操作。
stack 只是很单纯地把各项操作转化为内部容器对应的函数调用。你可以使用任何支持 back()、push_back()和pop_back()成员函数的标准容器支持 stack。
使用push(入栈)将数据放入stack,使用pop(出栈)将元素从容器中移除。
使用stack,必须包含头文件<stack>:
cpp
#include <stack>
cpp
#include <stack>
// 默认初始化(使用deque作为底层容器)
std::stack<int> s1;
// 使用自定义底层容器初始化
std::stack<int, std::vector<int>> s2;
// 使用已有的容器初始化
std::vector<int> v = {1, 2, 3};
std::stack<int, std::vector<int>> s3(v);
2.常用操作
(1)empty 成员函数
检查栈是否为空,返回布尔值。
cpp
std::stack<int> s;
bool is_empty = s.empty(); // true
(2)pop 成员函数
移除栈顶元素,无返回值。
cpp
std::stack<int> s;
s.push(1);
s.push(2);
s.pop(); // 移除栈顶元素2
(3)push 成员函数
向栈顶添加元素。
cpp
std::stack<int> s;
s.push(1);
s.push(2);
(4)size 成员函数
返回栈中元素的数量。
cpp
std::stack<int> s;
s.push(1);
s.push(2);
s.push(3);
size_t size = s.size(); // 3
(5)top 成员函数
返回栈顶元素的引用,不修改栈。
cpp
std::stack<int> s;
s.push(1);
s.push(2);
int top_val = s.top(); // 2
二、queue 队列
1. 定义及初始化
queue 是一种先进先出 (FIFO, First-In-First-Out)的数据结构,它允许在队尾插入元素,在队首删除元素。
使用queue,必须引用头文件<queue>:
cpp
#include <queue>
cpp
#include <queue>
// 默认初始化(使用deque作为底层容器)
std::queue<int> q1;
// 使用自定义底层容器初始化
std::queue<int, std::list<int>> q2;
// 使用已有的容器初始化
std::list<int> l = {1, 2, 3};
std::queue<int, std::list<int>> q3(l);
2.常用操作
(1)back 成员函数
返回队尾元素的引用,不修改队列。
cpp
std::queue<int> q;
q.push(1);
q.push(2);
int back_val = q.back(); // 2
(2)empty 成员函数
检查队列是否为空,返回布尔值。
cpp
std::queue<int> q;
bool is_empty = q.empty(); // true
(3)front 成员函数
返回队首元素的引用,不修改队列。
cpp
std::queue<int> q;
q.push(1);
q.push(2);
int front_val = q.front(); // 1
(4)pop 成员函数
移除队首元素,无返回值。
cpp
std::queue<int> q;
q.push(1);
q.push(2);
q.pop(); // 移除队首元素1
(5)push 成员函数
向队尾添加元素。
cpp
std::queue<int> q;
q.push(1);
q.push(2);
(6)size 成员函数
返回队列中元素的数量。
cpp
std::queue<int> q;
q.push(1);
q.push(2);
q.push(3);
size_t size = q.size(); // 3
三、priority queue 优先级队列
1.定义及初始化
priority queue 是一种特殊的队列,它会根据元素的优先级自动排序,这里的第一个元素并不是第一个放入的元素,而是"优先级最高"的元素。默认情况下最大元素会位于队首。
其内部数据结构为:大根堆,不能使用list作为其容器。
priority queue也是定义在头文件<queue>中:
cpp
#include<queue>
cpp
#include <queue>
// 默认初始化(使用vector作为底层容器,默认使用less比较器)
std::priority_queue<int> pq1;
// 使用自定义比较器初始化(最小元素位于队首)
std::priority_queue<int, std::vector<int>, std::greater<int>> pq2;
// 使用已有的容器初始化
std::vector<int> v = {3, 1, 4};
std::priority_queue<int> pq3(v.begin(), v.end()); // 队首元素是4
2.常用操作
(1)empty 成员函数
检查优先级队列是否为空,返回布尔值。
cpp
std::priority_queue<int> pq;
bool is_empty = pq.empty(); // true
(2)pop 成员函数
移除队首元素(优先级最高的元素),无返回值。
cpp
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
pq.pop(); // 移除元素3
(3)push 成员函数
向优先级队列中添加元素,会自动调整以保持优先级顺序。
cpp
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
(4)size 成员函数
返回优先级队列中元素的数量。
cpp
std::priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
size_t size = pq.size(); // 3
(5)top 成员函数
返回队首元素(优先级最高的元素)的引用,不修改队列。
cpp
std::priority_queue<int> pq;
pq.push(1);
pq.push(3);
pq.push(2);
int top_val = pq.top(); // 3
3.深入 priority queue
priority queue 的底层实现通常是二叉堆,它具有以下特点:
-
时间复杂度:
- push 操作:O(log n)
- pop 操作:O(log n)
- top 操作:O(1)
-
自定义类型的优先级:
- 对于自定义类型,需要重载比较运算符或提供自定义比较器。
cppstruct Person { std::string name; int age; // 重载小于运算符,使年龄大的人优先级更高 bool operator<(const Person& other) const { return age < other.age; } }; std::priority_queue<Person> pq; pq.push({"Alice", 30}); pq.push({"Bob", 25}); pq.push({"Charlie", 35}); Person top_person = pq.top(); // Charlie, 35 -
使用自定义比较器:
cppstruct CompareByAge { bool operator()(const Person& a, const Person& b) { // 返回true表示a应该在b之后(即b的优先级更高) return a.age > b.age; // 年龄小的人优先级更高 } }; std::priority_queue<Person, std::vector<Person>, CompareByAge> pq;
四、 bitset 位图
1.初始化方法
bitset 是一种固定大小的位集合,它提供了位级别的操作。
位图,是一个类模板,它类似array类,具有固定的大小。当我们定义一个bitset 时,需要声明它包含多少个二进制位。例如:
cpp
bitset<32>bitvec(1);//32位;低位为1,其他位为0
cpp
#include <bitset>
// 默认初始化(所有位为0)
std::bitset<8> b1; // 00000000
// 使用整数初始化
std::bitset<8> b2(42); // 00101010(42的二进制表示)
// 使用字符串初始化
std::bitset<8> b3("10101010"); // 10101010
// 使用部分字符串初始化
std::bitset<8> b4("1010", 0, 4); // 00001010(只取前4位)
2.常用的符号和方法
(1)位操作符
&:按位与|:按位或^:按位异或~:按位取反<<:左移>>:右移
(2)成员函数
set():设置所有位为1set(pos):设置指定位置的位为1reset():设置所有位为0reset(pos):设置指定位置的位为0flip():翻转所有位flip(pos):翻转指定位置的位test(pos):检查指定位置的位是否为1any():检查是否有任何位为1none():检查是否所有位都为0count():返回为1的位的数量size():返回位集合的大小to_ulong():转换为unsigned longto_ullong():转换为unsigned long longto_string():转换为字符串
示例:
cpp
std::bitset<8> b("10101010");
// 检查位
bool bit0 = b.test(0); // false(第0位是0)
bool bit1 = b.test(1); // true(第1位是1)
// 设置位
b.set(0); // 10101011
b.reset(1); // 10101001
b.flip(); // 01010110
// 检查状态
bool has_any = b.any(); // true
bool has_none = b.none(); // false
int count = b.count(); // 4(有4位为1)
// 转换
unsigned long ul = b.to_ulong(); // 86
std::string s = b.to_string(); // "01010110"
位操作示例:
cpp
std::bitset<4> a("1010"); // 1010
std::bitset<4> b("1100"); // 1100
std::bitset<4> c = a & b; // 1000(按位与)
std::bitset<4> d = a | b; // 1110(按位或)
std::bitset<4> e = a ^ b; // 0110(按位异或)
std::bitset<4> f = ~a; // 0101(按位取反)
std::bitset<4> g = a << 1; // 0100(左移1位)
std::bitset<4> h = a >> 1; // 0101(右移1位)