C++容器技术
1. string容器
1.1 定义:字符串
1.2 头文件:
include <string>
1.3 构造
string str1;//初始化一个空的字符串
string str2 = "abc";//创建字符串str2,并赋值abc
string str3(str2);//创建str3,并用str2初始化str3
string str4(5, 'a');//创建str4,并赋值为5个a
1.4 赋值
string str1,str2,str3;
str1 = "abc";
str2.assign("abc",2);//把abc的前2个字符赋值给str2
str2.assign(str1);
str2.assign(str1,2);//把str1的前2个字符赋值给str2
str3.assign(3,'a');//str3为 aaa
1.5 拼接
str1 += "a";
str1 +=str2;
str1.append("a");
str1.append(str2);
str2.append("abc", 2);//str2增加abc的前两位
str2.append(str3, 1,1);//str3从第1个字符开始的1个字符拼接给str2
1.6 查找和替换
1.6.1 str.find():从左往右查找
string str1="abcdabcd";
string str2 = "bc";
int pos1 = str1.find("c");//查看c在str1中第一次出现的下标
int pos2 = str1.find("c",3);//查看c在str1中第一次出现的下标,从下标3开始查找
int pos3 = str1.find(str2);
int pos4 = str1.find(str2, 3);
1.6.2 str.rfind():从右往左查找
1.6.3 str.replace():替换
str1.replace(2, 2, "eee");//从str1的下标2开始的2个字符替换为eee
str1.replace(2, 2, str2);//从str1的下标2开始的2个字符替换为str2的内容
1.7 字符串比较
按ASCII码比较,=返回0,>返回1,<返回-1
int a = str1.compare("a");
a = str1.compare(str2);
1.8 存取及修改
string str1="abcdabcd";
//输出c
cout << str1[2] << endl;
cout << str1.at(2) << endl;
//修改下标为2的字符
str1[2] = 't';
str1.at(2) = 'c';
1.9 插入
string str1="abcd";
string str2 = "ef";
str1.insert(2, "a");//从下标2开始插入一个a
str1.insert(2, str2);//从下标2开始插入str2的内容
str1.insert(2,3, 'a');//从下标2开始插入3个a
1.10 删除
string str1="abcdef";
str1.erase(3);//删除下标3及以后的元素
str1.erase(1, 1);//删除下标1开始的1个元素
1.11 获取子串
string str1="abcdef";
string str2 = str1.substr(2, 3);//str2获取str1从下标2开始的3个字符
2. vector容器
2.1 定义:单端数组
2.2 头文件:
include <vector>
2.3 构造
vector<int>v1;
vector<int>v2(v1.begin(),v1.end());
vector<int>v3(5,1);//构造v3,并赋值5个1
vector<int>v4(v1);
2.4 赋值
vector<int>v1;
vector<int>v1 = { 0,1,2,3,4,5 };
vector<int>v2;
v2 = v1;
v2.assign(v1.begin(), v1.end());
v2.assign(5, 1);//将5个1赋值给v2
2.5 容量与大小
vector<int>v1;
int a = v1.empty();//判断v1是否为空,空返回1,非空返回0
int b = v1.capacity();//返回v1的最大容量
int c = v1.size();//返回v1当前的大小(元素个数)
v1.resize(3);//把v1的容量改为3,若当前容量比3大,则删除后面元素;若小,则用0填充
v1.resize(5, 1);//把v1的容量改为5,若当前容量比5小,则用1填充
2.6 插入
vector<int>v1 = { 0,1,2,3,4,5 };
v1.push_back(6);//尾部插入6
vector<int>::iterator i = v1.begin();//创建迭代器指向v1头部
i = v1.insert(i, 7);//在位置i处插入1个7,返回头部位置
i = v1.insert(i, 2,0);//在位置i处插入2个0,返回头部位置
2.7 删除
v1.pop_back();//尾部删除
i = v1.erase(i);//删除在位置i的元素,并返回下一个数据的位置
i = v1.erase(i, i + 2);//删除在位置i、i+1的元素,下一个数据的位置。不删除i+2的元素!!!
2.8 互换容器
vector<int>v1 = { 0,1,2,3,4,5 };
vector<int>v2 = { 1 };
v1.swap(v2);
2.9 预留空间
目的:减少vector在动态扩展容量时的扩展次数
vector<int>v1 = { 0,1,2,3,4,5 };
v1.reserve(10);
cout << v1.capacity() << endl;//输出10
cout << v1.size() << endl;//输出6
3. deque容器
3.1 定义:双端数组
3.2 头文件:
include <deque>
3.3 构造
deque<int>d1;
deque<int>d2 = { 0,1,2,3,4 };
deque<int>d3(d2.begin(), d2.end());
deque<int>d4(5, 1);
3.4 赋值
deque<int>d1,d3,d4;
deque<int>d2 = { 0,1,2,3,4 };
d1 = d2;
d3.assign(d2.begin(), d2.end());
d4.assign(3, 1);
3.5 大小操作
deque<int>d2 = { 0,1,2,3,4 };
cout << d2.empty() << endl;
cout << d2.size() << endl;
d2.resize(3);
d2.resize(5, 1);
3.6 插入(会引起迭代器失效)
deque<int>d2 = { 0,1,2,3,4 };
deque<int>::const_iterator i = d2.begin();//创建迭代器
d2.push_back(5);//尾插
d2.push_front(-1);//头插
//尾插头插会导致重新分配空间,所以之前的迭代器失效,需要重新初始化迭代器,否则代码奔溃报错
i = d2.begin();
i=d2.insert(i, 1);//位置i插入1,返回位置i
i=d2.insert(i, 2,5);//位置i插入2个5,返回位置i
//不返回i的话连续插入会报错!
3.7 删除
deque<int>d2 = { 0,1,2,3,4,5,6 };
deque<int>::iterator i = d2.begin();
d2.pop_back();//删除最后一个
d2.pop_front();//删除第一个
i = d2.begin();//因为第一个被删除,所以再次初始化迭代器
i=d2.erase(i);//删除位置i的数据
i = d2.erase(i, i + 2);//删除位置i、i+1的数据,不删i+2
d2.clear();//清空所有数据
3.8 数据存取
deque<int>d2 = { 0,1,2,3,4 };
cout << d2[2] << endl;
cout << d2.at(2) << endl;
cout << d2.front() << endl;//返回第一个元素
cout << d2.back() << endl;//返回最后一个元素
4. stack容器
4.1 定义:栈,先进后出,不可遍历,只能使用栈顶数据
4.2 头文件:
include <stack>
4.3 构造
stack<int>s1;
stack<int>s2(s1);
4.4 赋值
stack<int>s3;
s3 = s1;
4.5 数据存取
stack<int>s1;
s1.push(1);//把1入栈
cout << s1.top() << endl;//获取最上面的数据
s1.pop();//把最上面的数据出栈
4.6 大小操作
cout << s1.empty() << endl;//判断s1是否为空
cout << s1.size() << endl;//返回s1的大小(元素个数)
5. queue容器
5.1 定义:队列,先进先出,尾进头出,不可遍历
5.2 头文件:
include <queue>
5.3 构造
queue<int>q1;
queue<int>q2(q1);
5.4 赋值
queue<int>q3;
q3 = q1;
5.5 数据存取
queue<int>q1;
q1.push(1);//把1入队
q1.push(2);
cout << q1.front() << endl;//输出队头
cout << q1.back() << endl;//输出队尾
q1.pop();//把队头出队(删除)
5.6 大小操作
cout << q1.empty() << endl;//判断q1是否为空
cout << q1.size() << endl;//输出q1大小(元素个数)
6. list容器
6.1 定义:链表,链式存储,插入、删除方便
6.2 头文件:
include <list>
6.3 构造
list<int>l1;
list<int>l2(l1.begin(),l1.end());
list<int>l3(3, 1);//创建l3,并赋初值3个1
list<int>l4(l1);
6.4 大小操作
cout << l2.empty() << endl;
cout << l2.size() << endl;
l2.resize(3);
l2.resize(5, 1);//容量不足5时用1填充
6.5 插入
list<int>l2;
list<int>::iterator i = l2.begin();
l2.push_back(1);//1
l2.push_front(0);//01
i = l2.insert(i, 2);//012 因为i已不在是头部位置
i = l2.begin();//重新初始化
i = l2.insert(i, 3, 1);//111012
6.6 删除
l2.pop_back();
l2.pop_front();
i = l2.begin();//1101
i = l2.erase(i);//101
//i = l2.erase(i,i+2);//链表的迭代器每次只能+1,+n报错
i++;//迭代器移动一个位置
i++;//迭代器移动一个位置
i = l2.erase(l2.begin(),i);//1
l2.push_back(1);
l2.push_back(1);
l2.push_back(2);
l2.push_back(2);//11122
l2.remove(1);//删除链表中所有的1
l2.clear();清空
6.7 数据存取
cout << l2.front() << endl;//返回链表头
cout << l2.back() << endl;//返回链表尾
6.8 链表排序、反转
l2.sort();//从小到大排序
l2.reverse();//反转
按类中某变量排序:
#inlcude<iostream>
#include<list>
using namespace std;
//仿函数实现排序按年龄从大到小排列
bool lssort(Person p1, Person p2)
{
return p1.p_age > p2.p_age;
}
//仿函数实现打印Person类的年龄
void Print2(Person p)
{
cout << p.p_age;
}
int main()
{
list<Person>l1;
Person p1,p2;
p1.p_age = 3;
p2.p_age = 5;
l1.push_back(p1);
l1.push_back(p2);
l1.sort(lssort);
for_each(l1.begin(), l1.end(), Print2);
cout << endl;
system("pause");
return 0;
}
7. set/multiset容器
7.1 定义:集合,元素插入时自动排序
7.2 头文件:
include <set>
7.3 构造、赋值
set<int>s1,s3;
set<int>s2(s1);
s3 = s1;
7.4 插入、删除
set<int>s1;
s1.insert(2);//只有这一种插入方式,因为可以自动排序
s1.insert(3);
s1.insert(1);
s1.insert(5);
s1.insert(4);//12345
set<int>::iterator i = s1.begin();
i = s1.erase(i);//2345
i++; i++;//与list一样不能i+n
i = s1.erase(s1.begin(),i);//45
7.5 大小、交换
cout << s1.size() << endl;
cout << s1.empty() << endl;
s1.swap(s3);//s1和s3交换
7.6 查找、统计
set<int>s1;
s1.insert(2);
s1.insert(3);
s1.insert(1);
s1.insert(5);
s1.insert(4);//12345
set<int>::iterator i = s1.begin();
i = s1.find(3);//查找数据3,若存在返回数据的迭代器位置;不存在则返回s1.end()
s1.insert(3);//还是12345,因为set不允许重复
int num = s1.count(3);//统计3的个数
cout << num << endl;
7.7 set、multiset的区别:set不可插入重复数据,可以插入但只显示一个;multiset可以插入重复数据。
8. map/multimap容器
8.1 定义:key-value容器,自动按key值大小排序,元素全是对组
优点:可以根据key值快速找到value值
8.2 头文件:
include <map>
8.3 map不允许重复key值,multimap允许重复key值
8.4 pair对组
对组的两种构造方法:
pair<int, int>p1(1, 100);
pair<int, int>p2 = make_pair(2, 200);
8.5 构造
map<int, int>m1,m3;
map<int, int>m2(m1);
m3 = m1;
8.6 插入
map<int, int>m1;
m1.insert(pair<int, int>(1, 100));
m1.insert(make_pair(2, 200));
m1[3]=300;
//遍历map中的数据
for (map<int, int>::iterator i = m1.begin(); i != m1.end(); i++)
{
cout << i->first << ' ' << i->second << endl;
}
8.7 删除
map<int, int>::iterator i = m1.begin();
i = m1.erase(i);//删除迭代器i指向的对组值,返回下一个迭代器位置
i++; i++;// 与 list、set一样不能i+n
i=m1.erase(m1.begin(),i);
m1.erase(4);//删除key值为4的对组
m1.clear();//清空
8.8 大小、交换
cout << m1.size() << endl;
cout << m1.empty() << endl;
m1.swap(m2);
8.9 查找、统计
map<int, int>::iterator i = m1.begin();
i = m1.find(3);//查找key值为3的对组,并返回其迭代器位置
int num = m1.count(2);//统计key为2的对组数量
cout << num << endl;