C++STL总结详解

10 篇文章 0 订阅
5 篇文章 0 订阅

用C++刷题很久了,对用到的STL做个总结,方便以后查阅学习。

STL的诞生

C++的面向对象和泛型编程思想,目的是复用性的提升。
面向对象三大特性:继承、封装、多态
STL从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
算法容器之间通过迭代器进行链接。
STL六大组件容器、算法、迭代器、仿函数、适配器、空间配置器
1 容器 :各种数据结构,vector,list,deque,set,map
2 算法:常见的算法,sort ,find,copy,for_each
3 迭代器:容器和算法之间的连接
4 仿函数:行为类似函数,可作为某些算法的某种策略,例如排序默认升序,可写函数该为降序
5 适配器:用来修饰容器或者仿函数或迭代器接口的东西
6 空间配置器:负责空间的配置和管理

STL中的容器、算法和迭代器

容器:将运用最广泛的数据结构实现出来
常用的数据结构:数组、链表、树、栈和队列、集合
容器又分为:
     序列式容器:强调值的排序,容器中每个数据有固定的位置,如vector,list等
     关联式容器:二叉树结构,元素之间没有严格的物理上的顺序,如map,set
算法:质变算法和非质变算法
质变算法:运算过程中会更改区间内元素的内容,拷贝,替换等
非质变算法:查找,计数,遍历,查找等
迭代器:容器和算法之间的粘合剂,沟通的桥梁。
提供一种方法,遍历某个容器中的各个元素,又无需暴露该容器的内部表示方式。
每个容器都有自己的专属迭代器。
1

vector容器

vector和普通数组之间的区别:
    数组是静态空间,vector可以动态扩展。
动态扩展并不是在原有空间后续接新的空间,而是找到更大内存卡农关键,然后将原始数据拷贝到新空间,释放原空间。

容器:vector
算法:for_each
迭代器:vector::iterator 。支持随机访问
fig2

vector插入数据

vector<int>v;//创建容器,命名为v
	v.push_back(1);//插入数据
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	
	//通过迭代器访问容器中的数据
	vector<int>::iterator it = v.begin();//起始迭代器,指向容器中第一个元素
	cout << *it << endl;//1
	vector<int>::iterator itend = v.end();//结束迭代器,指向容器中最后一个元素的下一个位置
	while (it != itend) {
		cout << *it << endl;//1,2,3,4,5
		it++;
	}
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it << endl;//1,2,3,4,5
	}
	for_each(v.begin(), v.end(), myprint);//这种需要自己写一个函数传进去,告诉要干嘛
	return 0;
	v.insert(v1.begin(),2,1000)//在指定位置插入2个1000

使用迭代器遍历数据的方式有多种,常见的是for循环!

vector也可以存放自定义的数据类型,

如下图代码所示

class person {//定义一个person类
public:
	person(string name, int age) {
		this->m_name = name;
		this->m_age = age;
	}
	string m_name;
	int m_age;
};
int main()
{
	vector<person>v;
	person p1("aa", 10);
	person p2("bb", 20);
	person p3("cc", 30);
	person p4("dd", 40);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
		cout << it->m_name << " " << (*it).m_age << endl;
	}

嵌套vector存放数据,并用迭代器遍历

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;
	}

vector删除元素

1:如果想删除指定位置或者末尾元素,可以采用下面的方式进行删除

    vector<int>v1;
	for (int i = 0; i < 4; i++) {
		v1.push_back(i + 1);
	}
	for_each(v1.begin(), v1.end(), myptring);
	cout << endl;
	v1.pop_back();//如果要删除末尾的元素
	for_each(v1.begin(), v1.end(), myptring);
	cout << endl;
	auto it1 = v1.begin() + 2;//可以删除指定位置的元素,但删除之后迭代器会失效
	v1.erase(it1);
	for_each(v1.begin(), v1.end(), myptring);

2:如果不知道元素的具体位置,可以使用迭代器删除,但是因为删除元素之后迭代器就会失效,因此删除时候不能直接用定义好的迭代器,需要删除元素之后返回新的迭代器。代码如下

vector<int>v1;
	for (int i = 0; i < 4; i++) {
		v1.push_back(i + 1);//插入元素
	}
	for_each(v1.begin(), v1.end(), myptring);
	cout << endl;
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++) {
		if (*it == 3) {
			it = v1.erase(it);//返回新的迭代器,不然会报错
		}
		else {
			it++;
		}
	}
	for_each(v1.begin(), v1.end(),myptring);

vector互换容器

vector<int>v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), myptring);//0  1  2  3  4  5  6  7  8  9
	cout << endl;
	vector<int>v1;
	for (int i = 10; i >0; i--) {
		v1.push_back(i);
	}
	for_each(v1.begin(), v1.end(), myptring);//10  9  8  7  6  5  4  3  2  1
	cout << endl;
	cout << "after the exchange" << endl;
	v.swap(v1);
	for_each(v.begin(), v.end(), myptring);//10  9  8  7  6  5  4  3  2  1

swap函数主要用来收缩内存
利用匿名对象交换,然后系统回收匿名对象指代的对象内存

vector<int>v;
	for (int i = 0; i < 100000; i++) {
		v.push_back(i);
	}
	cout << v.size() << endl;//100000
	cout << v.capacity() << endl;//138255
	v.resize(4);
	cout << v.size() << endl;//4
	cout << v.capacity() << endl;//138255
	vector<int>(v).swap(v);//匿名函数
	cout << v.size() << endl;//4
	cout << v.capacity() << endl;//4

vector预留空间

减少vector自动扩充空间扩充的太大,可以手动指定预留多少大小
下图代码看看 10万数据需要扩充多少次,

vector<int>v;
	int num=0;
	int *p=nullptr;//
	for (int i = 0; i < 100000; i++) {
		v.push_back(i);
		if (p != &v[0]) {
			p = &v[0];
			num++;
		}
	}
	cout << num << endl;//30

如果预留空间之后,扩充次数就是1

vector<int>v;
	v.reserve(100000);
	int num=0;
	int *p=nullptr;//
	for (int i = 0; i < 100000; i++) {
		v.push_back(i);
		if (p != &v[0]) {
			p = &v[0];
			num++;
		}
	}
	cout << num << endl;//30

string容器

基本概念

本质:string是C++风格字符串,string本质是一个类
string和char* 的区别:
     char*是一个指针
    string是一个类,内部封装了char *,管理这个字符串,是一个char *型的容器
特点:
    string内部封装了很多成员方法
    例如find ,delete,replace,insert
string管理char * 分配的内存,不用担心复制越界或取值越界

构造函数

string();//创建一个空字符串
string(const char* s)//用字符串s初始化
string(const string& str)//引用,使用另一个string对象初始化
string(int n,char c)//使用n个字符c初始化

string s1;
	const char*str = "hello world";
	string s2(str);
	cout << "s2 is: " << s2 << endl;//用str去初始化新的字符串s2
	string s3(10, 'a');
	cout << s3 << endl;

赋值操作

string s1;
	s1 = "kobe bryant";
	cout << s1 << endl;
	string s2;
	s2 = s1;
	cout << s2 << endl;
	string s3;
	s3 = "a";
	cout << s3 << endl;;

	string s5;
	s5.assign("hello  ww");
	cout << s5 << endl;
	string s6;
	s6.assign("hello AC++", 5);
	cout << s6 << endl;

string拼接操作

string s1 = "我";
	s1 += "喜欢湖人队";
	cout << s1 << endl;
	string s2 = "kobe";
	cout << s1 + s2 << endl;
	s1.append("喜欢湖人队");
	cout << s1 << endl;
	s1.append("喜欢湖人队", 3);
	cout << s1 << endl;
	s1.append(s2);//追加另外一个字符串到当前字符串
	cout << s1 << endl;
	s1.append(s2, 0, 3);//参数2从哪个位置开始截取,参数3是截取多少个
	cout << s1 << endl;

string查找和替换

查找:
主要是find和rfind,返回的是一个int型数据,找不到则返回-1;

//查找
	//find从左往右找,rfind从右往左找
	string s1 = "abcdefghil";
	int pos = s1.find("de");//返回的一个int类型的值,找不到返回-1;
	cout << pos << endl;
	if (pos == -1)cout << "没找到" << endl;
	else cout << "the location is:"<<pos << endl;
	int pos1 = s1.rfind("de");//从右往左查找第一个出现的字符串;
	cout << pos1 << endl;

替换:

//替换
	//
	string s1 = "abcdefghil";
	s1.replace(1, 3, "kobe");//第一个参数是起始位置,第二个参数截止位置,第三个参数是替换的字符串
	cout << s1 << endl;//输出结果为 akobeefghil

string比较

比较按照的是ASCII码值进行比较
相等返回 0;
大于返回 1;
小于返回 -1;
比较是逐次按照对应字母大小;
主要是用来比较两个字符串是否相等。

//字符串比较
	string s1 = "kobe";
	string s2 = "james";
	int res = s1.compare(s2);
	cout << res << endl;//输出1

string字符存取

string中单个字符存取方式有两种。
char&operator[](int n);//通过[]方式获取
char&at(int n);//通过at方式获取,越界时候会抛出异常,更安全

string s1 = "kobe the legend";
	for (int i = 0; i < s1.size(); i++) {
		cout << s1[i] << " "  ;
	}
	cout << endl;
	for (int i = 0; i < s1.size(); i++) {
		cout << s1.at(i) << " ";//越界时候会抛出异常
	}
	cout << endl;
	s1[0] = 'w';//对字符串进行修改
	cout << s1 << endl;

string插入和删除

	string s = "hello";
	s.insert(1, "kobe");
	cout << s << endl;//输出结果为hkobeello
	s.erase(1, 4);//第一个参数位置,第二个参数是删几个字符
	cout << s << endl;//输出结果为hello

string子串

截取字符串中某一段字符串

string s = "abcdefg";
	string subs = s.substr(1, 3);//第一个参数为截取起始位置,第二个参数为截取多少个
	cout << subs << endl;//输出结果为bcd
	string email = "kobe@qq.com";
	//从邮件中获取用户名
	int pos = email.find("@");
	string name = email.substr(0, pos);
	cout << name <<endl;

deque容器

跟vector相比,deque的两端都可以进行删除与删除,vector在头部插入需要移动大量的数据。
3
deque内部工作原理:
    deque内部有个中控器,维护每段缓冲区中的内容,缓冲区存放真实数据。
    中控器维护的是每个缓冲区的地址,使得deque使用时像一片连续的内存空间
5

deque的构造函数

void printd(const deque<int>&d) {//封装一个只读打印数据函数
	for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	deque<int>d;
	for (int i = 0; i < 10; i++) {//直接赋值构造
		d.push_back(i);
	}
	printd(d);
	deque<int>d1(d.begin(), d.end());//区间形式赋值
	printd(d1);
	deque<int>d2(10, 100);//10个100
	printd(d2);
}

deque赋值操作

操作跟vector差不多

	deque<int>d;
	for (int i = 0; i < 10; i++) {
		d.push_back(i);
	}
	deque<int>d1;
	d1 = d;//直接赋值
	printd(d1);
	deque<int>d2;
	d2.assign(d1.begin(), d1.end());//assign赋值
	printd(d2);

deque大小操作

deque没有capacity概念,理论上可以无限填充,扩充容量时候默认是0,也可以指定

deque<int>d;
	for (int i = 0; i < 10; i++) {
		d.push_back(i);
	}
	cout << d.size() << endl;
	d.resize(15);
	printd(d);//0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
	d.resize(20,1);
	printd(d);//0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 1 1 1 1 1

deque插入删除

插入操作

deque<int>d;
	d.push_back(10);//尾插
	d.push_back(20);
	d.push_front(30);
	d.push_front(40);//头插
	
	d.pop_back();//尾删
	d.pop_front();//头删

	//指定位置插入
	d.insert(d.begin(), 1000);
	d.insert(d.begin()+2, 2000);
	printd(d);//1000 30 2000 10

	//按照区间进行插入
	deque<int>d1;
	d1.push_back(1);
	d1.push_back(2);
	d1.push_back(3);
	d.insert(d.begin(), d1.begin(), d1.end());//第一个参数插入位置,第二和第三参数是插入数据区间
	printd(d);//1 2 3 1000 30 2000 10

删除操作
删除时候提供的一定得是迭代器,迭代器可以偏移位置,指定位置

deque<int>::iterator it = d.begin();
	d.erase(it);//z指定位置
	printd(d);//2 3 1000 30 2000 10
	d.clear();清空//

deque数据存取

可以通过at或者[]访问元素,
front() back()可以获取deque的头部和尾部的元素

案例 评委打分

4

class person {//定义选手的类
public:
	person(string name, int score) {//两个属性 姓名和分数
		this->m_name = name;
		this->m_score = score;
	}
	string m_name;
	int m_score;
};
void creatperson(vector<person>&v) {//实例化选手类
	string nameseed = "ABCDE";
	for (int i = 0; i < 5; i++) {
		string name = "选手";
		name += nameseed[i];
		int score = 0;
		person p(name, score);//利用上面给出的name和score 实例化一个person类
		v.push_back(p);
	}
}

void setscore(vector<person>&v) {//给每个选手打分
	for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
		deque<int>d;
		for (int i = 0; i < 10; i++) {//先打分
			int score = rand() % 41 + 60;
			d.push_back(score);
		}
		cout << it->m_name << "  ";
		for (deque<int>::iterator it1 = d.begin(); it1 != d.end(); it1++) {
			cout << *it1 << " ";
		}
		cout << endl;
		sort(d.begin(), d.end());
		d.pop_back();//去除最低分和最高分
		d.pop_front();
		int av = 0;
		for (deque<int>::iterator it1 = d.begin(); it1 != d.end(); it1++) {
			av += *it1;
		}
		int avg = av / d.size();//选手最终的平均分
		it->m_score = avg;//将最终的平局分赋值给选手

	}
}

void showscore(vector<person>&v) {
	cout << "每个选手的最终平均分是 " << endl;
	for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
		cout << it->m_score << endl;
	}
}
int main()
{
	vector<person>v;
	creatperson(v);//创建选手类
	/*for (vector<person>::iterator it = v.begin(); it != v.end(); it++) {
		cout << it->m_name << " " << it->m_score << endl;
	}*/
	setscore(v);//给每个选手打分
	showscore(v);
}

stack容器

栈是一种先进后出(FILO)的数据结构,只有一个出口,只能从栈顶进出数据。
栈不允许进行遍历。
5

stack常用操作

stack<int>s;
	s.push(1);
	s.push(2);
	s.push(3);
	s.push(4);
	cout << s.top() << endl;
	s.pop();
	cout << s.top() << endl;
	cout << s.empty() << endl;

queue容器

queue是一种先进先出的数据结构。
4

queue<int>q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	cout << q.front() << endl;
	cout << q.back() << endl;
	q.pop();
	cout << q.front() << endl;

list容器

将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:一个是存储数据元素的数据域,一个是存储下一个结点地质的指针域
stl中的链表是一个双向循环链表
stl中链表结构
6
链表存储方式不是连续的空间,因此链表中迭代器只支持前移和后移,属于双向迭代器
list优点:
1 动态分配内存,不会造成浪费
2 插入和删除都很方便,修改指针即可
list缺点:
1 空间和时间开销比较大,存放指针域和逐次遍历

list构造函数

list<int>q;
	q.push_back(1);
	q.push_back(2);
	q.push_back(3);
	q.push_back(4);
	printl(q);
	list<int>l1(q.begin(), q.end());
	printl(l1);

list赋值和交换

list<int>q;
	q.push_back(1);
	q.push_back(2);
	q.push_back(3);
	q.push_back(4);
	printl(q);//1 2 3 4
	list<int>l1;
	l1.push_back(5);
	l1.push_back(6);
	l1.push_back(7);
	l1.push_back(8);
	printl(l1);// 5 6 7 8
	q.swap(l1);
	printl(l1);//1 2 3 4
	

list大小操作

list<int>q;
	q.push_back(1);
	q.push_back(2);
	q.push_back(3);
	q.push_back(4);
	cout << q.size() << endl;//4
	q.resize(10);//重新指定大小
	cout << q.size() << endl;//10

list插入和删除

list删除和插入都可以在两端,也可以在指定位置插入删除,但传入的位置参数都得是迭代器,不能是index。如果要删除指定元素,也可以用remove操作。

list<int>q;
	q.push_back(1);
	q.push_back(2);
	q.push_back(3);
	q.push_back(4);//尾插
	q.push_front(5);//头插
	q.pop_back();//尾删
	q.pop_front();//头删
	pl(q);//1 2 3
	list<int>::iterator it = q.begin();
	q.insert(++it, 100);//1 100 2 3
	pl(q);
	//删除
	it = q.begin();
	q.erase(it);//删除操作传入的是迭代器
	pl(q);//100,2,3
	q.push_back(10000);
	q.remove(10000);//删除指定元素值
	pl(q);
	q.clear();//清空list全部数据

list反转和排序

不可以随机访问的容器,不能用标准算法,只能用容器提供的自带的算法。不可用全局函数

list<int>q;
	q.push_back(1);
	q.push_back(2);
	q.push_back(3);
	q.push_back(4);//尾插
	q.push_front(5);//头插
	
	pl(q);//1 2 3
	q.reverse();
	pl(q);//1 2 3
	//不支持随机访问的迭代器,不可以用标准算法
	q.sort();//排序方式这样写
	pl(q);
	q.sort(mycompare);//降序排列
	pl(q);

排序案例

1
排序自定义的数据类型。

class person {//定义person的类别
public:
	person(string name, int age, int height) {
		this->m_name = name;
		this->m_age = age;
		this->m_height = height;
	}
	string m_name;
	int m_age;
	int m_height;
};
//指定排序规则
bool compareperson(person&p1, person&p2) {//定义排序函数
	//年龄按照升序
	if (p1.m_age == p2.m_age) {
		return p1.m_height > p2.m_height;
	}
	else {
		return p1.m_age < p2.m_age;
	}
	
}
int main()
{	
	list<person>li;
	person p1("kobe", 24, 8);
	person p2("james", 23, 6);
	person p3("paul", 3, 9);
	person p4("durant", 35, 5);
	person p5("yaoming", 11, 12);
	li.push_back(p1);
	li.push_back(p2);
	li.push_back(p3);
	li.push_back(p4);
	li.push_back(p5);
	for (list<person>::iterator it = li.begin(); it != li.end(); it++) {
		cout << it->m_name << "  " << it->m_age << "   " << it->m_height << endl;
	}
	li.sort(compareperson);
	cout << "自定义排序规则之后。。。。。。。。。。" << endl;
	for (list<person>::iterator it = li.begin(); it != li.end(); it++) {
		cout << it->m_name << "  " << it->m_age << "   " << it->m_height << endl;
	}
}

set/multiset容器

set容器:
所有元素插入时候都会被排好序
本质:
属于关联式容器,底层结构是二叉树
区别:
set不允许容器中有重复元素
multiset允许容器中有重复元素

void prints(set<int>&s) {
	for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
		cout << *it << "   ";
	}
	cout << endl;
}
int main()
{	
	set<int>s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(3);
	s1.insert(4);
	s1.insert(4);
	prints(s1);

}

set大小和交换

set<int>s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(4);
	s1.insert(4);
	cout << s1.size() << endl;//4
	set<int>s2;
	s2.insert(7);
	s2.insert(86);
	s2.insert(45);
	s2.insert(34);
	s2.insert(98);
	s1.swap(s2);
	prints(s2);

set插入和删除

set<int>s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(4);
	s1.insert(4);
	cout << s1.size() << endl;//4
	auto it = s1.begin();
	s1.erase(it);//传入迭代器进行删除
	prints(s1);
	s1.erase(4);//可以直接删除某一个数
	prints(s1);
	s1.clear();//清空全部数据

set查找和统计

对set容器内数据进行查找和统计
find(key)//找到了返回该数据的迭代器,找不到返回末尾数据的迭代器
count(key)//统计key的个数

set<int>s1;
	s1.insert(1);
	s1.insert(3);
	s1.insert(2);
	s1.insert(4);
	s1.insert(4);
	cout << s1.size() << endl;//4
	prints(s1);
	
	set<int>::iterator it=s1.find(1);
	if (it != s1.end()) {
		cout << "find it  " <<*it<< endl;
	}
	else cout << "not exist" << endl;

	cout << s1.count(2) << endl;

se和multiset的区别

1 set不允许插入重复数据,multiset允许
2 set插入数据同时会返回插入结果,表示是否插入成功
3 multiset不会检查数据,因此可以重复插入

set<int>s1;
	s1.insert(10);
	pair<set<int>::iterator,bool> ret = s1.insert(10);//检查数据是否插入成功
	if (ret.second == true) {
		cout << "插入成功" << endl;
	}
	else {
		cout << "failed" << endl;
	}
	multiset<int>s2;//multiset运行重复插入数据
	s2.insert(10);
	s2.insert(10);
	for (multiset<int>::iterator it = s2.begin(); it != s2.end(); it++) {
		cout << *it << endl;
	}

pair对组的创建

成对出现的数据,利用对组可以返回两个数据

set<int>s1;
	s1.insert(10);
	pair<string, int>p("kobe", 24);
	cout << p.first << "  " << p.second << endl;

内置类型指定排序规则

在还没插入数据之前就要指定插入规则
需要重载运算符,需要自己写一个仿函数。

class mycompare {//需要重载运算符
public:
	bool operator()(int a,int b){
		return a > b;
	}
};
int main()
{	
	set<int,mycompare>s1;
	s1.insert(10);
	s1.insert(50);
	s1.insert(20);
	s1.insert(5);
	for (set<int, mycompare>::iterator it = s1.begin(); it != s1.end(); it++) {
		cout << *it << "  ";
	}
	cout << endl;
	pair<string, int>p("kobe", 24);

自定义类型指定排序规则

class person {//定义person的类别
public:
	person(string name, int age, int height) {
		this->m_name = name;
		this->m_age = age;
		this->m_height = height;
	}
	string m_name;
	int m_age;
	int m_height;
};
//指定排序规则
class comparep {
public :
	bool operator()(const person&p1, const person&p2) {
		if (p1.m_age == p2.m_age) {
			return p1.m_height > p2.m_height;
		}
		else {
			return p1.m_age > p2.m_age;
		}
	}
};
int main()
{	
	set<person, comparep >s;//此时的set容器需要提前指定排序规则
	person p1("kobe", 24, 8);
	person p2("james", 6, 23);
	person p3("jordan", 23, 3);
	person p4("durant", 35, 11);
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);
	//迭代器也需要指定排序规则
	for (set<person, comparep>::iterator it = s.begin(); it != s.end(); it++) {
		cout <<it->m_name<< it->m_name << " " << it->m_age << endl;
	}

map/multimap容器

map中的元素都是pair
pair中第一个元素是key(键值),第二个元素是value(实值)
所有元素都会根据元素的键值进行排序
map/multimap属于关联式容器,底层是二叉树结构
优点:
可以根据key快速的找到value
map不允许有重复的key值元素
multimap允许有重复的key值

构造函数

void printm(map<int, int>&m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << it->first << "  " << (*it).second << endl;
	}
}
int main()
{	
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));//匿名对组,
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 60));
	printm(m);//根据键值自动排序
	map<int, int>m1;
	m1 = m;
	map<int, int>m2(m);
	printm(m);//根据键值自动排序

map容器大小和交换

cout << m.size() << endl;

map插入和删除

插入方式有四种
但不太推荐第4种方式,要是插入错了,会默认添加value为0的,可以利用第四种方式去访问数据

map<int, int>m;
	m.insert(pair<int, int>(1, 10));//匿名对组,
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 60));//第一种插入方法
	m.insert(make_pair(4, 50));//第二种插入方法
	m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
	m[23] = 34;//第四种插入方法

删除操作

map<int, int>m;
	m.insert(pair<int, int>(1, 10));//匿名对组,
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 60));//第一种插入方法
	m.insert(make_pair(4, 50));//第二种插入方法
	m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
	m[23] = 34;//第四种插入方法
	printm(m);
	m.erase(m.begin());
	printm(m);
	m.erase(3);//按照键值删除
	m.erase(m.begin(), m.end());//按照区间进行删除
	m.clear();//清空全部数据

map查找和统计

find返回的是一个迭代器,如果没找到就返回末尾元素位置的迭代器。

map<int, int>m;
	m.insert(pair<int, int>(1, 10));//匿名对组,
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 60));//第一种插入方法
	m.insert(make_pair(4, 50));//第二种插入方法
	m.insert(map<int, int>::value_type(8, 12));//第三种插入方法
	m[23] = 34;//第四种插入方法
	printm(m);
	
	map<int,int>::iterator pos = m.find(5);//按照key值进行查找,返回的是迭代器
	if (pos != m.end()) {
		cout << "找到了" << pos->first << "  " << pos->second << endl;
	}
	else {
		cout << "没找到" << endl;
	}

统计操作
统计的是key值
如果是map结果只能是0/1
如果是multimap则结果可能是其他值

map排序

利用仿函数去重载排序规则
默认按照key值进行升序排序

map<int,int,sortmap>m;
	m.insert(make_pair(1, 10));//匿名对组,
	m.insert(make_pair(3, 30));
	m.insert(make_pair(2, 60));//
	m.insert(make_pair(4, 50));//
	
	
	for (map<int, int, sortmap>::iterator it = m.begin(); it != m.end(); it++) {
		cout << it->first << " " << it->second << endl;
	}

员工分组

在这里插入图片描述

class worker {//定义员工的类
public:
	/*worker(string name, int salary) {
		this->m_name = name;
		this->m_salary = salary;
	}*/
	string m_name;
	int m_salary;
};

void creatework(vector<worker>&v) {//实例化员工
	string nameseed = "ABCDEFGHIJ";
	for(int i = 0; i < 10; i++) {
		worker w;
		w.m_name = "员工";
		w.m_name += nameseed[i];
		w.m_salary = rand() % 10000 + 10000;
		v.push_back(w);
	}
}
void setgroup(vector<worker>&v, multimap<int, worker>&mv) {//给员工分组
	for (vector<worker>::iterator it = v.begin(); it != v.end(); it++) {
		//产生随机部门的编号
		int depid = rand() % 3;//0 1 2
		//利用multimap将员工信息插入进去
		//key代表部门编号
		mv.insert(make_pair(depid,*it));
	}
}

void showwork(multimap<int, worker>&mv) {//显示处员工分组信息
	cout << "策划部门" << endl;
	multimap<int, worker>::iterator pos = mv.find(0);
	int count = mv.count(0);
	int index = 0;
	for (; pos != mv.end()&&index<count; pos++,index++) {
		cout << pos->second.m_name << "  " << pos->second.m_salary << endl;
	}
}
int main()
{	//创建员工
	vector<worker>v;
	creatework(v);
	/*for (vector<worker>::iterator it = v.begin(); it != v.end(); it++) {
		cout << it->m_name << " " << it->m_salary << endl;
	}*/
	//员工分组
	multimap<int, worker>mv;
	setgroup(v,mv);
	/*for (multimap<int, worker>::iterator it = mv.begin(); it != mv.end(); it++) {
		cout << it->first<< endl;
		
	}*/
	//分组显示员工信息
	showwork(mv);
	system("pause");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值