STL容器的基础应用
STL容器的基础应用
注:本文中所有可选参数(包括可选模板参数、可选构造函数参数)均在其之后标注*
STL容器做形参时,默认情况下仍为按值传递。若需按址传递,可在形参中传递STL容器的引用,或使用指向STL容器的指针,或使用模板参数推导结合传引用。
序列容器
序列容器可接受的数据类型有基类型、序列容器类型(多维序列容器的实现方法之一)、复合类型(pair、tuple等)、自定义数据类型(struct、union等)、指针类型(包括函数指针)等。
同时,序列元素本身可以作为数组元素(多维序列容器另一实现方法)。高维序列容器在此仅用vector进行举例,其余序列容器同理。
vector 动态数组
- 支持随机访问
- 具有begin、end迭代器
- 在等长度的数组中,所占内存大小:vector>array==C数组
- vector的属性:size:实际大小;capacity:容量,即为预分配大小(注:访问超过实际大小的预分配内存部分为未定义行为)
一维vector
- 定义:
vector<数据类型>类名
。默认size=0,capacity由编译器决定,O(1) - 构造函数:
- 传入size及数据:
vector<数据类型>类名(size,data*)
,实际大小为size,每个元素都为data,data数据类型必须与vector模板参数中的数据类型相同,若不指定data则默认每个data为0。O( n n n) - 传入其他同维vector类名:
vector<数据类型>类名(其他类名)
,O( n n n) - 传入其他vector或非vector序列容器(包括C数组)的迭代器或指针:
vector<数据类型>类名(迭代器1/指针基址,迭代器2/尾指针)
,O( n n n)或O( n log n n\log n nlogn)
注:若传入不同维的vector,仅支持将低维vector传递给高维vector,且仅支持复制size和capacity,value无法复制;若反向传递则不允许。
- 传入size及数据:
- 初始化:
- 以序列表形式初始化:
vector<数据类型>类名{...}
或vector<数据类型>={...}
,O( n n n) - 以其他同维vector初始化:
vector<数据类型>类名=其他类名
,O( n n n)
- 以序列表形式初始化:
二维vector
数据类型为vector
-
定义:
vector<vector<数据类型>>类名
,O(1) -
构造函数:
- 传入size及数据:
vector<vector<数据类型>>类名(size,data*)
,实际大小为size,每个元素都为data,data必须与最外层vector模板参数中所指定的类型相同(在此处即必须为vector<数据类型>
),若不指定data则默认每个data为vector<数据类型>
,即每个data为size=0,data=0的一维vector)。data中的vector支持构造函数。O( m ∗ n m*n m∗n)
例:vector<vector<int>>v(3,vector<int>(5,4))
:创建一个3行5列,每个元素为4的二维vector - 传入其他同维vector类名:
vector<vector<数据类型>>类名(其他类名)
,O( m ∗ n m*n m∗n) - 传入其他vector迭代器:
vector<vector<数据类型>>类名(迭代器1,迭代器2)
,O( m ∗ n m*n m∗n)
注:若传入不同维的vector,仅支持将低维vector传递给高维vector,且仅支持复制size和capacity,value无法复制;若反向传递则不允许;二维及更高维vector不支持传入其他非vector序列容器及C数组
- 传入size及数据:
-
初始化:
- 以序列表形式初始化:
vector<vector<数据类型>>类名{{...},{...},...}
或vector<vector<数据类型>>类名={{...},{...},...}
,O( m ∗ n m*n m∗n) - 以其他同维vector初始化:vector<vector<数据类型>>类名=其他类名`,O( m ∗ n m*n m∗n)
- 以序列表形式初始化:
-
可采用每次push_back一维数组的方式完成输入
vector数组
- 定义:
vector<int>类名[大小]
,O(1) - vector数组无法使用构造函数
vector的常用成员函数
成员函数 | 功能 | 复杂度 |
---|---|---|
运算符[下标] | 随机访问元素 | O(1) |
类名.at(下标) | 随机访问元素(有越界检查) | O(1) |
类名.front() | 访问首元素 | O(1) |
类名.back() | 访问末元素 | O(1) |
类名.data() | 访问基址(当size!=0时,否则为NULL) | O(1) |
类名.push_back() | 向容器末尾插入元素 | O(1) |
类名.pop_back() | 弹出容器末尾元素 | O(1) |
类名.size() | 获取size(实际长度) | O(1) |
类名.empty() | 判断size是否为0 | O(1) |
类名.capacity() | 获取capacity(预分配内存) | O(1) |
类名.erase(迭代器1,迭代器2*) | 擦除某个或某个区间的元素(真删除),常与std::remove 结合使用(移除-擦除惯用法) | O( n n n) |
类名.insert(迭代器,数量*,元素) 类名.insert(目标迭代器,来源迭代器1,来源迭代器2) | 在该位置插入指定数量的某元素 在目标处插入来源区间内的元素 | O(
n
n
n) O( m + n m+n m+n) |
类名.clear() | 清空容器为size==0,capacity不变 | O( n n n) |
类名.resize(个数,数据*) | 修改容器的size:原容器size==个数,无操作;原容器size>个数,将size减小到个数,原有数据不变;原容器size<个数,原有数据不变,新增部分设为指定数据(默认为0) | O( n n n) |
类名.reserve(值) | 增加capacity到新值(增加预分配内存) | O( n n n) |
类名.shrink_to_fit() | 减小capacity的值,修改为与size相同(释放预分配内存) | O( n n n) |
类名.assign(个数,元素) 类名.assign(来源迭代器1,来源迭代器2) | 将指定个数的元素值或将某个区间内的值分配给容器,容器原有内容被覆盖。 | O( n n n) |
类名.swap(其他类名) | 交换两数组容器,比std::swap (O(
n
n
n))更优秀 | O(1) |
补充:一些其他常与STL容器结合使用的函数
函数 | 功能 | 复杂度 |
---|---|---|
fill(迭代器1,迭代器2,数据) | 填充容器 | O( n n n) |
remove(迭代器1,迭代器2,数据) | 移除某个区间内的某元素,不改变size大小的“假删除”。将区间内非此数据的元素向前移动。返回值为冗余区首个元素的迭代器,常与erase结合使用(移除-擦除惯用法) | O( n n n) |
unique(迭代器1,迭代器2) | 移除某个区间内重复元素,不改变size大小的“假删除”。将区间内非重复元素向前移动,将重复元素的首个元素向前移动。返回值为冗余区首个元素的迭代器,常与erase结合使用 | O( n n n) |
reverse(迭代器1,迭代器2) | 反转容器元素顺序 | O( n n n) |
find(迭代器1,迭代器2,值) | 在区间内寻找某值。若找到,返回值为迭代器,否则返回end迭代器 | O( n n n) |
max(值1,值2) 或max({...}) ;min(值1,值2) 或min({...}) | 返回两个元素/序列表中元素的最大(小)值 | O(1) O( n n n) |
max_element(迭代器1,迭代器2) min_element(迭代器1,迭代器2) | 返回区间内最大(小)值元素的迭代器 | O( n n n) |
sort(迭代器1,迭代器2,cmp*) | 对区间内元素进行排序,默认为升序 比较规则: std::greater<>() (前一个>后一个,降序)或std::less<>() (前一个<后一个,升序);若自定义cmp 函数,则也遵循此规则 | O( n log n n\log n nlogn) |
binary_search(迭代器1,迭代器2,key,cmp*) | 在有序序列中二分查找某元素,若存在返回1,不存在返回0,cmp默认为升序 | O( n log n n\log n nlogn) |
upper_bound(迭代器1,迭代器2,key,cmp*) | 在有序序列中二分查找首个>(严格大于)key的元素,查找成功返回其迭代器,否则返回end 迭代器,cmp默认为升序 | O( n log n n\log n nlogn) |
lower_bound(迭代器1,迭代器2,key,cmp*) | 在有序序列中二分查找首个
≥
\ge
≥(大于等于)key的元素,查找成功返回其迭代器,否则返回end 迭代器,cmp默认为升序 | O( n log n n\log n nlogn) |
next_permutation(迭代器1,迭代器2,cmp*) | 若序列有下一个字典序排列组合,则在原序列中改变顺序,返回值为1;否则返回0 常与 do-while 循环使用 | O ( n ) O(n) O(n) |
prev_permutation(迭代器1,迭代器2,cmp*) | 若序列有上一个字典序排列组合,则在原序列中改变顺序,返回值为1;否则返回0 常与 do-while 循环使用 | O ( n ) O(n) O(n) |
deque 双端队列
- 支持随机访问
- 有begin、end迭代器
- 仅有size属性,没有capacity属性
- 定义:
deque<数据类型>类名
,O(1) - 构造函数:
- 传入size及数据:
deque<数据类型>类名(size,data*)
,O( n n n) - 传入其他同维deque类名:
deque<数据类型>类名(其他类名)
,O( n n n) - 传入其他deque或非deque序列容器(包括C数组)的迭代器或指针:
deque<数据类型>类名(迭代器1/指针基址,迭代器2/尾指针)
,O( n n n)
注:若传入不同维的vector,仅支持将低维deque传递给高维deque,且仅支持复制size,value无法复制;若反向传递则不允许。
- 传入size及数据:
- 初始化:
- 以序列表形式初始化:
deque<数据类型>类名{...}
或deque<数据类型>={...}
,O( n n n) - 以其他同维deque初始化:
deque<数据类型>类名=其他类名
,O( n n n)
- 以序列表形式初始化:
成员函数 | 功能 | 复杂度 |
---|---|---|
运算符[下标] | 随机访问 | O(1) |
类名.at(下标) | 带有越界检查的随机访问 | O(1) |
类名.front() | 访问队头元素 | O(1) |
类名.back() | 访问队尾元素 | O(1) |
类名.push_front() | 在队头插入元素 | O(1) |
类名.push_back() | 在队尾插入元素 | O(1) |
类名.pop_front() | 弹出队头元素 | O(1) |
类名.pop_back() | 弹出队尾元素 | O(1) |
类名.insert(迭代器,数量*,元素) 类名.insert(目标迭代器,来源迭代器1,来源迭代器2) | 在该位置插入指定数量的某元素 在目标处插入来源区间内的元素 | O(
n
n
n) O( m + n m+n m+n) |
类名.size() | 获取size | O(1) |
类名.empty() | 判断size是否为0 | O(1) |
类名.erase(迭代器1,迭代器2*) | 擦除某个或某个区间的元素(真删除),常与std::remove 结合使用(移除-擦除惯用法) | O( n n n) |
类名.resize(个数,数据*) | 修改容器的size:原容器size==个数,无操作;原容器size>个数,将size减小到个数,原有数据不变;原容器size<个数,原有数据不变,新增部分设为指定数据(默认为0) | O( n n n) |
类名.clear() | 清空容器为size==0 | O( n n n) |
类名.swap(其他类名) | 交换两数组容器,比std::swap (O(
n
n
n))更优秀 | O(1) |
类名.assign(个数,元素) 类名.assign(来源迭代器1,来源迭代器2) | 将指定个数的元素值或将某个区间内的值分配给容器,容器原有内容被覆盖。 | O( n n n) |
list 双链表
- 有begin、end迭代器
- 不支持随机访问
- 无capacity属性
- 定义:
list<数据类型>类名
,O(1) - 构造函数:
- 传入size及data:
list<数据类型>类名(size,data*)
,O( n n n) - 传入其他同维list类名:
list<数据类型>类名(其他类名)
,O( n n n) - 传入其他list或非list序列容器(包括C数组)的迭代器或指针:
list<数据类型>类名(迭代器1/指针基址,迭代器2/尾指针)
,O( n n n)
注:若传入不同维的list,仅支持将低维list传递给高维list,且仅支持复制size,value无法复制;若反向传递则不允许。
- 传入size及data:
- 初始化:
- 以序列表形式初始化:
list<数据类型>类名{...}
或list<数据类型>={...}
,O( n n n) - 以其他同维list初始化:
list<数据类型>类名=其他类名
,O( n n n)
- 以序列表形式初始化:
成员函数 | 功能 | 复杂度 |
---|---|---|
类名.front() | 访问头结点 | O(1) |
类名.back() | 访问尾结点 | O(1) |
类名.push_front() | 在头结点插入元素 | O(1) |
类名.push_back() | 在尾结点插入元素 | O(1) |
类名.pop_front() | 弹出头结点 | O(1) |
类名.pop_back() | 弹出尾结点 | O(1) |
类名.size() | 获取size | O(1) |
类名.empty() | 判断size是否为0 | O(1) |
类名.clear() | 清空容器为size==0 | O( n n n) |
类名.swap(其他类名) | 交换两链表容器,比std::swap (O(
n
n
n))更优秀 | O(1) |
类名.assign(个数,元素) 类名.assign(来源迭代器1,来源迭代器2) | 将指定个数的元素值或将某个区间内的值分配给容器,容器原有内容被覆盖。 | O( n n n) |
类名.insert(迭代器,数量*,元素) 类名.insert(目标迭代器,来源迭代器1,来源迭代器2) | 在该位置插入指定数量的某元素/在目标处插入来源区间内的元素 | O( n n n) |
类名.erase(迭代器1,迭代器2*) | 擦除某个或某个区间的元素(真删除) | O( n n n) |
类名.sort(cmp*) | 对链表进行排序,默认为升序 排序规则: std::greater<>() (降序)或std::less<>() (升序) | O( n log n n\log n nlogn) |
类名.remove(值) | 真删除某个元素值(与其他序列容器不同) | O( n n n) |
类名.merge(其他类名) | 合并两有序链表 | O( m + n m+n m+n) |
类名.reverse() | 反转链表 | O( n n n) |
类名.unique() | 真删除重复元素值(与其他序列容器不同) | O( n n n) |
类名.splice(目标迭代器,其他类名,来源迭代器1*,来源迭代器2*) | 将其他链表元素链接到当前链表的目标迭代器处。若无第3和4参数,则为其他链表所有元素均链接;若有第3无4参数,则为其他链表的来源迭代器1处的元素进行链接;若有第3和4参数,则为其他链表的区间元素进行链接 | O(1)(无3无4或有3无4) O( n n n)(有3有4) |
array 数组
- 大小必须在编译时确定的字面常量,不能使用变量控制大小(不支持VLC)
- 无capacity属性
- 有begin、end迭代器
- 定义:
array<数据类型,大小>类名
- 无构造函数
- 初始化:
- 以序列表形式初始化:
array<数据类型,大小>类名{...}
或array<数据类型,大小>类名={...}
,O( n n n) - 以其他同维list初始化:
array<数据类型,大小>类名=其他类名
,O( n n n)
- 以序列表形式初始化:
成员函数 | 功能 | 复杂度 | 成员函数 | 功能 | 复杂度 |
---|---|---|---|---|---|
运算符[下标] | 随机访问 | O(1) | 类名.size() | 获取size(实际长度) | O(1) |
类名.at(下标) | 带有越界检查的随机访问 | O(1) | 类名.empty() | 判断size是否为0 | O(1) |
类名.front() | 访问首元素 | O(1) | 类名.swap(其他类名) | 交换两容器 | O(1) |
类名.back() | 访问末元素 | O(1) | 类名.fill(值) | 以特定值填充容器 | O( n n n) |
类名.data() | 访问基址(当size!=0时,否则为NULL) | O(1) |
- 通过
std::get
对array进行访问:get<下标>(类名)
下标必须是字面常量,不可以是变量!
补充:bitset 二进制位序列容器
- 无begin、end迭代器
- 定义:
bitset<size>类名
,size为二进制位数,必须为字面常量 - 补充:计算size: ∀ x > 0 \forall x>0 ∀x>0,size= ⌈ log 2 ( x ) ⌉ \lceil\log_2(x)\rceil ⌈log2(x)⌉
- 构造函数:
- 传入整数:
bitset<size>类名(整数)
- 传入其他全部由数字型字符构成的string/C字符数组/字符串字面常量:
bitset<size>类名(其他类名/数组名/常量)
(传入内容中不允许包含任何非数字型字符!) - 传入其他bitset:
bitset<size>类名(其他类名)
- 传入整数:
- 初始化:
- 传入整数:
bitset<size>类名{整数}
- 传入其他全部由数字型字符构成的string/C字符数组/字符串字面常量:
bitset<size>类名{其他类名/数组名/常量}
(传入内容中不允许包含任何非数字型字符!)
- 传入整数:
- bitset容器间可进行位运算
成员函数 | 功能 | 复杂度 |
---|---|---|
运算符[下标] | 随机访问指定位 | O(1) |
类名.test(下标) | 随机访问指定位(带越界检查) | O(1) |
类名.size() | 返回容器size | O(1) |
类名.any() | 若任意位为1则返回1,否则返回0 | |
类名.none() | 若没有位为1则返回1,否则返回0 | |
类名.all() | 若所有位为1则返回1,否则返回0 | |
类名.set(位) | 将某位设为1 | O(1) |
类名.reset(位) | 将某位设为0 | O(1) |
类名.count() | 统计容器中位为1的位的数量 | |
类名.flip(位) | 将某位值取反 | O(1) |
类名.to_string() | 返回数据的字符串表示 | |
类名.to_ulong() | 返回数据的unsigned long 整数表示 | |
类名.to_ullong() | 返回数据的unsigned long long整数表示 |
补充:string
- 有begin、end迭代器
- 特殊成员:
string::npos
,一个整数下标,通常为-1,表示字符串中无效或不存在的位置 - 支持随机访问
- 有两个属性:size(实际大小)和capacity(预分配内存)
- 定义:
string 类名
,O(1) - 构造函数:(注:起始下标必须是整形!)
- 传入其他string类名:
string 类名(其他类名,起始下标*,传入长度*)
,O( n n n) - 传入字符串字面常量:
string 类名(字符串字面常量,起始下标*,传入长度*)
,O( n n n) - 传入C风格字符串:
string 类名(数组名,起始下标*,传入长度*)
,O( n n n) - 传入指定数量的字符:
string 类名(数量,字符字面常量)
,可传入ASCII码,O( n n n) - 传入其他string或序列容器的迭代器:
string(迭代器1,迭代器2)
,O( n n n)
- 传入其他string类名:
- 初始化:
- 以其他string类名初始化:
string 类名=其他类名
,O( n n n) - 以字符串字面常量进行初始化:
string 类名="字符串字面常量"
或string 类名{"字符串字面常量"}
,O( n n n) - 以字符字面常量进行初始化:
string 类名{'常量1','常量2',...}
,O( n n n)
- 以其他string类名初始化:
- 字符串的输入:
cin
(遇到空格或换行停止)、getline(cin,类名)
(读取整行) - 字符串的转换:
to_string
:转换为string;stoi
/stol
/stoll
/stof
/stod
/stold
:将string转换为int/long/long long/float/double/long double - 字符串流(
<sstream>
):三种类:istringstream(字符串输入流)、ostringstream(字符串输出流)和stringstream(字符串输入输出流,向下兼容C),支持通过插入器(<<)和析取器(>>)对流进行操作
成员函数 | 功能 | 复杂度 |
---|---|---|
运算符[下标] | 随机访问 | O(1) |
类名.at(下标) | 随机访问(带越界检查) | O(1) |
类名.data() | 访问基址(当size!=0时,否则为NULL) | O(1) |
类名.front() | 访问首元素 | O(1) |
类名.back() | 访问末元素 | O(1) |
类名.push_back(数据) | 向容器末尾插入元素 | O(1) |
类名.pop_back() | 弹出容器末尾元素 | O(1) |
类名.size() 类名.length() | 获取string的size(不会被\0 截断) | O(1) |
类名.capacity() | 获取string的capacity | O(1) |
类名.empty() | 检查string是否为空 | O(1) |
类名.clear() | 清除string | O( n n n) |
类名.reserve(值) | 增加capacity到指定值 | O( n n n) |
类名.resize(值) | 修改容器的size:原容器size==个数,无操作;原容器size>个数,将size减小到个数,原有数据不变;原容器size<个数,原有数据不变,新增部分设为指定数据(默认为0) | O( n n n) |
类名.shrink_to_fit() | 减小capacity的值,修改为与size相同(释放预分配内存) | O( n n n) |
运算符+=类名/C字符数组/字符/字符序列表/字面常量 或类名.append(类名,起始下标*,长度*) /类名.append(C字符数组,长度*) /类名.append(字符,数量) /类名.append(迭代器1,迭代器2) /类名.append(字符序列表) | 字符串连接 | O( n n n) |
运算符+ | 连接两字符串 | O( m + n m+n m+n) |
类名.insert(目标下标,来源字符串*,长度*) /类名.insert(目标下标,C字符数组,长度*) /类名.insert(目标下标/迭代器,长度*,字符) /类名.insert(目标迭代器,来源迭代器1,来源迭代器2) /类名.insert(目标迭代器,序列表) | 插入元素 | O( n n n) |
类名.erase(起始下标*,长度*) /类名.erase(迭代器) /类名.erase(迭代器1,迭代器2) | 擦除某个或某个区间的元素(真删除) | O( n n n) |
类名.replace(目标起始下标,替换长度,来源字符串,来源起始下标*,来源长度*) /类名.replace(目标迭代器1,目标迭代器2,来源字符串) /类名.replace(目标起始下标/目标迭代器1,替换长度/目标迭代器2,来源C字符数组,来源长度*) /类名.replace(目标下标/目标迭代器1,替换长度/目标迭代器2,数量,字符) /类名.replace(目标迭代器1,目标迭代器2,来源迭代器1,来源迭代器2) /类名.replace(目标迭代器1,目标迭代器2,字符序列表) | 替换字符串中的某部分 | O( n n n) |
类名.swap(其他类名) | 交换两字符串 | O(1) |
类名.c_str() | 返回该字符串字符常量指针 | O(1) |
类名.copy(目标C字符数组,数量,起始位置) | 将该string中的内容复制到目标字符数组中 | O( n n n) |
类名.find(其他类名/字符/C字符数组,起始位置*) /类名.find(C字符数组,起始位置,查找长度) 类名.rfind(其他类名/字符/C字符数组,起始位置*)`/`类名.rfind(C字符数组,起始位置,查找长度) | 正/反向查找子串/子字符:若找到返回起始位置迭代器;若未找到,则返回string::npos | O( m + n m+n m+n) |
类名.find_first_of(其他类名/字符/C字符数组,起始位置*) /类名.find_first_of(C字符数组,起始位置,查找长度) 类名.find_last_of(其他类名/字符/C字符数组,起始位置*)`/`类名.find_last_of(C字符数组,起始位置,查找长度) 类名.find_first_not_of(其他类名/字符/C字符数组,起始位置*) /类名.find_first_not_of(C字符数组,起始位置,查找长度) 类名.find_last_not_of(其他类名/字符/C字符数组,起始位置*)`/`类名.find_last_not_of(C字符数组,起始位置,查找长度) | 正向查找首/末个是/不是该子串/字符:若找到返回起始位置迭代器;若未找到,则返回string::npos | O( m + n m+n m+n) |
类名.substr(起始位置,长度*) | 生成子串,返回值为新的string对象 | O( n n n) |
类名.compare(当前字符串起始位置*,当前字符串比较长度*,被比较字符串/C字符数组) /类名.compare(当前字符串起始位置,当前字符串比较长度,被比较字符串,被比较字符串起始位置,被比较长度*) /类名.compare(当前字符串起始位置,当前字符串比较长度,被比较C字符数组,被比较长度) | 比较字符串:若当前字符串<被比较字符串,返回负数;当前字符串==被比较字符串,返回0;当前字符串>被比较字符串,返回正数 | O( m + n m+n m+n) |
容器适配器
底层容器:表示用于实现该STL容器所基于何种底层容器。手动指定时,必须为序列容器(vector、deque、list、array等)。
stack 栈
-
定义:
stack<数据类型,底层容器*>类名
,默认底层容器类型为deque,可接受的数据类型与底层容器相同 -
构造函数:
- 传入另一stack容器:
stack<数据类型,底层容器*>类名(其他类名)
,不支持传入其他非stack容器,O(1) - 传入序列容器的迭代器:仅C++23及之后支持,O( n n n)
- 传入另一stack容器:
-
不支持使用序列表初始化
-
无
begin
、end
迭代器,因此无法使用find、unique等函数 -
可作为数组元素
成员函数 | 功能 | 复杂度 | 成员函数 | 功能 | 复杂度 |
---|---|---|---|---|---|
类名.push(数据) | 入栈 | O(1) | 类名.empty() | 判断栈是否为空 | O(1) |
类名.pop() | 出栈 | O(1) | 类名.size() | 获取栈中元素个数 | O(1) |
类名.top() | 读栈顶元素 | O(1) | 类名.swap(其他类名) | 交换两栈容器 | O(1) |
-
swap
成员函数相比于std::swap
(O( n n n))更优秀 -
无清空容器的成员函数,需用while循环+
pop
函数实现清空,O( n n n)
queue 队列
-
定义:
queue<数据类型,底层容器*>类名
,默认底层容器类型为deque,可接受的数据类型与底层容器相同 -
构造函数:
- 传入另一queue容器:
queue<数据类型,底层容器*>类名(其他类名)
,不支持传入其他非queue容器,O(1) - 传入序列容器的迭代器:仅C++23及之后支持,O( n n n)
- 传入另一queue容器:
-
不支持使用序列表初始化
-
无
begin
、end
迭代器,因此无法使用find、unique等函数 -
可作为数组元素
成员函数 | 功能 | 复杂度 | 成员函数 | 功能 | 复杂度 |
---|---|---|---|---|---|
类名.push(数据) | 入队 | O(1) | 类名.size() | 获取队列元素个数 | O(1) |
类名.pop() | 出队 | O(1) | 类名.empty() | 判断队列是否为空 | O(1) |
类名.front() | 读队头元素 | O(1) | 类名.swap(其他类名) | 交换两队列容器 | O(1) |
类名.back() | 读队尾元素 | O(1) |
swap
成员函数相比于std::swap
(O( n n n))更优秀- 无清空容器的成员函数,需用while循环+
pop
方法实现清空,O( n n n)
priority_queue 优先队列(二叉堆)
-
定义:
priority_queue<数据类型,底层容器*,优先规则*>类名
,默认底层容器为vector,可接受的数据类型与底层容器相同。默认优先规则为less<>
(大根堆)。若使用优先规则,则底层容器必须指定。 -
优先规则:
greater<>
或less<>
:greater<>
表示前>后,在二叉堆中指子节点>父节点,因此创建小根堆;less<>
表示前<后,在二叉堆中指子节点<父节点,因此创建大根堆。注意不要与greater<>()
和less<>()
混淆。- 自定义函数:在做优先规则时使用
std::function<>
:priority_queue<数据类型,底层容器,function<返回值类型(形参表)>>类名(函数名)
-
构造函数:
- 传入序列容器的迭代器:
priority_queue<数据类型,底层容器*,优先规则*>类名(迭代器1,迭代器2)
,O( n n n)或O( m + n m+n m+n) - 传入其他priority_queue:
priority_queue<数据类型,底层容器*,优先规则*>类名(其他类名)
,O(1)
- 传入序列容器的迭代器:
-
不支持使用序列表初始化
-
无
begin
、end
迭代器,因此无法使用find、unique等函数 -
可作为数组元素
成员函数 | 功能 | 复杂度 | 成员函数 | 功能 | 复杂度 |
---|---|---|---|---|---|
类名.push(数据) | 在堆底插入数据 | O( log n \log n logn) | 类名.size() | 获取堆中元素个数 | O(1) |
类名.pop() | 弹出堆顶元素 | O( log n \log n logn) | 类名.empty() | 判断堆是否为空 | O(1) |
类名.top() | 读堆顶元素 | O(1) | 类名.swap(其他类名) | 交换两优先队列容器 | O(1) |
swap
成员函数相比于std::swap
(O( n n n))更优秀- 无清空容器的成员函数,需用while循环+
pop
方法实现清空,O( n log n n\log n nlogn)
关联容器
补充:复合结构类型 pair、tuple
pair 对组
批量组织一对数据类型(可接受的数据类型有基类型、序列容器类型、复合类型(pair、tuple等)、自定义数据类型(struct、union等)、指针类型(包括函数指针)等。)
- 定义:
pair<value1数据类型,value2数据类型>类名
- 构造函数:
pair<value1数据类型,value2数据类型>类名(value1,value2)
- make_pair:创建一个pair对象,
make_pair(value1,value2)
- 初始化:
pair<value1数据类型,value2数据类型>类名=make_pair(value1,value2)
- 访问:与struct类似
- 直接访问:
类名.first
:访问value1类名.second
:访问value2 - 通过指针访问:
类名->first
:访问value1类名->second
:访问value2 - 通过
std::tie
解包:tie(接收变量1,接收变量2)=类名
,若不想接收某个值,用std::ignore
代替 - 通过
std::get
访问:get<0>(类名)
:访问value1,get<1>(类名)
:访问value2
- 直接访问:
tuple 元组
批量组织多个数据类型(可接受的数据类型有基类型、序列容器类型、复合类型(pair、tuple等)、自定义数据类型(struct、union等)、指针类型(包括函数指针)等。)
- 定义:
tuple<value1数据类型,value2数据类型,...,value n数据类型>类名
- 构造函数:
tuple<value1数据类型,value2数据类型,...,value n数据类型>类名(value1,value2,...,value n)
- make_tuple:创建一个tuple对象,
make_tuple(value1,value2,...value n)
\ - 初始化:
tuple<value1数据类型,value2数据类型,...,value n数据类型>类名=make_tuple(value1,value2,...value n)
- 访问:
- 通过
std::tie
解包:tie(接收变量1,...,接收变量n)=类名
,若不想接收某个值,用std::ignore
代替 - 通过
std::get
访问:get<0>(类名)
:访问value1,…,get<n>(类名)
:访问value n+1
- 通过
- 拼接元祖:
auto 新类名=tuple_cat(类1,类2,...,类n)
set 键集合
set是不重复的key集合
- 有begin、end迭代器
- 不支持随机访问
- 定义:
set<类型,排序规则*>类名
,默认排序规则为less<>
,O(1) - 构造函数:
- 传入其他set类名:
set<类型>类名(其他类名)
,O(1) - 传入其他set迭代器:
set<类型>类名(迭代器1,迭代器2)
,O( n log n n\log n nlogn)
- 传入其他set类名:
- 初始化:
- 传入其他set类名:
set<类型>类名=其他类名
,O(1) - 以序列表初始化:
set<类型>类名{value1,...,value n}
,O( n n n)
- 传入其他set类名:
成员函数 | 功能 | 复杂度 |
---|---|---|
类名.empty() | 检查容器是否为空 | O(1) |
类名.size() | 返回容器size | O(1) |
类名.clear(key) | 清空容器 | O( n n n) |
类名.swap(其他类名) | 交换两容器 | O(1) |
类名.insert(值) 类名.insert(迭代器1,迭代器2) 类名.insert({序列表}) | 插入某元素/某区间元素 | O(
n
n
n) O( n log n n\log n nlogn) |
类名.erase(值) 类名.erase(迭代器1,迭代器2) | 真删除某元素/某区间元素 | O( n n n) |
类名.count(值) | 查询值出现的次数 | O( n n n) |
类名.find(值) | 若找到返回对应值的迭代器,否则返回end迭代器 | O( log n \log n logn) |
类名.upper_bound(值) | 查找>(严格大于)值的迭代器,否则返回end迭代器 | O( log n \log n logn) |
类名.lower_bound(值) | 查找 ≥ \ge ≥值的迭代器,否则返回end迭代器 | O( log n \log n logn) |
- set的遍历:与序列容器相同,支持正向遍历、反向遍历,基于范围的for循环遍历
- 特殊的set:
unordered_set
:不自动排序的set;multiset
:允许多个重复值的set;unordered_multiset
:不自动排序且允许多个重复值的set
map 键值对集合
map是key->value的集合,可用于实现哈希表/字典,其内部采用红黑树实现。map中无重复的key,但value可以重复。
-
有begin、end迭代器
-
定义:
map<key类型,value类型,排序规则*>类名
,默认排序规则为less<>
,O(1) -
构造函数:
- 传入其他map类名:
map<key类型,value类型>类名(其他类名)
,O(1) - 传入其他map迭代器:
map<key类型,value类型>类名(迭代器1,迭代器2)
,O( n log n n\log n nlogn)
- 传入其他map类名:
-
初始化:
- 传入其他map类名:
map<key类型,value类型>类名=其他类名
,O(1) - 以序列表初始化:
map<key类型,value类型>类名{make_pair(key1,value1),...,make_pair(key n,value n)}
/map<key类型,value类型>类名{{key1,value1},...,{key n,value n}}
,O( n log n n\log n nlogn)
- 传入其他map类名:
成员函数 | 功能 | 复杂度 |
---|---|---|
运算符[key] | 随机访问key所指的value,否则返回0 | O( log n \log n logn) |
类名.at(key) | 随机访问(带越界检查) | O( log n \log n logn) |
类名.empty() | 检查容器是否为空 | O(1) |
类名.size() | 返回容器size | O(1) |
类名.clear(key) | 清空容器 | O( n n n) |
类名.insert(pair<类型,类型>(数据,数据)) 类名.insert(make_pair(数据,数据)) 类名.insert({key,value}) 类名.insert(迭代器1,迭代器2) 类名[key]=value | 插入元素 | O(
log
n
\log n
logn) O(( n log n n\log n nlogn) + n +n +n) |
类名.erase(key) 类名.erase(迭代器1,迭代器2*) | 真删除当前key或删除某个区间 | O( n n n) |
类名.swap(其他类名) | 交换两容器 | O(1) |
类名.count(key) | 查询key出现的次数 | O( n n n) |
类名.find(key) | 若找到返回对应key的迭代器,否则返回end迭代器 | O( log n \log n logn) |
类名.upper_bound(key) | 查找>(严格大于)key的迭代器,否则返回end迭代器 | O( log n \log n logn) |
类名.lower_bound(key) | 查找 ≥ \ge ≥key的迭代器,否则返回end迭代器 | O( log n \log n logn) |
- map的遍历:与序列容器相同,支持正向遍历、反向遍历(注意使用
迭代器->first
访问元素);基于范围的for循环遍历(注意使用变量.first
访问元素) - 特殊的map:
unordered_map
:不自动排序的map;multimap
:允许多个重复key的map;unordered_multimap
:不自动排序且允许多个重复key的map;hash_map
:自定义hash函数的map
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具