C++ 知识总结
C++常用知识点
l count函数用以统计key值在unordered_map中出现的次数。实际上,c++ unordered_map不允许有重复的key。因此,如果key存在,则count返回1,如果不存在,则count返回0. Eg:unordered_map<int, int> water; if(water.count(r)){…}
unordered_map关联容器的常用方法
find() 如果key存在,则find返回key对应的迭代器,如果key不存在,则find返回unordered_map::end。因此可以通过map.find(key) == map.end()
emplace()向容器中添加新键值对,效率比 insert() 方法高。
Eg:vector<vector<int>>& connections
link_map[conn[0]].emplace(conn[1]);
unordered_set关联容器的常用方法
erase()删除指定元素
//删除 set 容器中值为 val 的元素, 返回成功删除元素的个数
size_type erase (const value_type& val);
//删除 position 迭代器指向的元素,返回值是迭代器,指向set容器中删除之后的第一个元素
iterator erase (const_iterator position);
//删除 [first,last) 区间内的所有元素,返回值是迭代器,指向set容器中删除之后的第一个元素
iterator erase (const_iterator first, const_iterator last);
eg: unordered_set<string> origin; origin.erase(word.substr(k));
创建unordered_set关联容器,创建空的容器/初始化容器/赋值拷贝 初始化容器;
1) 通过调用 unordered_set 模板类的默认构造函数,可以创建空的 unordered_set 容器。比如:
std::unordered_set<std::string> uset;
2) 当然,在创建 unordered_set 容器的同时,可以完成初始化操作。比如:
std::unordered_set<std::string> uset{ "http://c.biancheng.net/c/",
"http://c.biancheng.net/java/",
"http://c.biancheng.net/linux/" };
3) 还可以调用 unordered_set 模板中提供的复制(拷贝)构造函数,将现有 unordered_set 容器中存储的元素全部用于为新建 unordered_set 容器初始化。
std::unordered_set<std::string> uset2(uset);
4) 当然,如果不想全部拷贝,可以使用 unordered_set 类模板提供的迭代器
std::unordered_set<std::string> uset2(++uset.begin(),uset.end());
eg: vector<string>& words; unordered_set<string> good(words.begin(), words.end());
string类型的常用方法
substr() 对象的子串string substr(int m = 0,int n = npos) const; substr 成员函数可以用于求子串 (n, m),原型如下:调用时,如果省略 m 或 m 超过了字符串的长度,则求出来的子串就是从下标 n 开始一直到字符串结束的部分。例如:
string s1 = "this is ok";
string s2 = s1.substr(2, 4); // s2 = "is i"
s2 = s1.substr(2); // s2 = "is is ok"
assign() 和 对string对象赋值,
string s1(“Hello”) string s2; s2.assign(s1);
s2.assign(s1, 1, 2); // s2 = “el”, 即s1的子串(1,2)
s2.assign(4, ‘k’); //s2 = “kkkk”
s2.assin(“abcde”,2,3); //s2 = “cde”,即abcde的子串(2,3)
append() 字符串连接。----用来向字符串后面添加内容。append 成员函数返回对象自身的引用。
string s1("123"), s2("abc");
s1.append(s2); // s1 = "123abc"
s1.append(s2, 1, 2); // s1 = "123abcbc"
s1.append(3, 'K'); // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3); // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
compare() 字符串比较。返回值,小于0 表示当前字符串小,等于0表示字符相等,大于0表示另外一个字符小。
string s1("hello"), s2("hello, world");
int n = s1.compare(s2);
n = s1.compare(1, 2, s2, 0, 3); //比较s1的子串 (1,2) 和s2的子串 (0,3)
n = s1.compare(0, 2, s2); // 比较s1的子串 (0,2) 和 s2
n = s1.compare("Hello");
n = s1.compare(1, 2, "Hello"); //比较 s1 的子串(1,2)和"Hello”
n = s1.compare(1, 2, "Hello", 1, 2); //比较 s1 的子串(1,2)和 "Hello" 的子串(1,2)
find()从前往后查找子串或字符出现的位置。rfind:从后往前查找子串或字符出现的位置。
find_first_of:从前往后查找何处出现另一个字符串中包含的字符。s1.find_first_of("abc"); //查找s1中第一次出现"abc"中任一字符的位置
find_last_of:从后往前查找何处出现另一个字符串中包含的字符。
find_first_not_of:从前往后查找何处出现另一个字符串中没有包含的字符。
find_last_not_of:从后往前查找何处出现另一个字符串中没有包含的字符。
string s1("Source Code");
int n;
if ((n = s1.find('u')) != string::npos) //查找 u 出现的位置
cout << "1) " << n << "," << s1.substr(n) << endl;
//输出 l)2,urce Code
if ((n = s1.find("Source", 3)) == string::npos)
//从下标3开始查找"Source",找不到
cout << "2) " << "Not Found" << endl; //输出 2) Not Found
if ((n = s1.find("Co")) != string::npos)
//查找子串"Co"。能找到,返回"Co"的位置
cout << "3) " << n << ", " << s1.substr(n) << endl;
//输出 3) 7, Code
if ((n = s1.find_first_of("ceo")) != string::npos)
//查找第一次出现或 'c'、'e'或'o'的位置
cout << "4) " << n << ", " << s1.substr(n) << endl;
//输出 4) l, ource Code
if ((n = s1.find_last_of('e')) != string::npos)
//查找最后一个 'e' 的位置
cout << "5) " << n << ", " << s1.substr(n) << endl; //输出 5) 10, e
if ((n = s1.find_first_not_of("eou", 1)) != string::npos)
//从下标1开始查找第一次出现非 'e'、'o' 或 'u' 字符的位置
cout << "6) " << n << ", " << s1.substr(n) << endl;
//输出 6) 3, rce Code
replace()替换子串。对 string 对象中的子串进行替换,返回值为对象自身的引用。
string s1("Real Steel");
s1.replace(1, 3, "123456", 2, 4); //用 "123456" 的子串第2个字符开始4个字符 替换 s1 的子串从位置1的字符后的3个字符。
cout << s1 << endl; //输出 R3456 Steel
string s2("Harry Potter");
s2.replace(2, 3, 5, '0'); //用 5 个 '0' 替换子串(2,3)
cout << s2 << endl; //输出 HaOOOOO Potter
int n = s2.find("OOOOO"); //查找子串 "00000" 的位置,n=2
s2.replace(n, 5, "XXX"); //将子串(n,5)替换为"XXX"
cout << s2 < < endl; //输出 HaXXX Potter
insert()插入子字符串。insert 成员函数可以在 string 对象中插入另一个字符串,返回值为对象自身的引用。例如:
string s1("Limitless"), s2("00");
s1.insert(2, "123"); //在下标 2 处插入字符串"123",s1 = "Li123mitless"
s1.insert(3, s2); //在下标 2 处插入 s2 , s1 = "Li10023mitless"
s1.insert(3, 5, 'X'); //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"
erase()删除子串。删除 string 对象中的子串,返回值为对象自身的引用。
string s1("Real Steel");
s1.erase(1, 3); //删除子串(1, 3),此后 s1 = "R Steel"
s1.erase(5); //删除下标5及其后面的所有字符,此后 s1 = "R Ste"
lower_bound( )和upper_bound( )常见用法-----
在从小到大的排序数组中, lower_bound( begin,end,num):从容器的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。 upper_bound( begin,end,num):从容器的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
Eg int lc =lower_bound(C.begin(),C.end(), requirements[i][0])-C.begin();
set集合常用方法----
insert() 用于在集合中插入元素,且元素键在集合中是唯一的。
//普通引用方式传参
pair<iterator,bool> insert (const value_type& val);
eg: pars.insert(getRoot(i));
//以普通引用的方式传递 val 值
iterator insert (const_iterator position, const value_type& val);
eg: set<int> s; auto itr = s.insert(s.begin(), 1); itr = s.insert(itr, 4);
vector 向量容器的常用方法---
vector<double> values; //创建一个double类型元素的vector容器;
二维数组初始化
vector<vector<int>> sum(row+1, vector<int>(3,0)); 注: sum.size() 是行数。
values.reserve(20); //增加容器的容量;
values.resize(n);//改变实际元素的个数n
values.push_back(1.0);//在序列的尾部添加一个元素;
values.pop_back(2.0);//移除序列尾部的元素
常用算法
sort() 函数,针对区间[L, R)
void sort (RandomAccessIterator first, RandomAccessIterator last);
//按照指定的 comp 排序规则,对 [first, last) 区域内的元素进行排序
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
//以函数对象的方式实现自定义排序规则
class mycomp2 {
public:
bool operator() (int i, int j) {
return (i < j);
}
};
vector<int> myvector{ 32, 71, 12, 45, 26, 80, 53, 33 };
sort(myvector.begin(), myvector.begin() + 4); //(12 32 45 71) 26 80 53 33
sort(myvector.begin(), myvector.begin() + 4, greater<int>()); //(71 45 32 12) 26 80 53 33
sort(myvector.begin(), myvector.end(), mycomp2());//12 26 32 33 45 53 71 80
stable_sort() 函数,针对区间[L, R)
当指定范围内包含多个相等的元素时,完成排序且可以保证相等元素的相对位置。
partial_sort()排序函数
partial_sort() 函数会以交换元素存储位置的方式实现部分排序的。具体来说,partial_sort() 会将 [first, last) 范围内最小(或最大)的 middle-first 个元素移动到 [first, middle) 区域中,并对这部分元素做升序(或降序)排序。只适用于 array、vector、deque 这 3 个容器。容器中存储的元素类型必须支持 <小于运算符;
std::vector<int> myvector{ 3,2,5,4,1,6,9,7};
//以默认的升序排序作为排序规则,将 myvector 中最小的 4 个元素移动到开头位置并排好序
std::partial_sort(myvector.begin(), myvector.begin() + 4, myvector.end()); // 1 2 3 4 5 6 9 7
// 以指定的 mycomp2 作为排序规则,将 myvector 中最大的 4 个元素移动到开头位置并排好序
std::partial_sort(myvector.begin(), myvector.begin() + 4, myvector.end(), mycomp2()); //9 7 6 5 1 2 3 4
partial_sort_copy() 函数
partial_sort_copy() 函数会将 [first, last) 范围内最小(或最大)的 result_last-result_first 个元素复制到 [result_first, result_last) 区域中,并对该区域的元素做升序(或降序)排序。
int myints[5] = { 0 };
std::list<int> mylist{ 3,2,5,4,1,6,9,7 };
//按照默认的排序规则进行部分排序
std::partial_sort_copy(mylist.begin(), mylist.end(), myints, myints + 5); //1 2 3 4 5
//以自定义的 mycomp2 作为排序规则,进行部分排序
std::partial_sort_copy(mylist.begin(), mylist.end(), myints, myints + 5, mycomp2());//9 7 6 5 4
merge() 函数用于将 2 个有序序列合并为 1 个有序序列
merge() 函数用于将 2 个有序序列合并为 1 个有序序列
//first 和 second 数组中各存有 1 个有序序列
int first[] = { 5,10,15,20,25 };
int second[] = { 7,17,27,37,47,57 };
//用于存储新的有序序列
vector<int> myvector(11);
//将 [first,first+5) 和 [second,second+6) 合并为 1 个有序序列,并存储到 myvector 容器中。
merge(first, first + 5, second, second + 6, myvector.begin());
//myvector 5 7 10 15 17 20 25 27 37 47 57
inplace_merge()函数
当 2 个有序序列存储在同一个数组或容器中时,将它们合并为 1 个有序序列
int first[] = { 5,10,15,20,25,7,17,27,37,47,57 };
//将 [first,first+5) 和 [first+5,first+11) 合并为 1 个有序序列。
inplace_merge(first, first + 5,first +11)
find() 函数
用于在指定范围内查找和目标元素值相等的第一个元素。[first, last) 用于指定该函数的查找范围;val 为要查找的目标元素。该函数适用于所有的序列式容器。
char stl[] ="http://c.biancheng.net/stl/";
char * p = find(stl, stl + strlen(stl), 'c');
//判断是否查找成功
if (p != stl + strlen(stl)) {
cout << p << endl;
}
//find() 函数作用于容器
std::vector<int> myvector{ 10,20,30,40,50 };
std::vector<int>::iterator it;
it = find(myvector.begin(), myvector.end(), 30);
if (it != myvector.end())
find_if() 函数
会根据指定的查找规则,在指定区域内查找第一个符合该函数要求(使函数返回 true)的元素。
vector<int> myvector{ 4,2,3,1,5 };
//调用 find_if() 函数,并以 IsOdd() 一元谓词函数作为查找规则
vector<int>::iterator it = find_if(myvector.begin(), myvector.end(), mycomp2());//*it = 3
find_if_not()函数
find_if_not() 函数也适用于所有的容器,包括所有序列式容器和关联式容器。该函数也会返回一个输入迭代器,当 find_if_not() 函数查找成功时,该迭代器指向的是查找到的那个元素;反之,如果查找失败,该迭代器的指向和 last 迭代器相同。
//自定义一元谓词函数
bool mycomp(int i) {
return ((i % 2) == 1);
}
vector<int> myvector{4,2,3,1,5};
//调用 find_if() 函数,并以 mycomp() 一元谓词函数作为查找规则
vector<int>::iterator it = find_if_not(myvector.begin(), myvector.end(), mycomp);// 4
find_end() 函数
用于在序列 A 中查找序列 B 最后一次出现的位置。
//以函数对象的形式定义一个匹配规则
class mycomp2 {
public:
bool operator()(const int& i, const int& j) {
return (i%j == 0);
}
};
vector<int> myvector{ 1,2,3,4,8,12,18,1,2,3 };
int myarr[] = { 1,2,3 };
//调用第一种语法格式
vector<int>::iterator it = find_end(myvector.begin(), myvector.end(), myarr, myarr + 3);
cout << "最后一个{1,2,3}的起始位置为:" << it - myvector.begin() << ",*it = " << *it << endl;
int myarr2[] = { 2,4,6 };
//调用第二种语法格式
it = find_end(myvector.begin(), myvector.end(), myarr2, myarr2 + 3, mycomp2());
cout << "最后一个{2,3,4}的起始位置为:" << it - myvector.begin() << ",*it = " << *it;
find_first_of()函数
用于在 [first1, last1) 范围内查找和 [first2, last2) 中任何元素相匹配的第一个元素。如果匹配成功,该函数会返回一个指向该元素的输入迭代器;反之,则返回一个和 last1 迭代器指向相同的输入迭代器。
l for 遍历循环表达式
for(auto x : range)
//创建拷贝,无法修改range中的元素
for(auto& x : range)
//可以修改range中的元素,但一般用以下这种
for(auto&& x : range)
for(const auto & x : range)
//只读range中的元素
l iota 递增序列填充
vector<int> ivec(10);
iota(ivec.begin(), ivec.end(), 0);
//输出 0 1 2 3 4 5 6 7 8 9