C++笔记十(STL:stack、queue、list、set\multiset、map\multimap)

1.stack容器

1.1基本概念
stack是一种先进后出的数据结构,只有一个出口。而且栈不允许有遍历操作。数据入栈、出栈的一端为栈顶,另一端为栈底。(可以想象成弹夹)

1.2stack常用接口
构造函数:
1> stack stk; //stack采用模板类实现,stack对象的默认构造函数形式
2> stack(const stack &stk); //拷贝构造函数
赋值操作:
3> stack& operator=(const stack &stk); //重载等号操作符
数据存取:
4> void push(elem); //向栈顶添加元素
5> void pop(); //从栈顶移除第一个元素
6> top(); //返回栈顶元素
大小操作:
7> empty(); //判断堆栈是否为空
8> size(); //返回栈的大小

void test14()
{
    
    
	stack<int> stk;	//默认构造
	for (int i = 0; i < 10; i++)
	{
    
    
		stk.push(i);	//push()从栈顶添加元素
	}
	stack<int> stk1(stk);	//拷贝构造函数
	stack<int> stk2;
	stk2 = stk1;	//重载等号操作符赋值
	stk.pop();	//删除栈顶元素
	cout << "栈顶元素:" << stk.top() << endl;	//返回8。top返回栈顶元素
	if (stk1.empty())
	{
    
    
		cout << "stk1为空" << endl;
	}
	else
	{
    
    
		cout << "stk1非空" << endl;
	}
	cout << "stk2大小:" << stk2.size() << endl;
}

2. queue容器

2.1 queue的基本概念
queue是一种先进先出的数据结构,它有两个出口。(可以想成排队买饭)
队列容器允许从一端新增数据,从另一端移除数据
队列中只有队头和队尾可以被外界使用,所以队列也不可以遍历
队列中进数据为入队(push)。出数据为出队(pop)。入队一端为队尾(back),出队一端为队头(front)。判断为空empty(),大小size()。

2.2queue常用接口
构造函数:
1> queue< T > que; //queue采用模板类实现,queue对象的默认构造形式
2> queue(const queue< T > &que); //拷贝构造函数
赋值操作:
3> queue& operator = (const queue< T > &que); //重载等号操作符
数据存取:
4> void push(elem); //往队尾添加元素
5> void pop(); //从队头移除第一个元素
6> back(); //返回最后一个元素
7> front(); //返回第一个元素
大小操作
8>bool empty(); //判断堆栈是否为空
9> size(); //返回栈大小

void test15()
{
    
    
	queue<int> que;	//默认构造函数
	for (int i = 0; i < 5; i++)
	{
    
    
		que.push(i);	//push 入队操作
	}
	queue<int> que1(que);	//拷贝构造函数
	queue<int> que2 = que1;	//重载等号赋值
	if (!que1.empty())
	{
    
    
		que1.pop();	//出队
		cout << "que1的队尾元素:" << que1.back() << endl;
		cout << "que1的队首元素:" << que1.front() << endl;
		cout << "que1的大小:" << que1.size() << endl;
	}
	else
	{
    
    
		cout << "que1为空!" << endl;
	}
}

3.list容器

3.1 list基本概念
功能:将数据链式存储。
链表(list):是一种在物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
链表组成:链表由一系列的结点组成。
结点组成:一个是存储数据的数据域,一个是存储下一个结点的地址的指针域。
STL中链表为带头节点的双向循环链表(最后一个结点的next指向头结点)。
链表优点:可以在任意位置进行快速插入和删除元素,不像数组必须要先删除后移动,只用改指针,效率更高。而且采用动态内存分配,不会造成内存浪费和溢出
链表缺点:遍历效率低,占用空间会比较大。
由于链表存储方式并不是连续的内存空间,所以链表list中的迭代器只支持前移和后移,所以是一个双向迭代器。
list还有一个重要的性质,插入和删除操作都不会造成原有list迭代器的失效,这在vector中是不成立的。(vector中指向某元素的迭代器如果在进行插入删除操作后,vector容器又重新开辟新空间,那么显然这个迭代器还指向原有地址便会失效,在list中就不会出现这种状况,除非指向的元素被删除)

总结:list与vector是两个最常用的容器,各有优缺点!

3.2list的构造函数
功能:创建list容器
函数原型:
1> list list; //list采用模板类实现,默认构造
2> list(beg,end); //构造函数将[beg,end)区间中的元素拷贝给本身
3> list(n,elem); //构造函数将n个elem拷贝给本身
4> list(cosnt list< T > &lst); //拷贝构造函数

void ListPrintf(const list<int> &lst)
{
    
    
	for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)
	{
    
    
		cout << *it << "\t";
	}
	cout << endl;
}
void test16()
{
    
    
	list<int> L;	//默认构造函数
	for (int i = 0; i < 5; i++)
	{
    
    
		L.push_back(i);
	}
	cout << "L:";
	ListPrintf(L);
	list<int> L1(L.begin(), L.end());	//使用区间构造
	cout << "L1:";
	ListPrintf(L1);
	list<int> L2(3, 8);	//3个8
	cout << "L2:";
	ListPrintf(L2);
	list<int> L3(L2);	//拷贝构造
	cout << "L3:";
	ListPrintf(L3);
}

3.3list赋值和交换
功能:给list容器进行赋值,以及交换list容器。
函数原型:
1> assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身
2> assign(n, elem); //将n个elem拷贝赋值给本身
3> list& operator=(const list &lst); //重载等号操作符
4> swap(lst); //将lst与本身的元素互换

void test17()
{
    
    
	list<int> L(3, 8);
	cout << "L:";
	ListPrintf(L);	//ListPrintf()函数前面的示例有实现

	list<int> L1;
	L1.assign(L.begin(),L.end());	//使用assign(beg,end)函数赋值
	cout << "L1:";
	ListPrintf(L1);

	list<int> L2;
	L2.assign(5, 6);	//使用assign(n,elem)函数赋值
	cout << "L2:";
	ListPrintf(L2);

	list<int> L3;
	L3 = L2;	//使用等号赋值
	cout << "L3:";
	ListPrintf(L3);

	L3.swap(L1);	//使用swap函数交换L1与L3
	cout << "L1与L3交换后!" << endl;
	cout << "L1:";
	ListPrintf(L1);
	cout << "L3";
	ListPrintf(L3);
}

3.4list大小操作
功能:对list容器的大小进行操作
函数原型:
1> int size(); //返回容器的元素个数
2> bool empty(); //判断容器是否为空
3> resize(num); //重新指定容器的长度为num,若容器变长,则用默认值0填充,若变短,则末尾超出的元素被删除
4> resize(num, elem); //重新指定容器长度,效果与前面一样,只不过默认值由0变为可以指定的elem

void test18()
{
    
    
	list<int> L(5, 8);
	if (!L.empty())
	{
    
    
		cout << "L的大小为:" << L.size() << endl;
		cout << "L的大小改为1!" << endl;
		L.resize(1);
		cout << "L:";
		ListPrintf(L);
		cout << "L的大小改为10!" << endl;
		L.resize(10, 6);
		cout << "L:";
		ListPrintf(L);
	}
	else
	{
    
    
		cout << "L为空!" << endl;
	}
}

3.5list插入和删除
功能:对list容器进行数据的插入和删除
函数原型:
1> push_back(elem); //在容器尾部加入一个元素
2> pop_back(); //删除容器中最后一个元素
3> push_front(elem); //在容器开头插入一个元素
4> pop_front(); //从容器开头移除一个元素
5> insert(pos, elem); //在pop位置插入elem元素的拷贝,返回新数据的位置(返回迭代器)
6> insert(pos, n, elem); //在迭代器pos位置插入n个元素elem
7> insert(pos, beg, end); //在迭代器pos位置插入[beg, end)区间的数据,无返回值
8> clear(); //清空容器所有数据
9> erase(beg, end); //删除[beg, end)区间的数据,返回下一个数据所在位置
10> erase(pos); //删除pos位置的数据,返回下一个数据的位置
11> remove(elem);//删除容器中所有与elem值匹配的元素

void test19()
{
    
    
	list<int> L;
	for (int i = 1; i <= 3; i++)
	{
    
    
		L.push_back(i);
		L.push_front(i);
	}
	ListPrintf(L);
	L.pop_back();	//删除容器最后一个元素
	L.pop_front();	//删除容器第一个元素
	ListPrintf(L);

	L.insert(L.begin(), 10);	//在容器头部添加一个元素10
	ListPrintf(L);
	L.insert(L.end(), 3, 10);	//在容器尾部添加三个10
	ListPrintf(L);
	list<int> L1(2, 8);
	list<int>::iterator it = L1.end();
	it--;
	L.insert(L.end(), L1.begin(), it);	//可见STL中凡是与区间相关的都是左闭右开
	ListPrintf(L);

	L.remove(2);	//删除所有与2匹配的结点
	ListPrintf(L);
	L.erase(L.begin());
	ListPrintf(L);
	L.clear();
	cout << "L.size:" << L.size() << endl;
}

3.6 list数据存取
功能:对list容器中数据进行存取
函数原型:
1> front(); //返回第一个元素
2> back(); //返回最后一个元素
list不支持at函数以及[]是因为底层实现原因。list是链表,结点之间的地址不是连续的,而且list只支持双向迭代器,不能跳跃式访问。

void test()
{
    
    
	list<int>::iterator it;
	it++;
	//it = it + 3;	//报错!可见该迭代器不支持跳跃式访问
}
void test20()
{
    
    
	list<int> L;
	for (int i = 0; i < 5; i++)
	{
    
    
		L.push_back(i);
	}
	ListPrintf(L);
	//0 1 2 3 4
	cout << "L第一个元素是:" << L.front() << endl;	//0
	L.back() = 10;
	ListPrintf(L);
	//0       1       2       3       10
}

3.7list反转和排序
功能:将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
1> reverse(); //反转链表
2> sort(); //链表排序
注意:这里sort函数用法与前面queue之中不同,凡是不支持随机迭代器的容器,不可以用标准算法,但是这些容器内部会提供一些算法(成员函数)。如果要实现降序排列,就要写个类似MyCompare函数,并把函数名当参数传入sort函数中。

bool MyCompare(int v1, int v2)
{
    
    
	return v1 > v2;
}

class MC
{
    
    
public:
	bool operator()(int v1, int v2)
	{
    
    
		return v1 > v2;
	}
};

void test21()
{
    
    
	list<int> L;
	for (int i = 0; i < 5; i++)
	{
    
    
		L.push_back(rand());
	}
	cout << "L:";
	ListPrintf(L);
	cout << "反转后L:";
	L.reverse();
	ListPrintf(L);
	cout << "从小到大排序:";
	L.sort();
	ListPrintf(L);

	//降序排列
	L.sort(MC());
	//L.sort(MyCompare);
	ListPrintf(L);
}

3.8排序案例
对于自定义数据类型,如果要进行排序需要自己制定排序规则,使用函数回调

函数回调见https://www.cnblogs.com/danshui/archive/2012/01/02/2310114.html

案例描述:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高。

排序规则:按照年龄进行升序排列,如果年龄相同按身高进行降序
实现:

class Person
{
    
    
public:
	Person(string name, int height, int age) :m_Name(name), m_Height(height), m_Age(age) {
    
    }

	string m_Name;
	int m_Height;
	int m_Age;
};

bool PerCompare(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;
	}
}

void test22()
{
    
    
	list<Person> L;
	Person p1("刘备", 160, 35);
	Person p2("关羽", 170, 35);
	Person p3("张飞", 159, 35);
	Person p4("马超", 180, 35);
	Person p5("赵云", 176, 22);
	Person p6("黄忠", 155, 55);
	L.push_back(p1);
	L.push_back(p2);
	L.push_back(p3);
	L.push_back(p4);
	L.push_back(p5);
	L.push_back(p6);

	for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
	{
    
    
		cout << "姓名:" << it->m_Name << "   年龄:" << it->m_Age << "   身高:" << it->m_Height << endl;
	}
	cout << "年龄升序,年龄相同身高降序排序后:" << endl;
	L.sort(PerCompare);
	for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
	{
    
    
		cout << "姓名:" << it->m_Name << "   年龄:" << it->m_Age << "   身高:" << it->m_Height << endl;
	}
}

4.set/multiset容器

4.1set基本概念
简介:所有元素插入时自动排序。
本质:set/multiset是关联容器,底层由二叉树实现。
set/multiset区别:set不允许容器中有重复元素。multiset允许容器中有重复元素。

4.2set构造函数与赋值
功能:创建set容器以及赋值
函数原型:
构造:
1> set st; //默认构造函数
2> set(const set &st); //拷贝构造函数
赋值:
3> set& operator=(const set &st); //重载等号操作符

void SetPrintf(const set<int> &s)
{
    
    
	for (set<int>::const_iterator it = s.begin(); it != s.end(); it++)
	{
    
    
		cout << *it << "\t";
	}
	cout << endl;
}

void test23()
{
    
    
	set<int> s;	//默认构造
	s.insert(1);
	s.insert(22);
	s.insert(3);
	s.insert(44);
	s.insert(5);
	cout << "s:";
	SetPrintf(s);
	set<int> s1(s);	//拷贝构造
	cout << "s1:";
	SetPrintf(s1);
	set<int> s2;
	s2 = s;	//重载等号操作符
	cout << "s2:";
	SetPrintf(s2);	//会自动排序
}

4.3set大小和交换
功能描述:统计set容器的大小以及交换set容器
函数原型:
注意:set不支持resize(),因为如果支持,假如利用resize增大容器大小,那么填充的便会重复,与set要求不符!
1> size(); //返回容器中元素的数目
2> empty(); //判断容器是否为空
3> swap(st); //交换两个集合容器

void test24()
{
    
    
	set<int> s1;
	set<int> s2;
	for (int i = 0; i < 5; i++)
	{
    
    
		s1.insert(i);
		s2.insert(i + 5);
	}
	cout << "s1:";
	SetPrintf(s1);
	cout << "s2:";
	SetPrintf(s2);
	if (!s1.empty())
	{
    
    
		cout << "s1大小:" << s1.size() << endl;
		s1.swap(s2);
	}
	else
	{
    
    
		cout << "s1为空!" << endl;
	}
	cout << "s1、s2交换后:" << endl;
	cout << "s1:";
	SetPrintf(s1);
	cout << "s2:";
	SetPrintf(s2);
}

4.4set插入和删除
功能描述:set容器进行插入数据和删除数据
函数原型:
1> insert(elem); //在容器中插入元素
2> clear(); //清除所有元素
3> erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
4> erase(beg, end); //删除区间[beg, end)的所有元素,返回下一个元素的迭代器
5> erase(elem); //删除容器中值为elem的元素

void test25()
{
    
    
	set<int> s;
	for (int i = 0; i < 5; i++)
	{
    
    
		s.insert(i);
	}
	cout << "s:";
	SetPrintf(s);
	//s:0     1       2       3       4
	cout << "删除值为3的结点!" << endl;
	s.erase(3);
	SetPrintf(s);
	//0       1       2       4
	set<int> s1(s);
	cout << "s1:";
	SetPrintf(s1);
	//s1:0    1       2       4
	cout << "删除s1!" << endl;
	s1.erase(s1.begin(),s1.end());
	cout << "s1.size:" << s1.size() << endl;
	//s1.size:0
	cout << "删除s的第二个元素!" << endl;
	set<int>::iterator it = s.begin();
	s.erase(++it);
	cout << "s:";
	SetPrintf(s);
	//s:0     2       4
	cout << "删除s:";
	s.clear();
	SetPrintf(s);
}

4.5set查找和统计
功能:对set容器进行查找数据以及统计数据。
函数原型:
1> find(key); //查找key是否存在,返回该键的元素的迭代器;若不存在,返回set.end()。
2> count(key); //统计key的元素个数。

void test26()
{
    
    
	set<int> s;
	for (int i = 0; i < 5; i++)
	{
    
    
		s.insert(i);
	}
	cout << "s:";
	SetPrintf(s);
	cout << "值为3的后一结点的值:";
	cout << *(++s.find(3)) << endl;
	//值为3的后一结点的值:4
	cout << "值为10的个数:";
	cout << s.count(10) << endl;
	//值为10的个数:0
}

4.6set与multiset的区别
区别:
1> set不可以插入重复数据,而multiset可以。
2> set插入数据的同时会返回插入结果,表示插入是否成功。
3> multiset不会检测数据,因此可以插入重复数据。

void test27()
{
    
    
	set<int> s;
	//可以通过看定义发现insert的返回类型为pair
	pair<set<int>::iterator, bool> ret = s.insert(10);	
	if (ret.second)
	{
    
    
		cout << "插入成功!" << endl;	
	}
	else
	{
    
    
		cout << "插入失败!" << endl;
	}
	pair<set<int>::iterator, bool> ret1 = s.insert(10);
	if (ret1.second)
	{
    
    
		cout << "插入成功!" << endl;
	}
	else
	{
    
    
		cout << "插入失败!" << endl;
	}
	multiset<int> mst;
	mst.insert(10);
	mst.insert(10);
	for (multiset<int>::iterator it = mst.begin(); it != mst.end(); it++)
	{
    
    
		cout << *it << " ";
	}
	cout << endl;
}
//插入成功!
//插入失败!
//10 10

4.7pair对组创建
功能:成对出现的数据,利用对组可以返回两个数据。
两种创建方式:
1> pair<type, type> p (value1, value2);
2> pair<type, type> p = make_pair(value1, value2);

void test28()
{
    
    
	pair<int, int> p(1, 100);
	pair<int, int>p1 = make_pair(2, 101);
	cout << p.first << "  " << p.second << endl;
	cout << p1.first << "  " << p1.second << endl;
}

4.8set容器排序
目标:set会自动从小到大排序,学会如何修改排序规则。
技术:使用仿函数
注意事项:
1> 因为set在插入时就开始排序了,所以要改排序规则必须在插入之间。
2> 自定义数据类型必须指定排序规则。

class Mycompare
{
    
    
public:
	bool operator()(int v1, int v2)
	{
    
    
		return v1 > v2;
	}
};

void test29()
{
    
    
	set<int> s;	 
	s.insert(1);
	s.insert(7);
	s.insert(3);
	s.insert(0);
	s.insert(5);
	cout << "s:";
	SetPrintf(s);

	set<int, Mycompare> s1;
	s1.insert(1);
	s1.insert(7);
	s1.insert(3);
	s1.insert(0);
	s1.insert(5);
	cout << "s1:";
	for (set<int, Mycompare>::iterator it = s1.begin(); it != s1.end(); it++)
	{
    
    
		cout << *it << "\t";
	}
}
//s:0     1       3       5       7
//s1 : 7    5       3       1       0

关于自定义数据类型

class Person1
{
    
    
public:
	Person1(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	string m_Name;
	int m_Age;
};

class Mycompare1
{
    
    
public:
	bool operator()(const Person1 &p1, const Person1 &p2)
	{
    
    
		return p1.m_Age > p2.m_Age;
	}
};

void test30()
{
    
    
	set<Person1,Mycompare1> s;
	Person1 p1("张飞", 10);
	Person1 p2("刘备", 6);
	Person1 p3("关羽", 8);
	Person1 p4("曹操", 20);
	Person1 p5("刘秀", 80);
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);
	s.insert(p5);
	for (set<Person1, Mycompare1>::iterator it = s.begin(); it != s.end(); it++)
	{
    
    
		cout << "姓名:" << it->m_Name << "       年龄:" << it->m_Age << endl;
	}
}
//姓名:刘秀       年龄:80
//姓名:曹操       年龄:20
//姓名:张飞       年龄:10
//姓名:关羽       年龄:8
//姓名:刘备       年龄:6

5.map/multimap容器

5.1 map基本概念
简介:
1> map中所有元素都是pair。所以插入操作一定要使用对组pair。
2> pair中第一个元素为key(键),第二个元素为value(实值)。
3> 所有元素都会根据元素的键值自动排序。(key可以起到索引作用)

本质:
1> map/multimap都是关联式容器,底层结构由二叉树实现。

优点:
1> 可以根据key值快速找到value值。

map与multimap的区别:
1> map不允许容器中由重复的key值元素。
2> multimap允许容器中由重复的key值元素。

map高性能高效率,使用频率仅次于list与vector

5.2 map构造和赋值
功能:对map容器进行构造和赋值操作。
函数原型:
构造:
1> map<T1, T2> mp; //map默认构造函数
2> map(const map &mp); //拷贝构造函数
赋值:
1> map& operator=(const map &mp); //重载等号操作符

void MapPrintf(const map<string, int> &m)
{
    
    
	for (map<string, int>::const_iterator it = m.begin(); it != m.end(); it++)
	{
    
    
		cout << "姓名:" << it->first << "       年龄:" << it->second << endl;
	}
	cout << endl;
}

void test31()
{
    
    
	map<string, int> m;	//默认构造函数
	m.insert(pair<string, int>("张飞", 10));
	m.insert(pair<string, int>("刘备", 6));
	m.insert(pair<string, int>("关羽", 8));
	m.insert(pair<string, int>("曹操", 20));
	m.insert(pair<string, int>("刘秀", 80));
	MapPrintf(m);
	//按照键值的大小自动排序
	//姓名:曹操       年龄:20
	//姓名:关羽       年龄:8
	//姓名:刘备       年龄:6
	//姓名:刘秀       年龄:80
	//姓名:张飞       年龄:10
	map<string, int> m1(m);	//拷贝构造函数
	MapPrintf(m1);
	map<string, int> m2;
	m2 = m;	//等号操作符重载,实现赋值操作
	MapPrintf(m2);
}

5.3map大小和交换
功能:统计map容器大小以及交换map容器
函数原型:
1> size(); //返回容器中元素的数目
2> empty(); //判断容器是否为空
3> swap(); //交换两个集合容器

void MapPrintf(const map<int, int> &m)
{
    
    
	for (map<int, int>::const_iterator it = m.begin(); it != m.end(); it++)
	{
    
    
		cout << "key:" << it->first << "       value:" << it->second << endl;
	}
	cout << endl;
}

void test32()
{
    
    
	map<int, int> m;	//默认构造函数
	m.insert(pair<int, int>(5, 10));
	m.insert(pair<int, int>(3, 6));
	m.insert(pair<int, int>(4, 8));
	m.insert(pair<int, int>(2, 4));
	m.insert(pair<int, int>(1, 2));
	MapPrintf(m);
	//key:1       value:2
	//key:2       value:4
	//key:3       value:6
	//key:4       value:8
	//key:5       value:10
	map<int, int> m1;	//默认构造函数
	m1.insert(pair<int, int>(6, 12));
	m1.insert(pair<int, int>(8, 16));
	m1.insert(pair<int, int>(10, 20));
	m1.insert(pair<int, int>(9, 18));
	m1.insert(pair<int, int>(7, 14));
	MapPrintf(m1);
	//key:6       value:12
	//key:7       value:14
	//key:8       value:16
	//key:9       value:18
	//key:10       value:20
	if (!m.empty())
	{
    
    
		cout << "m的大小:" << m.size() << endl;
		//m的大小:5
		m.swap(m1);
	}
	else
	{
    
    
		cout << "m为空!" << endl;
	}
	cout << "m、m1交换后!" << endl;
	MapPrintf(m);
	//key:6       value:12
	//key:7       value:14
	//key:8       value:16
	//key:9       value:18
	//key:10       value:20
	MapPrintf(m1);
	//key:1       value:2
	//key:2       value:4
	//key:3       value:6
	//key:4       value:8
	//key:5       value:10
}

5.4map插入和删除
功能:map容器进行插入数据和删除数据
函数原型:
1> insert(elem); //在容器中插入元素
不建议用第四种,因为如果插入时没给value,它会自动创建一个并且值为0。而且如果key值错误重复的话,会覆盖key值对应的原有value值,所以一般用于访问。

//第一种插入
m.insert(pair<int, int>(5, 10));
//第二种插入
m.insert(make_pair(3, 6));
//第三种插入
m.insert(map<int, int>::value_type(4, 8));
//第四种插入
m[2] = 4;

2> clear(); //清除所有元素
3> erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
4> erase(beg, end); //删除区间[beg, end)的所有元素,返回下一个元素的迭代器
5> erase(key); //删除容器中值为key的元素

void test33()
{
    
    
	map<int, int> m;
	//第一种插入
	m.insert(pair<int, int>(5, 10));
	//第二种插入
	m.insert(make_pair(3, 6));
	//第三种插入
	m.insert(map<int, int>::value_type(4, 8));
	//第四种插入
	m[2] = 4;
	m.insert(pair<int, int>(1, 2));
	MapPrintf(m);
	//key:1       value:2
	//key:2       value:4
	//key:3       value:6
	//key:4       value:8
	//key:5       value:10
	cout << "删除键为3的元素!" << endl;
	m.erase(3);
	MapPrintf(m);
	//key:1       value:2
	//key:2       value:4
	//key:4       value:8
	//key:5       value:10
	cout << "删除第一个元素!" << endl;
	m.erase(m.begin());
	MapPrintf(m);
	//key:2       value:4
	//key:4       value:8
	//key:5       value:10
	cout << "清空!" << endl;
	m.clear();
	cout << "m.size:" << m.size() << endl;
	//m.size:0
}

5.5map的查找和统计
功能:对map容器进行查找数据以及统计数据
函数原型:
1> find(key); //查找key是否存在,返回该键的元素的迭代器;若不存在,返回set.end()。
2> count(key); //统计key的元素个数

void test34()
{
    
    
	map<int, int> m;
	m.insert(pair<int, int>(5, 10));
	m.insert(pair<int, int>(3, 6));
	m.insert(pair<int, int>(4, 8));
	m.insert(pair<int, int>(2, 4));
	m.insert(pair<int, int>(1, 2));
	cout << "m:" << endl;
	MapPrintf(m);
	cout << "查找key为4的value:" << m.find(4)->second << endl;
	//查找key为4的value:8
	cout << "key为3的元素个数:" << m.count(3) << endl;
	//key为3的元素个数:1
	map<int, int>::iterator it = m.find(7);
	if (it == m.end())
	{
    
    
		cout << "找不到!" << endl;
	}
}

3.6map容器排序
目标:map默认按照key值进行排序,如何修改排序规则。
技术:使用仿函数!

//Key降序
class Mycompare2
{
    
    
public:
	bool operator()(int v1, int v2)
	{
    
    
		return v1 > v2;
	}
};
class Person2
{
    
    
public:
	Person2(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	string m_Name;
	int m_Age;
};
//自定义类型
class Mycompare3
{
    
    
public:
	bool operator()(Person2 v1, Person2 v2)
	{
    
    
		return v1.m_Age > v2.m_Age;
	}
};
void test35()
{
    
    
	map<int, int, Mycompare2> m;
	m.insert(pair<int, int>(5, 10));
	m.insert(pair<int, int>(3, 6));
	m.insert(pair<int, int>(4, 8));
	m.insert(pair<int, int>(2, 4));
	m.insert(pair<int, int>(1, 2));
	for(map<int, int, Mycompare2>::iterator it = m.begin(); it != m.end(); it++)
	{
    
    
		cout << "key:" << it->first << "       value:" << it->second << endl;
	}
	cout << endl;
	Person2 p1("张飞", 10);
	Person2 p2("刘备", 6);
	Person2 p3("关羽", 8);
	Person2 p4("曹操", 20);
	Person2 p5("刘秀", 80);
	map<Person2, int, Mycompare3> m1;
	m1.insert(pair<Person2, int>(p1, 5));
	m1.insert(pair<Person2, int>(p2, 3));
	m1.insert(pair<Person2, int>(p3, 8));
	m1.insert(pair<Person2, int>(p4, 4));
	m1.insert(pair<Person2, int>(p5, 2));
	for (map<Person2, int, Mycompare3>::iterator pit = m1.begin(); pit != m1.end(); pit++)
	{
    
    
		cout << "key(年龄):" << pit->first.m_Age << "       value:" << pit->second << endl;
	}
}

6.案例——员工分组

6.1案例描述:
1> 公司今天招聘了10个员工(ABCDEFGHIJ),10个员工进入公司后,需要指派员工在那个部门工作。
2> 员工信息有:姓名、工资组成;部门分为:策划、美术、研发
3> 随机给10名员工分配部门和工资
4> 通过multimap进行信息的插入,key(部门编号)、value(员工)
5> 分部门显示员工信息

6.2实现步骤
1> 创建10名员工,放在vector中
2> 遍历vector容器,取出每个员工,进行随机分组
3> 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
4> 分部门显示员工信息

5.3代码实现

class Person
{
    
    
public:
    Person(string name,int wages):m_Name(name),m_Wages(wages){
    
    }
    string m_Name;
    int m_Wages;
};
//创建vector存放10名员工
void CreatPerson(vector<Person> &v)
{
    
    
    string nameSeed = "ABCDEFGHIJ";
    int wages = rand()%10000+10000;
    for(int i =0; i<10; i++)
    {
    
    
        string name = "员工";
        name += nameSeed[i];
        Person p(name,wages);
        v.push_back(p);
    }
}
//随机选择部门
void SelectDepartment(const vector<Person> &v, multimap<int, Person> & m)
{
    
    
    int choice;
    
    for(vector<Person>::const_iterator it = v.begin();it!=v.end();it++)
    {
    
    
        choice = rand()%3;
        pair<int,Person> p(choice,*it);
        m.insert(p);
    }
}
//显示信息
void Show(const multimap<int, Person> &m)
{
    
    
    //0为策划
    //1为美术
    //2为研发
    multimap<int, Person>::const_iterator mit = m.find(0);
    int count = m.count(0);
    cout<<"策划部门:"<<endl;
    for(int num=0;mit!=m.end()&&num<count;mit++,num++)
    {
    
    
        cout<<"姓名:"<<mit->second.m_Name<<"   工资:"<<mit->second.m_Wages<<endl;
    }
    cout<<endl;
    count = m.count(1);
    cout<<"美术部门:"<<endl;
    for(int num=0;num<count;num++)
    {
    
    
        cout<<"姓名:"<<mit->second.m_Name<<"   工资:"<<mit->second.m_Wages<<endl;
    }
    cout<<endl;
    count = m.count(2);
    cout<<"技术部门:"<<endl;
    for(int num=0;num<count;num++)
    {
    
    
        cout<<"姓名:"<<mit->second.m_Name<<"   工资:"<<mit->second.m_Wages<<endl;
    }
}

void test9()
{
    
    
    //创建10名员工并存储在vector中
    vector<Person> v;
    CreatPerson(v);
    //遍历vector,随机分配部门
    multimap<int, Person> m;
    SelectDepartment(v,m);
    //显示信息
    Show(m);
}

int main()
{
    
    
    srand(time(NULL));
    test9();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45884870/article/details/111353661