sort默认从小到大
排序普通类型
bool complare(int a, int b) { return a < b; // 从小到大, 形参顺序不变, 看大小号判断排序顺序 return a > b; // 从大到小 } int a[10] = { 1, 7, 4, 0, 9, 4, 8, 8, 2, 4 }; sort(a, a + 10); // 数组长度 sort(a, a + 10, complare);
排序vector
bool complare(int a, int b) { return a > b; } vector<int> vt; for (int i = 0; i < 10; i++) { vt.push_back(static_cast<int>(rand() % 10)); } for (auto v : vt) cout << v << " "; cout << endl; sort(vt.begin(), vt.end(), complare); for (auto v : vt) cout << v << " "; cout << endl;
swap交换两个对象的值
myClass c1, c2; swap(c1, c2);
最值
int a = 1, b = 2; cout << max(a, b) << ' ' << endl; cout << min(a, b) << ' ' << endl;
字符转数字
方法:
fail: 转换失败时为true
clear: 只是清除错误状态, 并不清空字符串
str: 取流中的string类型, 清空字符串(释放内存)用str("")
类型转换
#include <sstream> #include <string> #include <iostream> using namespace std; template<class out_type, class in_value> out_type myConvert(const in_value & t) { stringstream stream; stream << t; //向流中传值 out_type result; //这里存储转换结果 stream >> result; //向result中写入值 return result; } int main() { string str1 = "3.1415926"; double num1 = 0; num1 = myConvert<double, string>(str1); cout << num1 << endl; string str2; double num2 = 3.1415926; str2 = myConvert<string, double>(num2); cout << str2.c_str() << endl; }
不定长度字符串转数字的读取求和
#include <sstream> #include <string> #include <iostream> using namespace std; int main() { string s; stringstream ss; int n, i, sum, a; cin >> n; getchar(); // 读取换行符 for (i = 0; i<n; i++) { getline(cin, s); ss.clear(); ss.str(s); cout << ss.str().size() << endl; sum = 0; while (1) { ss >> a; if (ss.fail()) { // fail方法 break; } sum += a; } ss.str(""); // 释放内存 cout << sum << endl; } }
混合转换
#include <sstream> #include <iostream> #include <string> using namespace std; int main() { stringstream stream; stream.str(cstr); string name; int score1, score2, average_score; stream >> name >> score1 >> score2; average_score = (score1 + score2) / 2; cout << name.c_str(); cout << " has average score " << average_score << endl; stream.clear(); // 若不注释会出问题 stream.str(""); stream.str(str); stream >> name >> score1 >> score2; average_score = (score1 + score2) / 2; cout << name.c_str(); cout << " has average score " << average_score << endl; return 0; }
istringstream与ostringstream配合使用, 把要输出的字符串保存到ostringstream中
#include <sstream> #include <iostream> #include <string> using namespace std; int main() { string str = "John 20 50"; // string to read from const char *cstr = "Amy 30 42"; // Cstring to read from istringstream istr1(str); // istr1 will read from str istringstream istr2; // istr2 will read from cstr ostringstream ostr; // The ostringstream object to write to string name; int score1, score2, average_score; istr1 >> name >> score1 >> score2; average_score = (score1 + score2) / 2; ostr << name << " has average score " << average_score << "\n"; istr2.str(cstr); istr2 >> name >> score1 >> score2; average_score = (score1 + score2) / 2; ostr << name << " has average score " << average_score << "\n"; ostr << hex; ostr << name << "'s scores in hexadecimal are: " << score1 << " and " << score2 << "\n"; cout << ostr.str(); return 0; }
数字转字符
// to_string() 函数无法处理非十进制整数的转换。如果需要该功能,则应该使用 ostringsteam 对象来完成该转换。 string to_string(int value) string to_string(long value) string to_string(double value) int stoi(const strings str, size_t* pos = 0, int base = 10) long stol(const strings str, size_t* pos = 0, int base = 10) float stof(const strings str, size_t* pos = 0) double stod(const strings str, size_t* pos = 0)
示例程序
#include <string> #include <iostream> using namespace std; int main() { string str; // string to convert size_t pos; // Hold position of stopping character //Convert string to double str = "-342.57is a number"; cout << str << endl; double d = stod(str, &pos); cout << "The converted double is " << d << endl; cout << "The stopping character is " << str[pos] << " at position " << pos << endl; // Convert string to int (default to decimal) str = "-342.57is a number"; cout << str << endl; int i = stoi(str, &pos); cout << "The converted integer is " << i << endl; cout << "The stopping character is " << str[pos] << " at position " << pos << endl; // Convert string to int (base is binary) str = "01110binary number"; cout << str << endl; i = stoi(str, &pos, 2); cout << "The converted binary integer is " << i << endl; cout << "The stopping character is " << str[pos] << " at position " << pos << endl; return 0; }
string
find: 匹配整个字符串
rfind: 从后向前匹配整个字符串
不严格匹配, 查找a中使用包含/不包含b的元素
a.find_first_of(b):
a.find_first_not_of(b)
a.find_last_of(b)
a.find_last_not_of(b)
严格匹配
#include <iostream> #include <string> using namespace std; int main() { string a = "123abcdef"; string b = "bced"; size_t pos = a.find(b); if (pos != string::npos) std::cout << "Yes" << "pos: " << pos << endl; else std::cout << "No" << endl; return 0; }
包含替换
#include <iostream> #include <string> using namespace std; int main() { string str("Please, replace the vowels in this sentence by asterisks."); size_t found = str.find_first_of("aeiou"); while (found != string::npos) { str[found] = '*'; found = str.find_first_of("aeiou", found + 1); } cout << str << '\n'; return 0; }
文件中查找字符串
#include <iostream> #include <string> #include <fstream> #include <vector> using namespace std; // test.txt文件中找Code:之后字符串, 以逗号分隔 void f_get_data(vector<string>& arr, string s_flag_name) { ifstream fin("test.txt"); if (!fin) { exit(0); } string str_file_content, str_content, str_type; while (getline(fin, str_file_content)) { int index = str_file_content.find_first_of(':'); str_type = str_file_content.substr(0, index); str_content = str_file_content.substr(index + 1, str_file_content.length()); if (s_flag_name == str_type) { index = str_content.find_first_of(','); while (string::npos != index) { arr.push_back(str_content.substr(0, index)); str_content = str_content.substr(index + 1, str_content.length()); index = str_content.find_first_of(','); } arr.push_back(str_content); } } } int main(void) { vector<string> str; f_get_data(str, "Code"); for (auto i : str) { cout << i << " "; } cout << endl; return 0; }
按指定字符分隔string
#include <iostream> #include <string> #include <vector> using namespace std; vector<string> Split(const string& str, const char delim) { vector<string> result; size_t start = 0; size_t pos = str.find(delim); // 从头开始查找分隔符 while (pos != string::npos) { if (pos > start) { result.push_back(str.substr(start, pos - start)); // 从start开始, 向后取pos-start个 } start = pos + 1; pos = str.find(delim, start); // 从指定位置之后查找分隔符 } if (start < str.length()) { // 末尾元素处理 result.push_back(str.substr(start)); } return result; } int main() { string str; getline(cin, str); vector<string> res = Split(str, ' '); for (auto i : res) { cout << i << " "; } cout << endl; return 0; }
算法不同
其中erase与find与序列式容器不同
关联式容器erase可以直接以key的方式删除
序列式容器erase只能通过迭代器方式形势删除
关联式容器find可以直接查找key
序列式容器只能通过algorithm中find查找
vector
- 构造函数
vector<type> arr; // 创建一个空vector vector<type> arr(int nSize); // 声明一个类型为type、含有nSize个默认值初始化元素的的双端队列que vector<type> arr(int nSize, const type& t); // 声明一个元素类型为type、含有nSize个t元素的双端队列que vector<type> arr(const vector&); // deq是mydeque的一个副本 vector<type> arr(begin,end); // 使用迭代器first、last范围内的元素初始化arr
常用函数
reference front(); reference back(); void push_back(const bool& _Val) // 向量尾部增加一个元素X void pop_back() // 尾端删除元素 // 没有push_front与pop_front操作 size_type size(); size_type capacity() void clear(); bool empty() const; iterator insert(iterator it, const T& x):向量中迭代器指向元素前增加一个元素x iterator insert(iterator it, int n, const T& x):向量中迭代器指向元素前增加n个相同的元素x iterator insert(iterator it, const_iterator first, const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据 iterator erase(iterator it):删除向量中迭代器指向元素 iterator erase(iterator first, iterator last): 删除向量中[first,last)中元素
二维数组的定义
int M = 2, N = 4; // 2行4列二维数组 vector<vector<int>> arr(M, vector<int>(N));
deque
- 常用函数
reference front(); reference back() void push_front(const value_type& _Val) void pop_front() void push_back(const value_type& _Val) void pop_back()
- 特点
- 支持随机访问,即支持[ ]以及at(),但是性能没有vector好。
- 可以在内部进行插入和删除操作,但性能不及list。
- deque两端都能够快速插入和删除元素,而vector只能在尾端进行。
- deque的元素存取和迭代器操作会稍微慢一些,因为deque的内部结构会多一个间接过程。
- deque迭代器是特殊的智能指针,而不是一般指针,它需要在不同的区块之间跳转。
- deque可以包含更多的元素,其max_size可能更大,因为不止使用一块内存。
- deque不支持对容量和内存分配时机的控制。
- 在除了首尾两端的其他地方插入和删除元素,都将会导致指向deque元素的任何pointers、references、iterators失效。不过,deque的内存重分配优于vector,因为其内部结构显示不需要复制所有元素。
- deque的内存区块不再被使用时,会被释放,deque的内存大小是可缩减的。不过,是不是这么做以及怎么做由实际操作版本定义。
- deque不提供容量操作:capacity()和reverse(),但是vector可以。
list
- 常用成员函数
reference front() reference back() void push_front(const _Ty& _Val); void pop_front(); void push_back(const _Ty& _Val); void pop_back() void remove(const _Ty& _Val); // 与algorithm中remove有区别, 前者是覆盖, 这里是删除 void remove_if(_Pr1 _Pred); // 传入比较器删除元素, 通过重载小括号 void unique(); // 删除 相邻 的重复元素 void reverse(); // 翻转list void merge(_Myt& _Right); // 合并两个list void swap(_Myt& _Right); // 交换两个list bool empty(); // 判断是否为空
示例程序
#include <iostream> #include <vector> #include <algorithm> #include <list> using namespace std; void printList(list<int>& lt); bool comparator_1(int& a) { return a == 10; } struct comparator_2 { // 这么重载小括号第一次见 int m_key; //comparator_2(int& key) { // 基础数据类型不能加引用 comparator_2(int key) { // 复合类型可以 this->m_key = key; } bool operator()(int& num) { return num == m_key; } }; int main() { list<int> lt = {10, 10, 1, 2, 20, 3, 10, 4, 20, 5, 10}; lt.reverse(); printList(lt); cout << "==============================" << endl; lt.unique(); // 删除相邻的重复元素 printList(lt); cout << "==============================" << endl; lt.remove_if(comparator_1); printList(lt); cout << "==============================" << endl; lt.remove_if(comparator_2(20)); // 通过重载小括号参数的形式可以删除不定元素 printList(lt); return 0; } void printList(list<int>& lt) { for (auto i : lt) { cout << i << " "; } cout << endl; } /* Before calling remove Numbers { 10 1 2 3 10 4 5 10 } After calling remove 10 Numbers { 10 1 2 3 10 4 5 10 } Total number of elements removed from Numbers = 0 Valid elements Numbers { 10 1 2 3 10 4 5 10 } After calling erease Numbers { 10 1 2 3 10 4 5 10 } 请按任意键继续. . . */
map/multimap
- 初始化
map<type, type> mp;
- 基本操作
size_type count(const key_type& _Keyval) 返回map中元素的个数 size_type size() bool empty() // 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器 // 根据map的类型,返回的迭代器为 iterator 或者 const_iterator iterator find (const key_type& k); void erase ( iterator position ); size_type erase ( const key_type& x ); void erase ( iterator first, iterator last ); // 插入操作 // 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败 pair<iterator,bool> insert (const value_type& val); // 在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排 iterator insert (const_iterator position, const value_type& val);
插入判断示例
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; pair<map<int, string>::iterator, bool> Insert_Pair; Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one")); if (Insert_Pair.second == true) cout << "Insert Successfully" << endl; else cout << "Insert Failure" << endl; Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two")); if (Insert_Pair.second == true) cout << "Insert Successfully" << endl; else cout << "Insert Failure" << endl; map<int, string>::iterator iter; for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++) cout << iter->first << ' ' << iter->second << endl; }
排序有两种方法: (1)重载小于号; (2)使用仿函数
类中重载小于号
#include <iostream> #include <string> #include <map> using namespace std; typedef struct tagStudentinfo { int niD; string strName; // 指定排序策略,按niD排序,如果niD相等的话,按strName排序 bool operator<(tagStudentinfo const& _A) const { if (niD < _A.niD) return true; if (niD == _A.niD) return strName.compare(_A.strName) < 0; return false; } } Studentinfo, *PStudentinfo; //学生信息 int main() { int nSize; //用学生信息映射分数 map<Studentinfo, int>mapStudent; map<Studentinfo, int>::iterator iter; Studentinfo studentinfo; studentinfo.niD = 1; studentinfo.strName = "student_one"; mapStudent.insert(pair<Studentinfo, int>(studentinfo, 90)); studentinfo.niD = 2; studentinfo.strName = "student_two"; mapStudent.insert(pair<Studentinfo, int>(studentinfo, 80)); for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++) cout << iter->first.niD << ' ' << iter->first.strName << ' ' << iter->second << endl; return 0; }
使用仿函数
#include <iostream> #include <string> #include <map> using namespace std; typedef struct tagStudentinfo { int niD; string strName; } Studentinfo, *PStudentinfo; //学生信息 class MySort { public: bool operator()(Studentinfo const& A, Studentinfo const& B) { if (A.niD < B.niD) return true; if (A.niD == B.niD) return A.strName.compare(B.strName) < 0; return false; } }; int main() { map<Studentinfo, int, MySort>mapStudent; map<Studentinfo, int>::iterator iter; Studentinfo studentinfo; studentinfo.niD = 1; studentinfo.strName = "student_one"; mapStudent.insert(pair<Studentinfo, int>(studentinfo, 90)); studentinfo.niD = 2; studentinfo.strName = "student_two"; mapStudent.insert(pair<Studentinfo, int>(studentinfo, 80)); for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++) cout << iter->first.niD << ' ' << iter->first.strName << ' ' << iter->second << endl; return 0; }
set/multiset
- 常用成员函数
iterator find(const key_type& _Keyval) size_type erase(const key_type& _Keyval) iterator erase(const_iterator _Plist) iterator erase(const_iterator _First, const_iterator _Last)
实例程序
#include <iostream> #include <string> #include <set> using namespace std; /* 仿函数CompareSet,在test02使用 */ class CompareSet { public: //从大到小排序 bool operator()(int v1, int v2) { return v1 > v2; } }; /* Person类,用于test03 */ class Person { friend ostream &operator<<(ostream &out, const Person &person); public: Person(string name, int age) { mName = name; mAge = age; } public: string mName; int mAge; }; ostream &operator<<(ostream &out, const Person &person) { out << "name:" << person.mName << " age:" << person.mAge << endl; return out; } /* 仿函数ComparePerson,用于test03 */ class ComparePerson { public: //名字大的在前面,如果名字相同,年龄大的排前面 bool operator()(const Person &p1, const Person &p2) { if (p1.mName == p2.mName) { return p1.mAge > p2.mAge; } return p1.mName > p2.mName; } }; /* 打印set类型的函数模板 */ template<typename T> void PrintSet(T &s) { for (T::iterator iter = s.begin(); iter != s.end(); ++iter) cout << *iter << " "; cout << endl; } void test01() { //set容器默认从小到大排序 set<int> s; s.insert(10); s.insert(20); s.insert(30); //输出set PrintSet(s); //结果为:10 20 30 /* set的insert函数返回值为一个对组(pair)。 对组的第一个值first为set类型的迭代器: 1、若插入成功,迭代器指向该元素。 2、若插入失败,迭代器指向之前已经存在的元素 对组的第二个值seconde为bool类型: 1、若插入成功,bool值为true 2、若插入失败,bool值为false */ pair<set<int>::iterator, bool> ret = s.insert(40); if (true == ret.second) cout << *ret.first << " 插入成功" << endl; else cout << *ret.first << " 插入失败" << endl; } void test02() { /* 如果想让set容器从大到小排序,需要给set容 器提供一个仿函数,本例的仿函数为CompareSet */ set<int, CompareSet> s; s.insert(10); s.insert(20); s.insert(30); //打印set PrintSet(s); //结果为:30,20,10 } void test03() { /* set元素类型为Person,当set元素类型为自定义类型的时候 必须给set提供一个仿函数,用于比较自定义类型的大小, 否则无法通过编译 */ set<Person, ComparePerson> s; s.insert(Person("John", 22)); s.insert(Person("Peter", 25)); s.insert(Person("Marry", 18)); s.insert(Person("Peter", 36)); //打印set PrintSet(s); } int main(void) { //test01(); //test02(); test03(); return 0; }
容器适配器
stack
void pop() void push(const value_type& _Val) reference top() size_type size() bool empty() void swap(_Myt& _Right)
queue
void pop() void push(const value_type& _Val) reference back() reference front() bool empty() size_type size() void swap(_Myt& _Right)
priority_queue
priority_queue用于先进先出的操作,元素的插入在容器的尾部进行,删除操做在容器的头部进行.它会对插入的数据进行排序, 默认大根堆
- 常用方法:
void pop() void push(const value_type& _Val) reference top() bool empty() size_type size() void swap(_Myt& _Right)
对于一些常见的优先队列,stl提供了简单的定义方法:
#include <functional> // greater与less需要此头文件 priority_queue<int,vector<int>, greater<int> >q; // 小根堆, 大的先压栈 priority_queue<int,vector<int>, less<int> >q; // 大根堆, 小的先压栈
类中重载与使用比较器
#include <iostream> #include <string> #include <queue> using namespace std; // 类中重载< typedef struct tagStudentinfo { int niD; string strName; bool operator<(tagStudentinfo const& _A) const { // 从大到小 --> 小根堆 if (niD > _A.niD) return true; if (niD == _A.niD) return strName.compare(_A.strName) < 0; return false; } } Studentinfo, *PStudentinfo; //学生信息 // 类外重载() struct compare { bool operator()(Studentinfo n1, Studentinfo n2) { if (n1.niD > n2.niD) return true; if (n1.niD == n2.niD) return n1.strName.compare(n2.strName) < 0; return false; } }; int main() { priority_queue<Studentinfo> q; // 直接使用类型 priority_queue<Studentinfo, vector<Studentinfo>, compare> p; // 第一个类型, 第二个vector, 第三个比较器 Studentinfo studentinfo; studentinfo.niD = 3; studentinfo.strName = "student_one"; q.push(studentinfo); p.push(studentinfo); studentinfo.niD = 1; studentinfo.strName = "student_two"; q.push(studentinfo); p.push(studentinfo); studentinfo.niD = 2; studentinfo.strName = "student_two"; q.push(studentinfo); p.push(studentinfo); while (!q.empty()) { cout << q.top().niD << ' ' << q.top().strName << endl; q.pop(); cout << p.top().niD << ' ' << p.top().strName << endl; p.pop(); } return 0; }
与pair, make_pair配合使用
#include <iostream> #include <vector> #include <queue> using namespace std; struct comparator { bool operator()(const pair<int, int>& a, const pair<int, int>& b) { return a.first != b.first ? a.first > b.first : a.second > b.second; } }; int main() { priority_queue<pair<int, int>, vector<pair<int, int>>, comparator> pq; pq.push(make_pair(2, 3)); pq.push(pair<int, int>(1, 2)); pq.push(make_pair(1, 1)); pq.push(pair<int, int>(3, 2)); while (!pq.empty()) { cout << pq.top().first << " " << pq.top().second << endl; pq.pop(); } return 0; } /* 1 1 1 2 2 3 3 2 请按任意键继续. . . */
algorithm
sort
bool compare(int a, int b) { return a < b; //升序排列,如果改为return a>b,则为降序 } int a[20] = { 2, 4, 1, 23, 5, 76, 0, 43, 24, 65 }; for (int i = 0; i<20; i++) cout << a[i] << " "; cout << endl; sort(a, a + 20, compare); for (int i = 0; i<20; i++) cout << a[i] << " "; cout << endl;
find
find() 为在输入迭代器所定义的范围内查找单个对象的算法,它可以在前两个参数指定的范围内查找和第三个参数相等的第一个对象。
find 算法会返回一个指向被找到对象的迭代器,如果没有找到对象,会返回这个序列的结束迭代器。下面展示了如何使用 find():
// 单次查找 std::vector<int> numbers {5, 46, -5, -6, 23, 17, 5, 9, 6, 5}; int value {23}; auto iter = std::find(std::begin(numbers), std::end(numbers), value); if (iter != std:: end (numbers)) std::cout << value << " was found. \n"; // 多次查找 size_t count = 0; int five {5}; auto start_iter = std::begin(numbers); auto end_iter = std::end(numbers); while((start_iter = std::find(start_iter, end_iter, five)) != end_iter) { ++count; ++start_iter; } std::cout << five << " was found " << count << " times." << std::endl; // 3 times
remove
不是删除元素, 而是复制移动, 与erase配合使用删除元素
remove与erease配合使用arr.erase(remove(arr.begin(), arr.end(), val), arr.end());
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> Numbers = {10, 1, 2, 3, 10, 4, 5, 10}; //vector containing numbers vector<int>::iterator it; cout << "Before calling remove" << endl << "Numbers { "; for (it = Numbers.begin(); it != Numbers.end(); it++) { cout << *it << " "; } cout << "}\n" << endl; // remove all elements from Numbers that match 10 vector<int>::iterator ret = remove(Numbers.begin(), Numbers.end(), 11); cout << "After calling remove 10" << endl << "Numbers { "; for (it = Numbers.begin(); it != Numbers.end(); it++) { cout << *it << " "; } cout << "}\n" << endl; cout << "Total number of elements removed from Numbers = " << Numbers.end() - ret << endl; cout << "Valid elements" << endl << "Numbers { "; for (it = Numbers.begin(); it != ret; it++) { cout << *it << " "; } cout << "}\n" << endl; cout << "After calling erease" << endl << "Numbers { "; Numbers.erase(ret, Numbers.end()); for (it = Numbers.begin(); it != Numbers.end(); it++) { cout << *it << " "; } cout << "}\n" << endl; return 0; } /* Before calling remove Numbers { 10 1 2 3 10 4 5 10 } After calling remove 10 Numbers { 10 1 2 3 10 4 5 10 } Total number of elements removed from Numbers = 0 Valid elements Numbers { 10 1 2 3 10 4 5 10 } After calling erease Numbers { 10 1 2 3 10 4 5 10 } 请按任意键继续. . . */