目录
4.用set来存储一个二维坐标系上的点的集合---关于结构体
一、vector容器---动态数组
1.为什么要引进动态数组?
(1)有些时候想开一个数组,单数却不知道应该开多大长度的数组合适,因为我们需要用到的数组可能会根据情况变动。这时候我们就需要用到动态数组。
(2)c++中的动态数组写作vector
2.引用库
c++中vector的实现在一个<vector>头文件中,在代码开头引入这个头文件,并在引入所有头文件之后加上一句using namespace std
#include<vector>
using namespace std;
int main(void)
{
return 0;
}
3.构造一个动态数组
vector<T> vec 其中T是我们数组要存储的数据类型:int float double都可以
4.一些增删查改动态数组的方法
vector方法总结:
push_back:在末尾加入一个元素
pop_back:删除动态数组的最后一个元素
size:获取长度
clear:清空 但是只是清空vector,并不会清空开的内存。用一种方法可以清空内存://vector<int> v;
vector<int>().swap(v);
5.使用基础的vector
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v;
for (int i = 1;i <= 10; i++)
{
v.push_back(i * i);
}
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
return 0;
}
6.构造函数
引言:我们都知道通过push_back()来向动态数组添加一个元素。如果我们需要一个长度为n的,全是1的动态数组,用for循环来写就小题大作了。so我们可以通过一个构造函数快速构建这样的一个动态数组。所谓构造函数,就是我们在定义一个对象的时候就可以给它赋值
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
int n = 10;
vector<int> vec(n, 1);//构造函数,第一个参数是初始的动态数组的长度,第二个参数表示初始的数组里面每个元素的值。
//如果不传入第二个参数,那么初始的值都是0
//通过合理的使用构造函数,可以减少代码量
for (int i = 0; i < n; i++)
{
cout << vec[i] << " ";
}
return 0;
}
7.二维动态数组
vector<vector<int> >vec2 这样定义了一个二维动态数组 注意:<int> >中间有一个空格,这个空格一定要加上,否则这些老版本的编译器不能通过编译
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
int n = 5;
vector<vector<int> > vec2;
for (int i = 0; i < n; i++)
{
vector<int> x(i + 1, 1);
vec2.push_back(x);
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < vec2[i].size(); j++)
{
cout << vec2[i][j] << " ";
}
cout << endl;
}
return 0;
}
二维动态数组的每一维的长度都可以不一样,可以是任意形状的。借助构造函数,我们可以快速构造一个n行m列的动态数组,每个元素的初始值是0:
vector<vector<int> > vec2(n,vector<int>(m,0));
下面我们用二维动态数组来记录一个1到5的乘法表
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<vector<int> > vec2;
for (int i = 0; i < 5; i++)
{
vec2.push_back(vector<int>());
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j <= i; j++)
{
vec2[i].push_back((i + 1) * (j + 1));
}
}
for (int i = 0; i < vec2.size(); i++)
{
for (int j = 0; j <= i; j++)
{
cout <<j+1<<"*"<<i+1<<"="<< vec2[i][j] << "\t";
}
cout << endl;
}
return 0;
}
二、set()容器---集合
1.构造一个集合
c++中直接构造一个set的语句为:set<T> s . 这样我们定义了一个名为s的、储存T类型数据的集合,其中T是集合要储存的数据类型。初始的时候s是空集合。比如
set<int> aa,set<string> bbb等等
2.方法
2.1插入元素
c++中用insert()函数向集合中插入一个新的元素。注意如果集合中已经存在了某个元素,再次插入不会产生任何效果,集合中是不会出现重复元素的。
2.2判断元素是否存在
c++中如果你想知道某个元素是否在集合中出现,你可以直接用count()函数。如果集合中存在我们要查找的元素,返回1,否则返回0。
2.3迭代器
.遍历元素:
c++通过迭代器可以访问集合中的每个元素,迭代器就好像一根手指指向set中的某个元素。通过操作这个手指,我们可以改变它指向的元素
通过*(解引用运算符,不是乘号的意思)操作可以获取迭代器指向的元素。
set<T>::iterator it就定义了一个迭代器it 注意:begin函数返回容器的其实元素的迭代器,end函数返回容器的尾后迭代器
2.4清空
c++中调用clear()函数就可清空set,同时会清空set占用的内存
2.5基本应用
#include<set>
#include<iostream>
using namespace std;
int main(void)
{
set<string> country;
country.insert("China");
country.insert("American");
country.insert("France");
set<string>::iterator it;
for (it = country.begin(); it != country.end(); it++)
{
cout << *it << endl;
}
cout << endl;
country.erase("American");//erase()函数用于删除集合中的元素
country.erase("England");
for (it = country.begin(); it != country.end(); it++)
{
cout << *it << endl;
}
cout << endl;
if (country.count("China"))
{
cout << "China in set" << endl;
}
country.clear();
return 0;
}
3.运算符重载
运算符重载:
set经常会配合结构体来使用,用set来存储结构体和vector有些区别,正如我们前面所说的那样,set是需要经过排序的,系统自带的数据类型有默认的比较大小的规则,而我们自定义的结构体,系统是不可能知道这个结构体比较大小的方式的
所以我们需要一种方式来告诉系统怎样比较这个结构体的大小。其中一种方法叫做运算符重载,我们需要重新定义小于符号。
struct Node
{
int x, y;
bool operator<(const Node& rhs) const
{
if (x == rhs.x)
{
return y < rhs.y;
}
else
{
return x < rhs.x;
}
}
};
4.用set来存储一个二维坐标系上的点的集合---关于结构体
#include<iostream>
#include<set>
using namespace std;
struct Point
{
int x, y;
bool operator<(const Point& rhs)const
{
if (x == rhs.x)
{
return y < rhs.y;
}
else
{
return x < rhs.x;
}
}
};
int main(void)
{
int n;
set<Point> v;
cin >> n;
for (int i = 0; i < n; i++)
{
Point temp;
cin >> temp.x >> temp.y;
v.insert(temp);
}
for (set<Point>::iterator it = v.begin(); it != v.end(); it++)
{
cout << it->x << " " << it->y << endl;
}
return 0;
}
三、map()容器---映射
映射:是指两个集合之间的元素的相互对应关系。通俗的说,就是一个元素对应另外一个元素。比如有一个姓名的集合{“tom”,“jone”},班级集合{1,2}。姓名与班级之间可以有如下的映射关系:
class{"tom"}=1,class{"jone"}=2,class{"Mary"}=1;
我们称其中的姓名集合为关键字集合(key),班级集合为值集合(value)
c++中我们常用的映射是map
1.构造一个映射
在c++中,我们构造一个map的语句为:map<T1,T2> m。这样我们定义了一个名为m的从T1类型到T2类型的映射。初始的时候m是空映射。比如map<string,int> m构建一个字符串到整数的映射,这样我们可以把一个字符串和一个整数关联起来
2.基本应用
#include<map>
#include<iostream>
using namespace std;
int main(void)
{
map<string, int> dict;
dict["Tom"] = 1;
dict["Jone"] = 2;
dict["Mary"] = 1;
if (dict.count("Mary"))
{
cout << "Mary is class " << dict["Mary"] << endl;;
dict["Mary"] = 5;
}
for (map<string, int>::iterator it = dict.begin(); it != dict.end(); it++)
{
cout << it->first << " is in class " << it->second << endl;
}
return 0;
}
3.map套set
(1)map套用set:为了帮助理解,我们举一个生活中实际例子。全校有很多班级,每个班级每个人都会有中文名。现在我们需要用一种方式来记录全校的同学的名字。如果直接用一个set记录,对于重名的同学,那么就没办法分辨了
我们可以把全校的班级进行编号,对每个班级建立一个set,也就是每个班级都映射成一个set,这样就能分辨不同班级的同名同学了
用法:map<int,set<string> > s就定义上面描述的数据结构,和二维的vector一样,两个> >中间的空格不能少
这样我们就可以进行插入和查询了,比如对2班的yuhaoran同学,我们s[2].insert("yuhaoran").然后查询yuhaoran是不是一个2班的人,是s[2].count("yuhaoran").然后还可以把他从二班删除,s[2].erase("yuhaoran")
4.map套用map
上面的结构没有办法解决同伴同名的情况。实际上,如果同班同名,单单通过名字本身是无法分辨的,需要通过其他特征来分辨。所以为了简单起见,我们只需要记录每个班级同名的人的个数
map<int,map<string,n> > s。2班有一个yuhaoran,s[2]["yuhaoran"]++ 。2班又转来了一个yuhaoran,s[2]["yuhaoran"]++
现在2班一共有多少个yuhaoran? cout<<s[2]["yuhaoran"]<<endl;
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(void)
{
map<int, map<string, int> > info;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int class_id;
string name;
cin >> class_id >> name;
info[class_id][name]++;
}
for (map<int, map<string, int> >::iterator it = info.begin(); it != info.end(); it++)
{
for (map<string, int>::iterator it1 = it->second.begin(); it1 != it->second.end(); it1++)
{
cout << "There are " << it1->second << " people name " << it1->first << " int class " << it->first << endl;
}
}
return 0;
}
四、锯齿矩阵
是指每行包含的元素个数不相同的矩阵
#include<iostream>
#include<vector>
using namespace std;
vector<int> mat[10005];//定义了一个vector类型的数组
int main(void)
{
int n, m,x,y;
cin >> n >> m;
for (int i = 0; i < m; i++)
{
cin >> x >> y;
mat[x].push_back(y);
}
for (int i = 0; i <= n; i++)
{
for (int j = 0; j < mat[i].size(); j++)
{
if (j != mat[i].size() - 1)
{
cout << mat[i][j] << " ";
}
else
{
cout << mat[i][j] << endl;
}
}
cout << endl;
}
return 0;
}