C++STL容器部分
定长数组
-
array
-
#include <array> #include <iostream> #include <string> using namespace std; //size_t unsigned int template <class _Ty,size_t size> class MyArray { public: MyArray() { memroy = new _Ty[size]; //new MM[size] } _Ty& operator[](int index) { return memroy[index]; } ~MyArray() { delete[] memroy; } public: _Ty* begin() { return memroy + 0; } _Ty* end() { return memroy + size; } //类的对象模仿指针的行为 class iterator { public: iterator(_Ty* pmove = nullptr) :pmove(pmove) {} void operator=(_Ty* pmove) { this->pmove = pmove; } bool operator!=(_Ty* pmove) { return this->pmove != pmove; } iterator operator++(int) { this->pmove++; return *this; } _Ty operator*() { return pmove[0]; } protected: _Ty* pmove; }; protected: _Ty* memroy; //MM }; void testMyArray() { MyArray<int, 3> array1D; for (int i = 0; i < 3; i++) { array1D[i] = i; } MyArray<int, 3>::iterator iter; for (iter = array1D.begin(); iter != array1D.end(); iter++) { cout << *iter << "\t"; } cout << endl; } void testArray() { //存储数据的类型是:int //数组长度:3 //用模板的时候用的都是对象,而不是new一个对象 array<int, 3> array1D; array<string, 3>* p = new array<string, 3>; delete p; #define MAX 5 array<double, 5> dAarray1D; //创建并初始化 array<int, 3> num = { 1,2,3 }; for (int i = 0; i < array1D.size(); i++) { array1D[i] = i; } //迭代器 } void testExOperator() { //使用: 和数组一样的用法 //一些函数 array<int, 3> test = { 1,2,3 }; cout << test.empty() << endl; cout << test.size() << endl; test.fill(5); //填充所有的元素 ,填充为5 for (int v : test) { cout << v << "\t"; } cout << endl; //交换 长度一定是要一样常 array<int, 3> test1 = { 0,0,0}; test.swap(test1); int cData[3] = { 1,2,3 }; //映射:一种对应关系,数组下标对应元素 for (auto v : cData) { cout << v << "\t"; } cout << endl; } //定长数组处理自定义类型的数据 class MM { public: MM() {} MM(string name, int age) :name(name), age(age) {} void print() { cout << name << "\t" << age << endl; } protected: string name; int age; }; void testUserData() { array<MM, 3> mmData; // MM array[3]; for (int i = 0; i < mmData.size(); i++) { string name = "name"; mmData[i] = MM(name + to_string(i), 16 + i); } for (auto v : mmData) { //v:就是MM的对象 v.print(); //cout<<v; //想要这样输出,重载<<运算符 } //迭代器访问 //对象模仿指针,*迭代器 就是取值运算 array<MM, 3>::iterator iter; //begin() //end(): 最后一个位置,不是最后元素的位置 (*mmData.begin()).print(); //(*mmData.end()).print(); 越界访问 (*(mmData.end() - 1)).print(); for (iter = mmData.begin(); iter != mmData.end(); iter++) { //(*iter).print(); iter->print(); //cout<<*iter; //重载<< } } //array当做函数参数,返回值都可以 array<int, 3>& returnArray(array<int, 3>& temp) { for (int i = 0; i < temp.size(); i++) { temp[i] = i; } return temp; } int main() { testArray(); testExOperator(); testUserData(); cout << "自己写的模板" << endl; testMyArray(); return 0; }
动态数组
-
vector
#include <vector> #include <iostream> #include <string> using namespace std; //辅助函数:遍历容器 template <class _Ty> void printVector(vector<_Ty>& temp) { for (auto v : temp) { cout << v << "\t "; } cout << endl; } //基本用法 void testCreateVector() { //模板类型:存储数据类型 //1.不带长度的创建方式 vector<int> vecData; //只能用成员函数做插入 for (int i = 0; i < 3; i++) { vecData.push_back(i); //尾插法 0 0 1 0 1 2 } printVector(vecData); //2.带长度 vector<string> strData(3); //当前动态数组的长度是3 //确定长度,可以直接使用数组法插入 for (int i = 0; i < 3; i++) { string name = "name"; //只有在确定长度范围以内的可以直接采用数组法插入 strData[i] = name + to_string(i); } printVector(strData); //超过的必须用成员函数插入 //strData[3] = "name3"; vector subscript out of range 错误 strData.push_back("name3"); //在这个函数中做了自动扩增 printVector(strData); //3.带初始化 vector<double> dData = { 1.1,1.23,1.44 }; //自动算出长度为3 printVector(dData); //猜谜 vector<int> intData(3); intData.push_back(1111); //在原来内存的后面扩增 printVector(intData); //0 0 0 1111 //迭代器遍历 vector<string>::iterator iter; for (iter = strData.begin(); iter != strData.end(); iter++) { cout << *iter << "\t"; } cout << endl; } //自定义类型数据 class MM { public: MM(string name, int age) :name(name), age(age) {} friend ostream& operator<<(ostream& out, const MM& temp) { out << temp.name << "\t" << temp.age; return out; } protected: string name; int age; }; void testUserData() { vector<MM> mmData; for (int i = 0; i < 3; i++) { string name = "name"; mmData.push_back(MM(name + to_string(i), 18 + i)); } //二进制“<<”: 没有找到接受“MM”类型的右操作数的运算符(或没有可接受的转换) printVector(mmData); } void testExOperator() { vector<int> iData = { 1,2,3,4 }; cout << iData.size() << endl; //当前容器中的元素个数 cout << iData.empty() << endl; //判断是否为空 return size==0; 有元素返回false cout << iData.front() << endl; //访问第一个元素 cout << iData.back() << endl; //访问最后一个元素 cout << iData.at(2) << endl; //下标访问 cout << iData[2] << endl; //和at(2)一样的效果 表示 //修改 iData.emplace(iData.begin() + 2, 100); //修改下标是2位置的元素为100 printVector(iData); iData.emplace_back(999); //和push_back一样的功能 iData.emplace(iData.begin(), 1111); //修改第一个元素 //删除函数 //iData.erase(iData.begin() + 2); //数组只有伪删除,没有删除操作 printVector(iData); //批量复制 int array[] = { 1,2,3 }; vector<int> vecData; vecData.assign(array, array + 3); //不需要起始长度 printVector(vecData); } int main() { testCreateVector(); testUserData(); testExOperator(); return 0; }
array与vector嵌套
-
#include <iostream> #include <array> #include <vector> #include <string> #include <ctime> #include <cstdlib> using namespace std; void testArrayVsArray() { array<array<int, 3>, 4> arrData; //int arrData[4][3] for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { arrData[i][j] = i * j; cout << arrData[i][j] << "\t"; } cout << endl; } } void testVectorVsVector() { srand((unsigned int)time(nullptr)); vector<vector<int>> vecData; //一般vecotor 采用的是push_back插入 for (int i = 0; i < 4; i++) { vector<int> temp; //rand()%3 [0,2] [2,4] for (int j = 0; j < rand()%3+2; j++) { temp.push_back(i * j); } vecData.push_back(temp); } //不等列数的二位数组 for (int i = 0; i < vecData.size(); i++) { for (int j = 0; j < vecData[i].size(); j++) { cout << vecData[i][j] << "\t"; } cout << endl; } } void testArrayVsVector() { array<vector<int>, 3> vecArr; vector<int> vec1[3] = { { 1,2,3 } , {1,2,3,4}, {1,2}}; for (int i = 0; i < vecArr.size(); i++) { vecArr[i] = vec1[i]; } //不等列数的二位数组 for (int i = 0; i < vecArr.size(); i++) { for (int j = 0; j < vecArr[i].size(); j++) { cout << vecArr[i][j] << "\t"; } cout << endl; } vector<array<array<vector<int>, 3>, 3>> vec; //慢慢剥洋葱即可 array<array<vector<int>, 3>, 3> test; for (int i = 0; i < 3; i++) { test[i] = vecArr; //vecArr: array<vector<int>, 3> } vec.push_back(test); vector<array<array<vector<int>, 3>, 3>> test; //上面一行 等效下面两行 using Data = array<array<vector<int>, 3>, 3>; vector<Data> test2; array<array<vector<int>, 3>, 3> test3; //上面一行 等效下面两行 using Data2 = array<vector<int>, 3>; array<Data2, 3> test3; } void testVectorVsArray() { vector<array<int, 3>> arrVec; array<int, 3> arr[3] = { { 1,2,3 } , {1,2,3}, {1,2,3}}; for (int i = 0; i < 3; i++) { arrVec.push_back(arr[i]); } for (int i = 0; i < arrVec.size(); i++) { for (int j = 0; j < arrVec[i].size(); j++) { cout << arrVec[i][j] << "\t"; } cout << endl; } } int main() { testArrayVsArray(); testVectorVsVector(); testArrayVsVector(); testVectorVsArray(); return 0; }
array与vector嵌套
#include <iostream> #include <array> #include <vector> #include <string> #include <ctime> #include <cstdlib> using namespace std; void testArrayVsArray() { array<array<int, 3>, 4> arrData; //int arrData[4][3] for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { arrData[i][j] = i * j; cout << arrData[i][j] << "\t"; } cout << endl; } } void testVectorVsVector() { srand((unsigned int)time(nullptr)); vector<vector<int>> vecData; //一般vecotor 采用的是push_back插入 for (int i = 0; i < 4; i++) { vector<int> temp; //rand()%3 [0,2] [2,4] for (int j = 0; j < rand()%3+2; j++) { temp.push_back(i * j); } vecData.push_back(temp); } //不等列数的二位数组 for (int i = 0; i < vecData.size(); i++) { for (int j = 0; j < vecData[i].size(); j++) { cout << vecData[i][j] << "\t"; } cout << endl; } } void testArrayVsVector() { array<vector<int>, 3> vecArr; vector<int> vec1[3] = { { 1,2,3 } , {1,2,3,4}, {1,2}}; for (int i = 0; i < vecArr.size(); i++) { vecArr[i] = vec1[i]; } //不等列数的二位数组 for (int i = 0; i < vecArr.size(); i++) { for (int j = 0; j < vecArr[i].size(); j++) { cout << vecArr[i][j] << "\t"; } cout << endl; } vector<array<array<vector<int>, 3>, 3>> vec; //慢慢剥洋葱即可 array<array<vector<int>, 3>, 3> test; for (int i = 0; i < 3; i++) { test[i] = vecArr; //vecArr: array<vector<int>, 3> } vec.push_back(test); vector<array<array<vector<int>, 3>, 3>> test; //上面一行 等效下面两行 using Data = array<array<vector<int>, 3>, 3>; vector<Data> test2; array<array<vector<int>, 3>, 3> test3; //上面一行 等效下面两行 using Data2 = array<vector<int>, 3>; array<Data2, 3> test3; } void testVectorVsArray() { vector<array<int, 3>> arrVec; array<int, 3> arr[3] = { { 1,2,3 } , {1,2,3}, {1,2,3}}; for (int i = 0; i < 3; i++) { arrVec.push_back(arr[i]); } for (int i = 0; i < arrVec.size(); i++) { for (int j = 0; j < arrVec[i].size(); j++) { cout << arrVec[i][j] << "\t"; } cout << endl; } } int main() { testArrayVsArray(); testVectorVsVector(); testArrayVsVector(); testVectorVsArray(); return 0; }
双向链表
-
list
#include <list> #include <iostream> #include <string> #include <functional> //less和greator头文件 using namespace std; list<int>::iterator myFind(list<int>& iNum,int data) { for (list<int>::iterator iter = iNum.begin(); iter != iNum.end(); iter++) { if (*iter == data) { return iter; } } return iNum.end(); } //基本操作: 操作基本数据类型 void testList() { list<int> iNum; list<string> strNum; //插入 strNum.push_back("string1"); //尾插发 strNum.push_back("string2"); strNum.push_front("string3"); //string3 string1 string2 //遍历 //不删除方式遍历 list<string>::iterator iter; for (iter = strNum.begin(); iter != strNum.end(); iter++) { cout << *iter << " "; } cout << endl; cout << "是否为空:" <<boolalpha<< !strNum.empty() << endl; cout << "元素个数:" << strNum.size() << endl; //删除方式遍历 //string3 string1 string2 while (!strNum.empty()) { cout << strNum.front() << " "; //back() strNum.pop_front(); //头部删除 pop_front(); } cout << endl; cout << "元素个数:" << strNum.size() << endl; //指定位置操作 //iterator find(iterator begin,iterator end,data); for (int i = 0; i < 3; i++) { iNum.push_back(i); } auto result = find(iNum.begin(), iNum.end(), 2); //没找到返回是end结束的位置 if (result == iNum.end()) { cout << "未找到指定位置" << endl; } //insert iNum.insert(result, 100); for (auto v : iNum) { cout << v << "\t"; } cout << endl; //删除函数 iNum.erase(result); for (auto v : iNum) { cout << v << "\t"; } cout << endl; //其他操作 iNum.reverse(); //反转链表 for (auto v : iNum) { cout << v << "\t"; } cout << endl; iNum.sort(less<int>()); //排序 for (auto v : iNum) { cout << v << "\t"; } cout << endl; } void testDelete() { int array[4] = { 1,2,2,3 }; list<int> data; data.assign(array, array + 4); //相同元素的删除 for (list<int>::iterator iter = data.begin(); iter != data.end(); ) { if (*iter == 2) { iter = data.erase(iter); } else { iter++; } } for (auto v : data) { cout << v << "\t"; } cout << endl; } //操作自定义类型数据 class MM { public: MM(string name, int age, int num) :name(name), age(age), num(num) {} void print() { cout << name << "\t" << age << "\t" << num << endl; } bool operator==(const string& name) const { return this->name == name; } bool operator<(const MM& object) const { return this->name < object.name; } string getName() const { return name; } int getAge() const { return age; } protected: string name; int age; int num; }; bool compareByName(const MM& object1, const MM& object2) { return object1.getName() < object2.getName(); } bool compareByAge(const MM& object1, const MM& object2) { return object1.getAge() < object2.getAge(); } void testUserData() { list<MM> mmData; string name; int age; int num; while (1) { cout << "input MM:" << endl; cin >> name >> age >> num; mmData.push_back(MM(name, age, num)); cout << "是否继续输入?" << endl; while (cin.get() != '\n'); if (cin.get() == 'n') break; } cout << "姓名\t年龄\t编号" << endl; for (MM v : mmData) { v.print(); } //二进制“==”: 没有找到接受“MM”类型的左操作数的运算符(或没有可接受的转换) auto result = find(mmData.begin(), mmData.end(), string("name1")); //重载方式 mmData.sort(less<MM>()); //重载< //mmData.sort(greater<MM>()); //重载> //不采用重载方式,需要自己写比较准则 mmData.sort(compareByName); mmData.sort(compareByAge); } int main() { //testList(); //testDelete(); testUserData(); return 0; }
栈
-
stack
#include <stack> #include <iostream> #include <string> using namespace std; void testStack() { //穿脱原则 //FILO //1 2 3 //3 2 1 //push(data) //pop() 删除 //top() 获取栈顶元素 //size() empty(); stack<int> intStack; for (int i = 0; i < 3; i++) { intStack.push(i); } while (!intStack.empty()) { cout << intStack.top() << "\t"; intStack.pop(); } cout << endl; } void NumTobinary(int data) { stack<int> bin; while (data) { bin.push(data % 2); data = data / 2; } if (bin.size() < 8) { for (int i = bin.size(); i < 8; i++) { bin.push(0); } } while (!bin.empty()) { cout << bin.top(); bin.pop(); } cout << endl; //中缀和后缀表达式资料看看 //a+b 中缀 //ab+ //a+b*c+d; } int main() { //testStack(); NumTobinary(512); return 0; }
队列
-
queue
#include <queue> #include <iostream> #include <string> using namespace std; void pop_queue(queue<int> qData) { while (!qData.empty()) { cout << qData.front() << " "; //获取队头元素 qData.pop(); //出队 } cout << endl; } void testQueue() { queue<int> qData; for (int i = 0; i < 3; i++) { qData.push(i); //入队 } while (!qData.empty()) { cout << qData.front() << " "; //获取队头元素 qData.pop(); //出队 } cout << endl; cout << qData.size() << endl; } int main() { testQueue(); return 0; }
deque
#include <deque> #include <iostream> #include <string> using namespace std; //从头出来 void pop_front_dequeue(deque<int> dData) { while (!dData.empty()) { cout << dData.front()<<" "; dData.pop_front(); } cout << endl; } //从尾出来 void pop_back_dequeue(deque<int> dData) { while (!dData.empty()) { cout << dData.back() << " "; dData.pop_back(); } cout << endl; } void testDeque() { deque<int> deData; for (int i = 0; i < 3; i++) { deData.push_back(i); //尾插法入队 deData.push_front(i); //头插法入队 } deData.push_back(999); //0 0 //1 0 0 1 //2 1 0 0 1 2 pop_front_dequeue(deData); pop_back_dequeue(deData); } int main() { testDeque(); return 0; }
priority_queue
#include <iostream> #include <queue> #include <vector> using namespace std; template <class _Ty,class _Container = vector<_Ty>,class _Pr = less<_Ty>> class my_priority_queue { public: protected: }; void testCreatePriorityQueue() { //默认的方式,一级下面三种 都一样,大的先出队 priority_queue<int> pqData; priority_queue<int,vector<int>> pqData2; //默认排序准则 priority_queue<int,vector<int>,less<int>> pqData3; //所有参数都完整 //优先队列,是按照数据的优先权出队,VIP服务 pqData.push(12); pqData.push(0); pqData.push(34); while (!pqData.empty()) { cout << pqData.top()<<" "; pqData.pop(); //出队 } cout << endl; //贪心算法 priority_queue<int, vector<int>, greater<int>> pqDataG; pqDataG.push(12); pqDataG.push(0); pqDataG.push(34); while (!pqDataG.empty()) { cout << pqDataG.top() << " "; pqDataG.pop(); //出队 } cout << endl; } int main() { testCreatePriorityQueue(); return 0; }
集合
-
set/multiset
#include <set> #include <iostream> #include <ctime> using namespace std; /* set:集合 1.数据自带排序 2.数据唯一性 */ class MM { public: MM(string name, int age) :name(name), age(age) {} bool operator<(const MM& object)const { return this->name < object.name; } void print() { cout << name << " " << age << endl; } protected: string name; int age; }; void testSet() { srand((unsigned int)time(nullptr)); set<int> setData; //默认方式 从小到大 set<int, less<int>> setData2; //和默认方式一样 set<int, greater<int>> setData3; //从大到小 int array[10] = { 0 }; for (int i = 0; i < 10; i++) { int temp = rand() % 10; array[i] = temp; setData.insert(temp); } for (auto v : array) { cout << v << " "; } cout << endl; for (set<int>::iterator iter = setData.begin(); iter != setData.end(); iter++) { cout << *iter << " "; } cout << endl; } void testUserData() { set<MM> mmData; //less<int> < mmData.insert(MM("name3", 19)); mmData.insert(MM("name2", 28)); mmData.insert(MM("name3", 188)); for (auto v : mmData) { v.print(); } set<char> cData; set<string> strData; } //多重集合: 只具有排序功能,不具有去重功能 void testmultiset() { multiset<int> mulData; for (int i = 0; i < 10; i++) { mulData.insert(rand() % 10); //rand()%26+'A'; //rand()%26+'a'; } for (auto v : mulData) { cout << v << " "; } cout << endl; } int main() { testSet(); testUserData(); testmultiset(); return 0; }
bitset
#include <iostream> #include <bitset> using namespace std; template <class _Ty,size_t size> class MyArray { }; int main() { //多个二进制位 bitset<8> bData("11110000"); cout << bData << endl; bData.flip(); cout << bData << endl; cout << bData.all() << endl; cout << bData.any() << endl; cout << bData.size() << endl; cout <<bData.none() << endl; bitset<8> num(7); cout << num << endl; return 0; }
映射
-
map/multiset
#include <map> #include <iostream> #include <graphics.h> using namespace std; template <class _Ty1, class _Ty2> struct MyPair { _Ty1 first; _Ty2 second; MyPair(_Ty1 first, _Ty2 second) :first(first), second(second) {} }; //map存储的数据是一个数对类型 void testPair() { pair<int, string> pData(1, "string"); MyPair<int, string> myPData(1, "string"); cout << pData.first << " " << pData.second << endl; } //map //1.自带排序,默认是从小到大 //2.数据唯一性 void testMap() { map<int, string> mapData; map<int, string, less<int>> mapData1; //和上面创建方式一样,从小到大 map<int, string, greater<int>> mapData2; //从大到小 //1.insert插入 mapData.insert(pair<int, string>(1, "string")); //2.make_pair构建数对插入 mapData.insert(make_pair<int, string>(3, "string3")); //3.单映射,可以直接采用数组下标方式进行插入 //数组在一定程序上来说或可以说数组 //map[first]=second; //相比数组来说,这个下标是没有任何要求 mapData[-1] = string("string-1"); //等效插入一个数对类型 //上面代码等效:mapData.insert(pair<int,string>(-1,"string-1")) mapData[1] = "string1"; //相同键 采用的是覆盖方式 //遍历: for (auto iter = mapData.begin(); iter != mapData.end(); iter++) { //*iter指的是pair类型 cout << iter->first << " " << iter->second<<endl; } for (auto v : mapData) { cout << v.first << "\t" << v.second << endl; } //map<string, IMAGE*> img; //img["墙"] = new IMAGE; //img["路"] = new IMAGE; //putimage(0, 0, img["墙"]); //putimage(0, 0, img["路"]); cout << mapData[1] << endl; //用的时候直接使用即可 mapData.erase(1); for (auto v : mapData) { cout << v.first << "\t" << v.second << endl; } cout << endl; } class MM { public: MM() = default; MM(string name, int age) :name(name), age(age) {} void print() const { cout << name << "\t" << age << endl; } bool operator<(const MM& object)const { return this->name < object.name; } protected: string name; int age; }; class Boy { public: Boy() = default; Boy(string name, int age) :name(name), age(age) {} void print() const { cout << name << "\t" << age << endl; } protected: string name; int age; }; void testUserData() { map<MM, Boy> mbData; mbData[MM("小美", 19)] = Boy("小张", 29); mbData[MM("小美", 19)].print(); mbData[MM("小丽", 20)] = Boy("小明", 18); cout << "配对信息:" << endl; for (auto v : mbData) { //容器管理自定义类型数据 //v:pair<MM,Boy> //v.frist:MM //v.second:Boy v.first.print(); v.second.print(); } } void testmultimap() { //多重映射,没有什么限制,什么样对应关系都可以插入到映射中 //因为存在相同的键,所以不能采用下标法 multimap<int, string> mulData; mulData.insert(pair<int, string>(1, "string")); mulData.insert(pair<int, string>(1, "string1")); mulData.insert(pair<int, string>(2, "string")); mulData.insert(pair<int, string>(3, "string")); mulData.insert(make_pair<int, string>(3, "string")); for (auto v : mulData) { cout << v.first << "\t" << v.second << endl; } } int main() { testMap(); testUserData(); testmultimap(); return 0; }
列表
-
initializer_list
#include <array> #include <list> #include <vector> #include <iostream> #include <initializer_list> using namespace std; class MM { public: MM(string a, string b, string c) :a(a), b(b), c(c) {} MM(const initializer_list<string>& list) { for (auto iter = list.begin(); iter != list.end(); iter++) { cout << *iter << endl; } } protected: string a; string b; string c; }; void print(initializer_list<int> list) { for (auto iter = list.begin(); iter != list.end(); iter++) { cout << *iter << " "; } cout << endl; } int main() { array<int, 3> arrData = { 1,2,3 }; vector<int> vecData1 = { 1,2,3,4 }; vector<int> vecData2 = { 1,2,3,4,5 }; MM mm1 = { "string1","string2","string3" }; MM mm2 = { "string1" }; MM mm3 = { "string1","string2" }; initializer_list<int> listOne = { 1,2,3,4,5 }; initializer_list<int> listTwo = { 1,2,3}; print({ 1 }); print({ 1,2 }); print({ 1,2,3,4 }); print({ 1,2,3,4,5 }); return 0; }
元组
-
tuple
#include <tuple> #include <iostream> using namespace std; void testTuple() { //把任何类型的一系列数据当做一组处理 tuple<string, int, int, string> mmInfo = {"MM",18,1001,"123445"}; tuple<double, double, double> mmscore = make_tuple(98, 98, 88); tuple<string, string> value = forward_as_tuple("小张", "小美"); tuple<string, int, int, string> array[3]; } void visitedData() { tuple<string, int, int, string> mmInfo = { "MM",18,1001,"123445" }; //get方法,不能用for循环 cout << get<0>(mmInfo) << "\t"; cout << get<1>(mmInfo) << "\t"; cout << get<2>(mmInfo) << "\t"; cout << get<3>(mmInfo) << endl; //tie的方式访问数据 string name; int age; int num; string tel; tie(name, age, num, tel) = mmInfo; cout << name << "\t" << age << "\t" << num << "\t" << tel << endl; } void Exoperator() { tuple<string, int, int, string> mmInfo = { "MM",18,1001,"123445" }; tuple<double, double, double> mmscore = make_tuple(98, 98, 88); auto result = tuple_cat(mmInfo, mmscore); } int main() { visitedData(); return 0; }
C++STL迭代器
迭代器
-
迭代器: 就是一个类中类,通过运算符重载通过类中类的对象去遍历容器
-
迭代器的分类
-
正向迭代器: iterator
-
begin();
-
end();
-
-
反向迭代器: reverse_iterator
-
rbegin();
-
rend();
-
-
常正向迭代器: const_iterator
-
cbegin();
-
cend();
-
-
常反向迭代器:const_reverse_iterator
-
crbegin();
-
crend();
-
-
-
Lambda: 就是一个返回函数指针的表达式,它定义和返回值函数指针在一起的
-
Lambda表达式的组成部分
-
按功能分类
-
正向迭代
-
双向迭代
-
随机访问迭代器
-
-
容器中迭代器分类
容器名 迭代器类型 array 随机访问 vector 随机访问 deque 随机访问 stack/queue/priority_queue(特定顺序存取) 不支持 list 双向 set/multiset 双向 map/multimap 双向 -
迭代器辅助函数
-
移动:advance(iterator iter,n);
-
间距:distance(iterator begin,iterator end);
-
交换:iter_swap(iterato first,iterator end);
-
-
拓展内容:特殊迭代器 流型迭代器-->一般用在辅助打印
-
输出流型
-
ostream_iterator<_Ty> iter(ostream& out);
-
ostream_iterator<_Ty> iter(ostream& out,char* str);
-
输出流型迭代做赋值运算,意味着就是打印数据到屏幕上
-
-
输入流型
-
istream_iterator<_Ty> iter; //构造无参对象,是一个错误流 end_of_ostream
-
istream_iterator<_Ty> iter(istream& in);
-
*iter 等效cin>>操作
-
Lambda表达式
-
Lambda: 就是一个返回函数指针的表达式,它定义和返回值函数指针在一起的
-
Lambda表达式的组成部分
// [捕获方式](函数参数)mutable exception->函数返回值类型{函数体;} int Max(int a,int b) { return a>b?a:b; } void print() { //Max的Lambda表达式写法 int(*pMax)(int,int)=[](int a,int b)mutable noexcept->int{ return a>b?a:b;}; //省略写法: 中间描述此都可以省略 auto ppMax=[](int a,int b){reutrn a>b?a:b;}; } //捕获方式-->函数使用外部的变量的方式 /* [=] //值的方式捕获 [&] //引用的方式捕获 [this]//this指针方式捕获 [] //不捕获任何变量 [=,&x];//x用引用方式捕获,其他变量用值的方式捕获 */
#include <iostream> using namespace std; int Max(int a, int b) { return a > b ? a : b; } void print(int(*pMax)(int, int), int a, int b) { cout << pMax(a, b) << endl; } class MM { public: void print() { [this] {cout << name << "\t" << age << endl; }(); //定义和调用一步到位 } protected: string name="默认"; int age=100; }; int main() { int(*pMax)(int, int) = nullptr; //完整版:Lambad 表达式 //final override pMax = [](int a, int b)mutable noexcept->int {return a > b ? a : b; }; cout << pMax(1, 3) << endl; //省略版本的,写代码越简单越好 auto pp = [](int a, int b) {return a > b ? a : b; }; cout << pp(1, 3) << endl; //实际使用可以一步到位--->短暂性局部使用的的函数 cout << [](int a, int b)mutable noexcept->int {return a > b ? a : b; }(1, 3) << endl; print([](int a, int b) {return a > b ? a : b; }, 1, 3); print([](int a, int b) {return a > b ? b : a; }, 1, 3); print([](int a, int b) {return a+b; }, 1, 3); //捕获方式的区别 //用值的捕获: 在Lambad中不能把值当做左值使用,函数调用不会因为值的改变而改变 int data = 101010; auto pFunc = [=] { cout << data << endl; }; //无参() 可以省略 auto pFunc2 = [&] { cout << data << endl; }; pFunc(); pFunc2(); data = 808080; pFunc(); pFunc2(); MM mm; mm.print(); //特殊的东西-->结合auto使用 auto pAuto = [](auto a, auto b) ->auto{return a > b ? a : b; }; cout << pAuto(1, 3) << endl; //[](auto a, auto b) ->auto{return a > b ? a : b; }(1,3) cout << pAuto("stringa", "stringb") << endl; //[] (auto a, auto b) ->auto{return a > b ? a : b; }("stringa", "stringb"); return 0; }
仿函数
-
什么仿函数? 类模仿函数调用行为,实质是无名对象调用重载的()函数
-
所以仿函数的关键点在于重载()
-
-
一般情况仿函数是做排序准则,或者一些算法的计算准则
-
标准库中的仿函数
-
算术类
-
关系类
-
逻辑类
-
选择,证同,投射
#include <iostream> #include <string> #include <functional> //仿函数所在头文件 #include <map> using namespace std; class Sum { public: int operator()(int a, int b) const { return a + b; } }; int main() { //重载的()的调用方式 Sum s; cout << "显式调用:" << s.operator()(1, 3) << endl; //显式调用重载函数 cout << "隐式调用:" << s(1, 3) << endl; //用{}和()帮助编译器去做解析 cout << "无名调用:" << Sum{}(1, 3) << endl; //类模仿函数调用行为--->仿函数 cout << "无名调用:" << Sum()(1, 3) << endl; //类模仿函数调用行为--->仿函数 //算术 cout << plus<int>{}(1, 3) << endl; //关系 cout << equal_to<int>{}(1, 3) << endl; map<int, less<int>> map1; map<int, greater<int>> map3; //逻辑类 cout << logical_and<int>{}(1,0) << endl; //求大于3 小于10的数字 //没必要的做的事情 int a = 34; if (logical_and<int>{}(a > 3, a < 10)) { cout << "大于3 小于10的数字" << endl; } return 0; }
函数适配器
-
什么是函数适配器: 用来绑定函数调用时候的参数,让函数适应其他调用的用法
#include <iostream> #include <string> #include <functional> #include <vector> #include <algorithm> using namespace std; //老版本bind1st bind2nd //新版本: bind函数 int Max(int a, int b) { return a > b ? a : b; } void print(int(*pMax)(int,int), int a,int b) { cout << pMax(a,b) << endl; } class Test { public: void print(int a, int b, int c) { cout << a << " " << b << " " << c << endl; } protected: }; void testClassFunc() { Test test; auto testFunc = bind(&Test::print, &test, std::placeholders::_1, std::placeholders::_2, 99); testFunc(1, 3); //调用,直接调用 } void printData(int one, Test two, string str) { cout << "调用成功" << endl; } //可以通过占位符,所以调整参数位置,形成不同的调用形态 void testExUser() { //占位符代表原函数的参数 在调用形态 的第二个位置 auto testFunc = bind(printData,std::placeholders::_3, std::placeholders::_1, std::placeholders::_2); printData(1, Test(), "ILoveyou"); testFunc(Test(), "ILoveyou", 1); } int main() { cout << Max(1, 3) << endl; //基本用法 //std::placeholders::_1占位符 auto pMax = bind(Max, std::placeholders::_1, 100); //把第二个参数置为100 //只是增加调用行为,并没有真正改变了这个函数指针类型 cout << pMax(34) << endl; cout << pMax(13, 44) << endl; //绑定后的函数指针,不再支持传参的,第二个参数无效 //语法上没问题,但是尽量别这样做 using namespace std::placeholders; auto pMax2 = bind(Max, _1, 100); //把第二个参数置为100 cout << pMax2(34) << endl; vector<int> vecData = { 19,43,89,89,34,54,67,54 }; cout << count_if(vecData.begin(), vecData.end(),bind(greater<int>(),std::placeholders::_1,60)) << endl; cout << count_if(vecData.begin(), vecData.end(), [](int a) {return a > 60; }) << endl; testClassFunc(); testExUser(); return 0; }
函数包装器
-
函数包装器是什么?就是把函数指针包装成一个对象。通过这个对象调用函数
-
一旦函数指针被函数包装器包装了,那这个包装器对象可以直接替换函数指针的用法去调用函数
-
-
函数包装器类的实力例化传参: function<函数返回值类型(参数类型)>
#include <iostream> #include <string> #include <functional> using namespace std; int Max(int a, int b) { cout << "包装普通函数:" << endl; return a > b ? a : b; } class MM { public: void print(int a) //void print(int a, MM* mm); { cout << "包装成员函数" << endl; } static void printStatic() { cout << "包装静态的函数" << endl; } protected: }; void testMMFunc() { MM mm; function<void(int)> func(bind(&MM::print,&mm,std::placeholders::_1)); func(12); } class Test { public: void operator()(string str) { cout << str << endl; } }; void printData(int a, MM mm, string str) { cout << "bind和function" << endl; } void TestFuncBind() { function<void(string, int, MM)> pf = bind(printData, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1 ); pf("string", 1, MM()); //3 1 2 } int main() { function<int(int, int)> funcMax(Max); cout << funcMax(1, 3) << endl; function<int(int, int)> funcMax2=Max; function<void()> funcS(MM::printStatic); funcS(); //仿函数包装 Test test; function<void(string)> func = test; func("包装仿函数"); TestFuncBind(); //包装成员函数 testMMFunc(); return 0; }
C++STL算法篇
STL查找算法
-
基本查找
-
find:区间查找
-
find_if:条件查找
-
find_firt_of: 查找区间第一次出现值
-
adjacent_find: 查找第一次重复的数
-
search:子序列查找
-
search_n: 子序列查找出现次数
-
-
统计查找
-
count: 区间统计
-
count_if: 条件统计个数
-
equal:比较
-
-
有序查找
-
binary_search:二分查找
-
upper_bound: 查找最后一个大于查找的值
-
lower_bound: 大于等于查找的值
-
equal_range:区间比较---有序序列
-
-
STL排序通用算法
-
merge: 归并排序,存于新容器
-
inplace_merge: 归并排序,覆盖原区间
-
sort: 排序,更改原容器顺序
-
stable_sort: 排序,保存原容器数据顺序
-
nth_element: 关键字排序
-
partition:范围排序
-
partial_sort:范围排序
-
partial_sort_copy:范围排序外加复制操作
-
stable_partition: 范围排序,保存原容器顺序
-
random_shuffle: 随机排序
-
reverse:逆序原容器
-
reverse_copy: 逆序容器保存到新容器
-
STL删除替换算法
-
copy: 拷贝函数
-
copy_backward: 逆序拷贝
-
iter_swap: 交换
-
remove: 删除
-
remove_copy: 删除元素复制到新容器
-
remove_if:条件删除
-
remove_copy_if:条件删除拷贝到新容器
-
replace:替换
-
replace_copy: 替换,结果放到新容器
-
replace_if: 条件替换
-
replace_copy_if:条件替换,结果另存
-
swap: 交换
-
swap_range:区间交换
-
unique:去重
-
unique_copy:去重,结果另存
-
STL排列组合算法
-
next_permutation:下一个排序序列的组合
-
prev_permutation:上一个排序序列的组合
-
STL 算术算法
-
accumulate:区间求和
-
partial_sum:相邻元素的和
-
inner_product:序列内积运算
-
adjacent_difference:相邻元素的差
-
STL 生成异变算法
-
for_each:迭代访问
-
fill:填充方式初始容器
-
fill_n:指定长度填充容器
-
generate_n:填充前n个位置
-
transform:一元转换和二元转换
-
STL 关系算法
-
equal:两容器元素是否都相同
-
includes:是否是包含关系
-
lexicographical_compare:比较两个序列
-
max:求最大值
-
max_element:返回最大值的iterator
-
min:求最小值
-
min_element:求最小值的iterator
-
mismatch:找到第一个不同的位置
-
STL 集合算法
-
set_union:差集
-
set_intersection:并集
-
set_difference:保存第一个中有第二个没有的元素
-
set_symmetric_difference:对称差集
-
STL堆算法
-
make_heap:生成一个堆
-
pop_heap:出堆
-
push_heap:入堆
-
sort_heap:堆排序
-
rotate:移动元素到容器末尾
-
rotate_copy:移动元素到新容器
-
-
-