c++学习记录,课程是:b站黑马程序员
1:vector容器嵌套
#include<iostream> using namespace std; #include <vector> //容器嵌套容器 void test01() { vector< vector<int>>v; //创建小容器 vector<int>v1; vector<int>v2; vector<int>v3; vector<int>v4; //向小容器中添加数据 for(int i = 0 ; i < 4;i++) { v1.push_back(i + 1); v2.push_back(i + 2); v3.push_back(i + 3); v4.push_back(i + 4); } //将小容器插入到大容器中 v.push_back(v1); v.push_back(v2); v.push_back(v3); v.push_back(v4); //通过大容器,把所有数据遍历一遍 for (vector< vector<int>>::iterator it = v.begin(); it != v.end(); it++) { // (*it) ---- 容器 vector<int> for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) { cout << *vit << " "; } cout << endl; } } int main() { test01(); system("pause"); return 0; }vector<vector<int>> v:
- 容器v里面存放的是“只能存int数据类型的vector容器”
v:
- 集装箱v里面有小盒子装着(int)苹果
v.push_back(v1);
- v 是大容器,它要求 push_back 进去的元素必须是 vector<int> 类型
vector< vector<int> >::iterator it:
- it:指针,是地址
- *it打开集装箱,里面存放的是小盒子,是vector<int>
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++):
- vit 是内层迭代器是地址
- *vit是某个int类型的元素
- (*it) 就是当前拿到的那个小盒子
- begin() 就是这个小盒子的第一个苹果盒子
2:vector构造函数
完整代码:
#include<iostream> using namespace std; #include<vector> void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //vector容器构造 void test01() { vector<int>v1; //默认构造 无参构造 for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); //通过区间方式进行构造 vector<int>v2(v1.begin(), v1.end()); printVector(v2); //n个elem方式构造 vector<int>v3(10, 100); printVector(v3); //拷贝构造 vector<int>v4(v3); printVector(v4); } int main() { test01(); system("pause"); return 0; }运行结果:
1:默认构造vector<int> v1
告诉编译器:装整数的容器,名字叫v1,现在什么都不放。
2:区间构造vector<int> v2(v1.begin(), v1.end())
把另一个容器(v1)中从头到尾的所有元素拿过来,初始化v2
3:n个elem构造vector<int> v3(10, 100)
(数量, 值),10个100的数字,初始化v3
4:拷贝构造vector<int> v4(v3)
用v3的内容初始化v4
3:vector赋值操作
#include<iostream> using namespace std; #include <vector> void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //vector赋值 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); //赋值 operator= vector <int>v2; v2 = v1; printVector(v2); // assign vector<int>v3; v3.assign(v1.begin(), v1.end()); printVector(v3); //n个elem 方式赋值 vector<int>v4; v4.assign(10, 100); printVector(v4); } int main() { test01(); system("pause"); return 0; }1:重载等号赋值
vector <int>v2; // 1. 先创建一个空的容器 v2 v2 = v1; // 2. 把 v1 的所有内容“抄”给 v2清空:如果v2里面原本有数据,编译器会先把它清空。
深拷贝:编译器会把v1里的数据完全复制一份,放入v2的内存中
2:assign成员函数赋值
vector<int>v3; v3.assign(v1.begin(), v1.end());语法:v3.assign(a1,a2)
参数:传入两个迭代器,左闭右开区间
含义:复制容器v1的全部内容给v3
3:assign n个elem赋值
vector<int>v4; // 语法:assign(数量, 值) v4.assign(10, 100);先创建容器v4,复制10个100给v4
4:vector容量大小
#include<iostream> using namespace std; #include<vector> void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //vector容器的容量和大小操作 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); if (v1.empty()) //为真 代表容器为空 { cout << "v1为空" << endl; } else { cout << "v1不为空" << endl; cout << "v1的容量为: " << v1.capacity() << endl; cout << "v1的大小为: " << v1.size() << endl; } //重新指定大小 v1.resize(15 , 100); //利用重载版本,可以指定默认填充值,参数2 printVector(v1);//如果重新指定的比原来长了,默认用0填充新的位置 v1.resize(5); printVector(v1); //如果重新指定的比原来短了,超出部分会删除掉 } int main() { test01(); system("pause"); return 0; }5:vector插入删除
#include<iostream> using namespace std; #include <vector> //vector插入和删除 /* - push_back(ele); //尾部插入元素ele - pop_back(); //删除最后一个元素 - insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele - insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele - erase(const_iterator pos); //删除迭代器指向的元素 - erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素 - clear(); //删除容器中所有元素 */ void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int>v1; //尾插 v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); //遍历 printVector(v1); //尾删 v1.pop_back(); printVector(v1); //插入 第一个参数是迭代器 v1.insert(v1.begin(), 100); printVector(v1); v1.insert(v1.begin(), 2, 1000); printVector(v1); //删除 参数也是迭代器 v1.erase(v1.begin()); printVector(v1); //清空 //v1.erase(v1.begin(), v1.end()); v1.clear(); printVector(v1); } int main() { test01(); system("pause"); return 0; }6:vector数据存取
#include<iostream> using namespace std; #include <vector> //vector容器 数据存取 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } //利用[]方式访问数组中元素 for (int i = 0; i < v1.size(); i++) { cout << v1[i] << " "; } cout << endl; //利用at方式访问元素 for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << " "; } cout << endl; //获取第一个元素 cout << "第一个元素为: " << v1.front() << endl; //获取最后一个元素 cout << "最后一个元素为: " << v1.back() << endl; } int main() { test01(); system("pause"); return 0; }7:vector互换容器
#include<iostream> using namespace std; #include <vector> //vector容器互换 void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } //1、基本使用 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } cout << "交换前: " << endl; printVector(v1); vector<int>v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } printVector(v2); cout << "交换后: " << endl; v1.swap(v2); printVector(v1); printVector(v2); } //2、实际用途 //巧用swap可以收缩内存空间 void test02() { vector<int>v; for (int i = 0; i < 100000; i++) { v.push_back(i); } cout << "v的容量为: " << v.capacity() << endl; cout << "v的大小为: " << v.size() << endl; v.resize(3); //重新指定大小 cout << "v的容量为: " << v.capacity() << endl; cout << "v的大小为: " << v.size() << endl; //巧用swap收缩内存 vector<int>(v).swap(v); cout << "v的容量为: " << v.capacity() << endl; cout << "v的大小为: " << v.size() << endl; } int main() { //test01(); test02(); system("pause"); return 0; }vector<int>(v).swap(v); 有收缩内存的作用
相当于
{ vector<int> temp(v); // ① 拷贝构造一个新容器 temp.swap(v); // ② 交换两个容器的存储空间 } // ③ temp 析构,释放原来的大块内存创建了临时容器,复制了3个有效的元素
然后进行容量跟大小的交换,temp是临时的,交换之后获得了较大的容量,最后被释放了
8:vector预留空间
reserve(int len); 容器预留len个元素长度,预留位置不初始化,元素不可访问。
#include<iostream> using namespace std; #include <vector> //vector容器 预留空间 void test01() { vector<int>v; //利用reserve预留空间 // v.reserve(100000); int num = 0; //统计开辟次数 int * p = NULL; for (int i = 0; i < 100000; i++) { v.push_back(i); if (p != &v[0]) { p = &v[0]; num++; } } cout << "num = " << num << endl; } int main() { test01(); system("pause"); return 0; }在没有使用reserve的情况下,编译器会开辟30次内存,才能存下100000个数据。
内存开辟一次,num增加1
if (p != &v[0]):只要重新开辟内存空间,首地址就会改变,所以p就不等于现在的首地址,num次数增加一次。
9:MAP构造与赋值
1:所有的元素都是pair,成对出现
2:第一个元素是key,起到索引作用。第二个元素是value
3:所有元素按key自动排序,key值不能重复
优点:可以根据key值,找到value值
函数:
1:map<T1,T2> mp;
默认构造函数,T1:key的类型是int,T2:value的类型是int
2:map(const map &map);
拷贝构造函数
3:map & operator=(const map &mp);
重载等于号运算符
#include<iostream> using namespace std; #include <map> //map容器 构造和赋值 void printMap(map<int, int>&m) { for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) { cout << "key = " << (*it).first << " value = " << it->second << endl; } cout << endl; } void test01() { //创建map容器 map<int, int> m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(3, 30)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(4, 40)); printMap(m); //拷贝构造 map<int, int>m2(m); printMap(m2); //赋值 map<int, int>m3; m3 = m2; printMap(m3); } int main() { test01(); system("pause"); return 0; }代码中:
1:m.insert(pair<int, int>(1, 10));
map的元素成对出现,第一个变量为:first,第二个是seconde。
pair:创建一个临时的成对 对象,first是1,seconde是10,整体存入map容器里
2:插入顺序:1 -> 3 -> 2 -> 4
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 20)); // 注意这里,虽然是第3个插入的
m.insert(pair<int, int>(4, 40));
当你插入(3, 30)时,它排在(1, 10)后面。
当你插入(2, 20)时,map发现 2 比 1 大,但比 3 小。会自动把(2, 20)插在 1 和 3 中间。
容器内部现在的顺序是Key: 1, 2, 3, 4
3:(*it).first
it指向pair的地址,*it拿到对象pair本体,然后用.访问成员。
10:MAP大小与交换
1:size()
返回容器中元素的数目
2:empt()
判断容器是否为空
3:swap(st)
交换两个容器
#include<iostream> using namespace std; #include <map> //map容器 大小和交换 //大小 void test01() { map<int, int>m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(3, 30)); if (m.empty()) { cout << "m为空" << endl; } else { cout << "m不为空" << endl; cout << "m的大小为: " << m.size() << endl; } } void printMap(map<int, int>&m) { for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) { cout << "key = " << it->first << " value = " << it->second << endl; } cout << endl; } //交换 void test02() { map<int, int>m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(3, 30)); map<int, int>m2; m2.insert(pair<int, int>(4, 100)); m2.insert(pair<int, int>(5, 200)); m2.insert(pair<int, int>(6, 300)); cout << "交换前: " << endl; printMap(m); printMap(m2); m.swap(m2); cout << "交换后: " << endl; printMap(m); printMap(m2); } int main() { //test01(); test02(); system("pause"); return 0; }11:MAP插入与删除
1:insert(elem)
在容器中插入元素
2:clear()
清除所有元素
3:erase(pos)
清除pos迭代器所指的元素,返回下一个元素的迭代器
4:erase(beg,end)
删除[beg,end)的所有元素,返回下一个元素的迭代器
5:erase(key)
清除容器中key值的元素
#include<iostream> using namespace std; #include <map> //map容器 插入和删除 void printMap(map<int, int>&m) { for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) { cout << "key = " << it->first << " value = " << it->second << endl; } cout << endl; } void test01() { map<int, int>m; //插入 //第一种 m.insert(pair<int, int>(1, 10)); //第二种 m.insert(make_pair(2, 20)); //第三种 m.insert(map<int, int>::value_type(3, 30)); //第四种 m[4] = 40; //[]不建议插入,用途 可以利用key访问到value //cout << m[4] << endl; printMap(m); //删除 m.erase(m.begin()); printMap(m); m.erase(3); //按照key删除 printMap(m); //清空 //m.erase(m.begin(), m.end()); m.clear(); printMap(m); } int main() { test01(); system("pause"); return 0; }12:MAP查找与统计
1:find(key)
查找key是否存在,若存在,返回该key元素的迭代器,若不存在,返回set.send()
2:count(key)
统计key的元素个数,返回0或者1
#include<iostream> using namespace std; #include <map> //map容器 查找和统计 void test01() { //查找 map<int, int>m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(3, 30)); m.insert(pair<int, int>(3, 40)); map<int,int>::iterator pos = m.find(3); if (pos != m.end()) { cout << "查到了元素 key = " << (*pos).first << " value = " << pos->second << endl; } else { cout << "未找到元素" << endl; } //统计 //map不允许插入重复key 元素 ,count统计而言 结果要么是0 要么是1 //multimap的count统计可能大于1 int num = m.count(3); cout << "num = " << num << endl; } int main() { test01(); system("pause"); return 0; }13:MAP排序
map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则
写仿函数,改变排序规则
仿函数知识点
1:在类里面重载了()从操作符,这个类的对象,就可以像函数一样被调用,因为他模仿了函数的行为,所以被称为仿函数
平时我们写map<int, int> m;时,编译器其实偷懒了,它默默帮你补全了第三个参数。
默认写法:
map<int, int, less<int>> m;less<int>是 C++ 内置的一个规则,意思是:“左边 < 右边”为真。导致结果是升序(1, 2, 3...)。
你的写法:
map<int, int, MyCompare> m;你告诉编译器:“别用默认的那套规则了,用我写的
MyCompare规则来排队。”
class MyCompare { public: // 这是一个重载了 () 操作符的函数 // 这种重载了 () 的类,产生的对象就像一个函数一样,我们叫它“仿函数” bool operator()(int v1, int v2) { // 降序逻辑:让大的排在前面 return v1 > v2; } };operator会返回0或者1;
map会不停的问MyCompare,v1应该排在v2前面吗?
operator()(5, 2):5>2,会返回1,为真,map就认为5应该排在2前面。