目录
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
所有容器都有.size()函数以及.empty()函数,.swap()函数下面列举的容器也都有。
但是.shrink_to_fit()函数只有string ,vector,deque有
.resize()只有string,vector,deque有
一.字符串string类
#include <string>
头文件为<string>
如果有窗口中的代码省略了一些东西是因为下面这些有关的代码都在同一文件中,唯独vector那里写的代码是各自独立的
1.string的一些创建
//string的一些创建 string s1; //默认初始化,s1是个空字符串 string s2 = s1; //s2是s1的副本,s2只是与s1的值相同,不是指向同一段地址 string s3 = "hiyaaaa"; //s3是该字符串字面值的副本 string s4(10, 'c'); //s4的内容是"cccccccccc"; string str2(s3, 3, 5); //将str2初始化为s3中从第3位置长度为5的字符 string str3(s3, 3); //将str3初始化为s3中从第3位置到末尾的字符 string str4("hellonihao", 5); //将str4初始化为从字符串常量开头往后5字节的内容(会输出hello)
2.string 的读入和输出:
//string 的读入和输出: cin >> s1; cout << s1 << endl;; printf("%s", s1.c_str()); //printf不能直接输出string,要写成这样,用.c_str()函数 //用getline读入一整行 string s; getline(cin, s); cout << s << endl; //关于c风格字符串的其他事情: char ss[20]; fgets(ss, 20, stdin); //用法类似于被弃用的gets,只不过第二参数要包括结尾的'\0' cin.getline(ss, 20); //往ss中读入一行
3.string的一些操作
//string支持>,<,>=,<=,==,!=等所有比较操作,按字典顺序进行比较 bool flag = s1 == s3; //字面值和string对象相加: string ss1 = "hello", ss2 = "world"; string ss3 = s1 + "," + s2 + '\n'; //当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string: //string的.empty()函数,来判断当前容器是否为空 string arr1, arr2 = "1231"; cout << arr1.empty() << endl; cout << arr2.empty() << endl; //string 的.size()函数,输出字符串里面字符的大小 cout << arr1.size() << endl; cout << arr2.size() << endl; string sp1 = "helelo"; int a=sp1.rfind("el"); //从右边去找,并返回第一个字母所在位置 int b = sp1.find("el"); //从左边去找,并返回第一个字母所在位置 cout << a << endl; cout << b << endl;
4.彻底清空string 容器的函数
//彻底清空string 容器的函数(.clear()并不会释放内存空间,只会把size()清零 s1.clear(); //使用shrink_to_fit()函数前,先用clear()清空 s1.shrink_to_fit(); //将s1多余的空间(未使用)释放 cout << "Capacity after shrink_to_fit() is " << s1.capacity()<< " and size is " << s1.size() << '\n'; string().swap(s3); //将s3清零并释放 cout << "Capacity after swap() is " << s3.capacity() << " and size is " << s3.size() << '\n';
5.string,2024.4.14新更新的一些操作:
#include <iostream> #include <string> using namespace std; #define endl "\n" //将endl宏定义为"\n" int main() { //.substr 获得子串 string s; s = "hellow"; string s2 = s.substr(1,3);//返回从s的1位置开始,长度为3的子串 string s3 = s.substr(2);//返回从s的2位置开始到结束的子串 cout << s2 << endl; cout << s3 << endl; //字符串1.append(字符串2,起始位置index,复制元素个数n); 末尾添加 string s4 = "nihao"; s.append(s4); //在s末尾添加s4 cout << s << endl; s.append(s4, 3); //在末尾添加s4从3位置开始到结束的字符 cout << s << endl; s.append(s4, 0, 3); //在末尾添加s4从0位置到3为止的字符 cout << s << endl; //assign 清空后替换 s.assign("oo"); //先把s内容清空,然后替换为oo cout << s << endl; s.assign(s4); //先把s内容清空,然后替换为s4 cout << s << endl; s.assign(s4, 0, 4); //替换为s4从0位置开始长度为4的字符串 cout << s << endl; s.assign(s4, 2); //替换为s4从2位置开始到末尾的字符串 cout << s << endl; s.assign("wwwwwww", 3); //替换为字符数组或c风格字符串的前3个字符 cout << s << endl; s.assign(4, 'x'); //替换为4个'x'; cout << s << endl; //.insert 插入 string s5 = "lets go"; s5.insert(0, " nihao "); //在s5的第0位置插入该字符串 cout << s5 << endl; s5.insert(0, s4); //在0位置插入s4 cout <<s5<< endl; s5.insert(0, s4, 2, 3); //在0位置插入s4从2开始的3个长度的字符串 cout << s5 << endl; s5.insert(0, " w w w x xx ", 4); //在0位置插入字符数组或c语言风格字符串的前4个字符 cout << s5 << endl; s5.insert(0, 8, ' '); //在0位置插入8个' ' cout << s5 << endl; // .erase 删除 s5.erase(0,8); //删除s5从0位置开始,长度为8的字符串 cout << s5 << endl; s5.erase(0); //删除s5从0位置开始到结束的字符串 cout << s5 << endl; //.find string s6 = "abcd"; cout << s6.find("bc")<<endl; //从左查找bc第一次出现的位置 cout << s6.find("bcde",0,4)<<endl; //从左查找bcde的前4个字符的第一次出现的位置 //.rfind string s7 = "abcdabcd"; cout << s7.rfind("cd") << endl; cout << s7.rfind("cd", 2) << endl; //虽从2到0位置查找,但还是正向匹配,也就是在第2位置往后找cd,若能找到,还是返回有效值 cout << s7.rfind("cdd", 2,1) << endl; //从2到0位置查找cdd的前1个字符出现的首位置 string ss = "cd"; cout << s7.rfind(ss,2) << endl; //从2到0位置查找ss变量出现的首位置(没第3个参数了) //.replace 替换 即将字符串中的某些字符替换成其他的字符 string s8 = "xxxx"; s8.replace(2, 1, "abc"); //从第2位置往后1个长度替换成abc cout << s8 << endl; //输出xxabcx s8 = "xxxx"; string aa = "abcd"; s8.replace(s8.begin(), s8.begin() + 2, aa); //从开始位置到第2位置(不包括第2位置)更换成aa("abcd"), cout << s8 << endl; s8 = "xxxxx"; s8.replace(1, 3, 8, 'c'); //从第1位置到第3位置(包括第3位置)替换位8个c cout << s8 << endl; s8 = "xxxxx"; string cc = "ccc"; s8.replace(1, 3, cc, 1, 2); //从第位置到第3位置(包括第3位置)替换为cc中从第1位置往后2个长度的字符 cout << s8 << endl; }
二.vector容器
#include <vector>
头文件为 <vector>
1.vector的一些创建:
vector<int>a; //相当于一个长度动态变化的int数组 vector<int>b[233]; //相当于第一维长233(不可改变),第二位长度动态变化的int数组 vector<double>c(20, 2.2); //创建了一个大小为20的,且内容全为2.2的double数组 int n = 4, m = 5; vector<vector<int>>aa(n, vector<int>(m)); //相当于创建了4*5的二维数组 //其他方法创建二维数组 vector<vector<int>>aa2(n); for (int i = 0; i < n; i++) aa2[i].resize(m, 1); vector<int>arr1(5,1); vector<int>arr2(arr1); //将arr1中的元素复制到arr2中 vector<string>str1(5, "nihao"); vector<string>str2(str1.begin(),str1.end()); //将str1的元素复制到str2中 vector<int>shuzu1={ 1,23,4,5 }; //shuzu1初始化为1,23,4,5 vector<int>shuzu2({ 1,23,4,5 }); //shuzu2初始化为1,23,4,5
2.vector的一些操作:
//.size()输出大小,.empty()判断是否为空,.clear()清空,但无法释放内存 vector<int>a(5, 2); cout << a.size() << endl; cout << a.empty() << endl; a.clear(); cout << a.size() << endl; cout << a.empty() << endl; vector<int>b({ 11,2,3,4,5 }); cout << b.front() << endl; //.front()返回第一个元素 cout << b.back() << endl; //.back()返回最后一个元素 int x = 555; b.push_back(x); //.push_back(x)把元素x插入到尾部 b.pop_back(); //.pop_back()删除最后一个元素 //迭代器,类似于指针,可以用来解引用 for (vector<int>::iterator it = b.begin(); it != b.end(); it++) cout << *it << endl; cout << endl; for (auto it = b.begin(); it != b.end(); it++) //方便起,可以用auto关键字 cout << *it << endl; //.begin()返回vector中第一个元素的迭代器,.end()返回vector的尾部,即其中最后元素的下一个位置 //利用迭代器运用binary_search()函数(头文件为<algorithm>)去寻找值, vector<int>::iterator ie = b.begin(); bool cc = binary_search(b.begin(), ie+3,3 ); cout << endl<< cc << endl;
3.vector的彻底清空并释放内存:
vector<int>a(50, 2); cout << a.capacity() << "\t" << a.size() << endl; a.clear(); //用.shrink_to_fit()函数前,先用clear()清空 a.shrink_to_fit(); cout << a.capacity() << "\t" << a.size() << endl; vector<int>b(50, 2); cout << b.capacity() << "\t" << b.size() << endl; vector<int>().swap(b); //利用交换来清空 cout << b.capacity() << "\t" << b.size() << endl;
ps:
在参考链接那里,有个文章的vector的swap清空写错了,应该改为:vector<int>().swap(nums)
4.vector 2024.4.14更新的一些操作:
#include <iostream> #include <string> #include <vector> using namespace std; #define endl "\n" //将endl宏定义为"\n" int main() { int i = 0; vector<int>a(10); //insert 插入 a.insert(a.begin(), 4); //向该迭代器位置插入4 for (auto k : a) { cout << i++<<"\t" << k << endl; } cout << endl; i = 0; a.insert(a.begin(), 3, 5); //向该迭代器位置插入3个5 for (auto k : a) { cout << i++ << "\t" << k << endl; } //.erase 删除 cout << endl; i = 0; a.erase(a.begin()); //清除迭代器指向元素 for (auto k : a) { cout << i++ << "\t" << k << endl; } cout << endl; i = 0; a.erase(a.begin(),a.begin()+4); //清除迭代器指向元素 for (auto k : a) { cout << i++ << "\t" << k << endl; } }
三.queue,priority_queue队列
#include <queue>
头文件为<queue>
包含queue和priority_queue
queue和priority_queue不存在迭代器,也就无法用基于范围的for循环
队列是先进先出的结构,从队尾插入,队头弹出
循环队列:queue
1.循环队列的创建以及操作
push // 从队尾插入 pop // 从队头弹出 front // 返回队头元素 back // 返回队尾元素
queue<int> q; //循环队列 //队列没有迭代器,无法遍历输出。 for(int i=0;i<4;i++) { q.push(29 + i); //.push()往队尾插入 } cout << q.front() << endl; //.front()返回队头元素 cout << q.back() << endl; //.back()返回队尾元素 q.pop(); //.pop()删除队头元素 cout << q.front() << endl;
优先队列:priority_queue
1.优先队列创建以及操作
push // 把元素插入堆 pop // 删除堆顶元素 top // 查询堆顶元素(最大值)
#include <iostream> #include <vector> #include <queue> using namespace std; struct ps1 { int a; int b; bool operator <(const ps1& j)const //重载小于号 { return a < j.a; } }; int main() { //优先队列里没有.front()以及.back() priority_queue<int>q; //优先队列,默认大根堆,即堆顶元素为最大值 priority_queue<int, vector<int>, greater<int>>p; //小根堆 priority_queue<ps1>ps; //优先队列,类型为结构体,默认大根堆,要重载小于号, ps.push({ 2, 3 }); //把结构体元素插入堆 ps.push({ 22,33 }); cout << ps.size() << endl; //.size()输出元素长度 cout << ps.top().b << endl; //.top()查询堆顶元素(默认大根堆的话,就是最大值) ps.pop(); //.pop()删除堆顶元素 cout << ps.top().b << endl; cout << ps.empty() << endl; //.empty()判断是否为空 //队列的清空,队列没有.clear()函数 ps = priority_queue<ps1>(); //可以让队列等于一个空队列,来清空里面的值 cout << ps.empty() << endl; //.empty()判断是否为空 priority_queue<ps1>().swap(ps); //通过与空队列交换来释放空间 return 0; }
四.stack栈
#include <stack>
头文件为<stack>
stack不存在迭代器,也就无法用基于范围的for循环
栈,后进先出,栈顶插入,栈顶弹出
1.栈的创建以及操作
push // 向栈顶插入 pop // 弹出栈顶元素 top // 查询栈顶元素
stack<int> a; //定义栈a a.push(50); //.push()向栈顶插入 a.push(3); a.push(100); cout << a.top() << endl; //.top()查询栈顶元素 a.pop(); //.pop()弹出栈顶元素 cout << a.top() << endl; cout << endl; cout << a.size() << endl; stack<int>().swap(a); //通过交换空栈来释放空间 cout << a.size() << endl;
五.deque双端队列
#include <deque>
头文件为<deque>
双端队列deque是一个支持在两端高效插入或删除元素的连续线性存储空间。它就像是vector和queue的结合。与vector相比,deque在头部增删元素仅需要 O(1) 的时间;与queue相比,deque像数组一样支持随机访问。
1.双端队列的创建以及操作
[] // 随机访问 begin/end // 返回deque的头/尾迭代器 front/back // 队头/队尾元素 push_back // 从队尾入队 push_front // 从队头入队 pop_back // 从队尾出队 pop_front // 从队头出队 clear // 清空队列
#include <iostream> #include <vector> #include <deque> using namespace std; int main() { deque<int>q(5, 2); //初始化双端队列q,元素个数是5,都为2; deque<int>p = { 1,2,3 }; //初始化为1,2,3 for (auto k : q) cout << k << " "; cout << endl; for (auto k : p) cout << k << " "; cout << endl; cout << p.front() << endl; //.front()返回队头元素 cout << p.back() << endl; //.back()返回队尾元素 p.push_back(55); //.push_back()队尾入队 p.push_front(33); //.push_front()队头入队 for (auto k = p.begin(); k != p.end(); k++) //.begin()返回双端队列的头迭代器,.end()返回双端队列的尾迭代器 cout << *k << " "; cout << endl; p.pop_back(); //.pop_back()从队尾出队 for (auto k = p.begin(); k != p.end(); k++) cout << *k << " "; cout << endl; p.pop_front(); //.pop_front()从队头出队 for (auto k = p.begin(); k != p.end(); k++) cout << *k << " "; cout << endl; p[0] = 999; for (auto k = p.begin(); k != p.end(); k++) cout << *k << " "; cout << endl; deque<int>().swap(p); //与空双端队列交换,来释放内存 cout << p.size() << endl; return 0; }
六.set,multiset集合
#include <set>
头文件为<set>
里面有set有序集合与multiset多重有序集合
由于set与multiset的操作一模一样,就以multiset为例:
有迭代器,无法用[ ]运算符
1.multiset的创建:
struct rec { int a, b; bool operator <(const rec& j)const { return a < j.a; //重载小于号 } }; set<int>ss; //创建int型有序集合,默认升序 multiset<int>s; //创建有序多重集合,默认升序 set<rec>s1; //创建结构体的有序结合(需要重载小于号)
2.multiset的一些操作和其迭代器
s.insert(5); //.insert(x)把一个元素x插入到集合中 s.insert(5); //在set中,如果元素已经存在,则不会重复插入 for (int i = 0; i < 4; i++) { s.insert(i); } cout << s.count(5) << endl; //.count(x)来返回集合中等于x的元素个数 set<int>::iterator it = s.begin(); //.begin()返回集合中第一个元素的迭代器 for (it; it != s.end(); it++) //set的迭代器不支持随机访问(无法用[]),支持星号*解引用,仅支持++和--两个与算术相关的操作 cout << *it << " "; //it++,则是指向升序过程中,排在it后的下一个元素。而it--则是上一个元素 cout<<endl; if (s.find(4) == s.end()) cout << "no" << endl; //.find(x)在集合中寻找等于x的元素,若不存在返回s.end(),若存在返回指向 auto p = s.lower_bound(3); //.lower_bound(x)查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器 auto p1 = s.upper_bound(3);//.upper_bound(x)查找大于x的元素中最小的一个,并返回指向该元素的迭代器 cout << *p << endl; cout << *p1 << endl; s.erase(p); //.erase(it),若it是一个迭代器,则是从s中删除迭代器it指向的元素 s.erase(5); //.erase(x)从s中删除所有等于x的元素 for (auto k : s) { cout << k << " "; }
3.multiset的清空和释放
s.clear(); //清空s集合 multiset<int>().swap(s); //也可以通过与空集合swap来清空并释放空间 cout <<"\n"<< "size=" << s.size() << endl;
4.set 2024.4.14更新的一些操作:
#include <iostream> #include <vector> #include <set> using namespace std; #define endl "\n" //将endl宏定义为"\n" int main() { set<int, greater<int>>p; //升序的set p.insert(3); p.insert(4); for (auto k : p) { cout << k << endl; } }
七.map容器
#include <map>
头文件为<map>
map容器是一个键值对key-value的映射,其内部实现是一棵以key为关键码的红黑树。Map的key和value可以是任意类型,其中key必须定义小于号运算符。
且map是有序的,根据key大小按照字典进行排序
有迭代器,可以用[ ]运算符
1.map的创建
struct rec { int a, b; bool operator <(const rec& j)const { return a < j.a; //重载小于号 } }; //map<key_type, value_type> name; map<int, int>arr; map<string, int>his; //定义string对int的映射 map<int, vector<int>>ve; //定义int对vector<int>的映射 ve[1] = { 1,2,3333,4,5 }; ve[0] = vector<int>({ 1,2122,3 }); cout << ve[1][2] << endl; cout << ve[0][1] << endl; his["nihao"] = 23; his["tashi"] = 56; cout << his["nihao"] << endl; map<rec, int>hh; //定义结构体对int的映射,结构体里必须重载小于号运算符 rec ad; hh[ad] = 4; cout << hh[ad] << endl;
2.map的一些操作
cout << his.size() << endl; //.size()输出大小 cout << his.empty() << endl; //.empty()判断是否为空 arr.insert({ 1,2 }); //.insert()插入元素,参数是pair<key_type,value_type> arr.insert({ 11,22 }); arr.insert({ 111,222 }); arr.erase(11); //.erase(x)删除key为x的元素 //map是有迭代器的 for (map<int, int>::iterator it = arr.begin(); it != arr.end(); it++) cout << (*it).first <<" "<<(*it).second << endl; auto it = arr.find(111); //.find(x)是寻找key为x的二元组,找到返回对应迭代器,找不到返回.end() cout << (*it).first<<" "<<(*it).second << endl; it = arr.lower_bound(1); //.lower_bound(x)是寻找第一个大于等于key为x的二元组,找到返回对应迭代器,找不到返回.end() cout << (*it).first << " " << (*it).second << endl; it = arr.upper_bound(1);//.upper_bound(x)是寻找第一个大于key为x的二元组,找到返回对应迭代器,找不到返回.end() cout << (*it).first << " " << (*it).second << endl;
3.map的清空和释放
his.clear(); //将his容器清空 map<int, int>().swap(arr); //通过与空map交换来清空并释放空间 cout << arr.size() << endl;
4.map 2024.4.14更新的一些操作:
#include <iostream> #include <vector> #include <map> using namespace std; #define endl "\n" //将endl宏定义为"\n" int main() { map<int, int, greater<int>>arr; //升序map arr.insert({ 2,3 }); arr.insert({ 5,6 }); for (auto k : arr) { cout << k.first <<" " << k.second << endl; } }
八.unordered_set无序集合
#include <unordered_set>
头文件为: <unordered_set>
包含unordered_set与unordered_multiset
操作与set和multiset一样,只是没有.upper_bound()和.lower_bound()函数,因为是无序的
//unordered_set没有.upper_bound()和.lower_bound()函数,因为是无序的
unordered_set<int>a; //哈希表,无序集合,不能存储重复元素
unordered_multiset<int>b; //哈希表,可以存储重复元素
九.unordered_map无序map容器
#include <unordered_map>
头文件为<unordered_map>
用法和map一样
效率更高,但因为无序不支持二分
unordered_map<int, int>c; //效率更高,不支持二分
十.bitset二进制串
#include <bitset>
头文件为<bitset>
可以看成二进制串
1.bitset的一些创建和操作
#include <iostream> #include <vector> #include <bitset> //二进制串 using namespace std; int main() { bitset<1000>a,b; //定义了一个长度为1000位的01串,默认为0 a[0] = 1; //第一个位置为1, a[1] = 1; cout << a.count() << endl; //返回该串1的个数 a &= b; //将a与b进行位运算 a |= b; a.set(3); //把第3为设置成1 cout << a[3] << endl; a.reset(3); //把第3为设置成0 cout << a[3] << endl; return 0; }
十一.pair<key_type,value_type>二元组
pair是一个二元组,可支持比较运算
1.pair二元组的创建和操作
#include <iostream> #include <vector> using namespace std; int main() { //pair<key_type,value_type> pair<int, string> a; //定义一个二元组 a = { 3,"abc" }; //给a赋值 cout << a.first << " " << a.second << endl; //输出里面的值 a = make_pair(4, "123"); //在c++99里面必须用该函数赋值 cout << a.first << " " << a.second << endl; pair<int, string>b; b.first = 999; b.second = "123"; cout << b.first << " " << b.second << endl; //二元组支持比较运算,>,<,=...先比较第一个数,再比较第二个数 if (a == b) cout << "yes" << endl; else cout << "no" << endl; //vector也支持比较运算,按照字典大小先从第一个元素开始,然后第二个,第三个 vector<int>c, d; if (c > d); return 0; }
十二.基于范围的for循环的一些用法
#include <iostream>
using namespace std;
int main()
{
int dxy[][2] = { {0,1},{0,-1},{1,0},{-1,0} };
for (auto [dx, dy] : dxy) //需要c++17标准,dx指向dxy[][0],dy指向dxy[][1],且必须用[dx,dy]语法
{
cout << "dx=" << dx << " dy=" << dy << endl;
}
int a[5] = { 1,2,3,4,5 };
for (auto k : a)
{
cout << k << "\t" << endl;
}
int b[5] = { 1,2,3,4,5 };
for (auto& k : b) //用引用可以改变数组里面的值
{
k += 2;
}
for (int i = 0; i < 5; i++)
cout << b[i] << "\t";
return 0;
}
参考:
【C++】string 之 find、rfind、replace、compare函数的学习_string find-CSDN博客
【C++】如何释放vector的内存空间及std::vector::shrink_to_fit用法简介_vector shrink_to_fit-CSDN博客
string对象的内存释放_如何将string内存清空-CSDN博客
C++ string清空并释放内存空间的两种方法(shrink_to_fit()、swap())_c++ string 释放-CSDN博客
顺序容器: 内存管理(shrink_to_fit、capacity、reserve)-CSDN博客
c++使用vector创建二维数组的方法_利用vector定义二维数组-CSDN博客
C++ vector用法详解_vector c++ 用法-CSDN博客
C++11新特性:基于范围的循环(foreach)_c++11 foreach-CSDN博客
C++ map与unordered_map区别及使用_c++中的map和unordered_map的区别和使用场景-CSDN博客 c++ unordered_map和map的区别-CSDN博客