c++学习笔记-提高篇-STL标准模板库4(set容器、map容器)

发布时间:2023年12月26日

set容器

一、set的基本概念

1.简介:所有元素都会在插入时自动被排序

2.本质:set/multiset属于关联式容器,底层结构是用二叉树实现

3.set和multiset区别

set不允许容器中有重复元素

multiset允许容器中有重复元素

二、set构造和赋值

1.描述:创建set容器以及赋值

2.构造:

  • set<T>st;? ? ? ? ? ? ? ? // 默认构造函数
  • set(const set &st)? ?//拷贝构造函数

3.赋值:

  • set& operator=(const set &st)? ?//重载等号操作符

4.示例

set容器插入数据时用insert

set容器插入数据会自动排序

#include<iostream>
using namespace std;
#include<set>

//set容器构造和赋值
void printSet(set<int>s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()
{
	set<int>s1;
	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(30);
	s1.insert(30);
	s1.insert(30);

	//遍历容器
	//set容器的特点,所有元素被插入的时候会自动排序
	//set容器不允许插入重复的值
	printSet(s1);

	//拷贝构造
	set<int> s2(s1);
	printSet(s2);

	//赋值操作
	set<int> s3;
	s3 = s2;
	printSet(s3);

}

int main()
{
	test01();

	system("pause");
	return 0;
}

三、set大小和交换

1.描述:set容器的大小、是否为空、交换

2.构造:

  • size();? ? ? ? ? ? ? ? ? ? ?//返回容器中元素的个数
  • empty();? ? ? ? ? ? ? ? ?//判断容器是否为空
  • swap(st);? ? ? ? ? ? ? ?//交换两个集合容器

3.示例:

#include<iostream>
#include<set>
using namespace std;
//set容器  大小和交换

void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

//大小
void test01()
{
	set<int> s1;
	
	//插入数据
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);	
	s1.insert(40);

	printSet(s1);

	//判断是否为空
	if (s1.empty())
	{
		cout << "s1为空" << endl;
	}
	else
	{
		cout << "s1不为空" << endl;
		cout << "s1的元素大小:" << s1.size()<< endl;

	}
}

//交换
void test02()
{
	set<int> s1;
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	set<int> s2;
	s2.insert(200);
	s2.insert(100);
	s2.insert(400);
	s2.insert(300);

	cout << "交换前:" << endl;
	printSet(s1);
	printSet(s2);

	cout << "交换后:" << endl;
	s1.swap(s2);
	printSet(s1);
	printSet(s2);

}

int main()
{
	//test01();
	test02();
	system("pause");
	return 0;
}

四、set插入和删除

1.描述:set容器进行插入数据和删除数据

2.构造:

  • insert(elem);? ? ? ? ? ? ? ? ? ? ?//在容器中插入元素
  • clear();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //清除所有元素
  • erase(pos);? ? ? ? ? ? ? ? ? ? ? ?//删除pos迭代器所指向的元素,返回下一个元素的迭代器
  • erase(beg,end);? ? ? ? ? ? ? ? //删除区间[beg,end]的所有元素,返回下一个元素的迭代器
  • erase(elem);? ? ? ? ? ? ? ? ? ? ?// 删除容器中值为elem的元素

3.示例:

#include<iostream>
using namespace std;
#include<set>
#include<vector>

//set容器的插入和删除

void printSet(set<int> &s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

void test01()
{
	set<int>s1;
	//插入
	s1.insert(20);
	s1.insert(10);
	s1.insert(40);
	s1.insert(30);

	//遍历
	printSet(s1);
	
	//删除
	s1.erase(s1.begin());
	printSet(s1);

	//删除重载版本
	s1.erase(30);
	printSet(s1);

	//清空
	//s1.erase(s1.begin(),s1.end());
	s1.clear();
	printSet(s1);

}	

int main()
{
	test01();

	system("pause");
	return 0;
}

五、set容器查找和统计

1.描述:对set容器进行查找数据以及统计数据

2.构造:

  • find(key);? ? //查找key是否存在,若存在,返回该元素的迭代器;若不存在,返回set.end()
  • count(key);?//统计key的元素个数

3.示例:

#include<set>
#include<iostream>
using namespace std;
//set容器查找和统计
void test01()
{
	//查找
	set<int>s1;

	//插入数据
	s1.insert(30);
	s1.insert(20);
	s1.insert(10);
	s1.insert(40);

	set<int>::iterator pos = s1.find(40);
	if (pos != s1.end())  //s1.end()指向最后一个元素的下一个位置
	{
		cout << "找到元素:" << *pos << endl;
	}
	else
	{
		cout << "未找到元素" << endl;
	}
	//对于set而言,统计结果不是0就是1
	//对于multiset而言,统计结果大于1	
}

//统计
void test02()
{
	set<int> s1;

	s1.insert(10);
	s1.insert(20);
	s1.insert(30);
	s1.insert(10);

	int num = s1.count(100);
	cout << "统计nus = " << num << endl;
}

int main()
{
	test02();
	system("pause");
	return 0;
}

注意:? ?count 对于set而言,统计结果不是0就是1;对于multiset而言,统计结果大于1

六、set和multiset的区别

1.区别:

  • set不可以插入重复数据,而multiset可以
  • set插入数据的同时会返回插入结果,表示插入是否成功
  • multiset不会检测数据,因此可以重复插入

2.示例:

#include<iostream>
#include<set>
using namespace std;

//set容器和multiset容器的区别
void test01()
{
	set <int>s;
	pair<set<int>::iterator, bool> ret = s.insert(10);
	if (ret.second)
	{
		cout << "第一次插入成功" << endl;
	}
	else
	{
		cout << "第一次插入失败" << endl;
	}

	pair<set<int>::iterator,bool> ret2 = s.insert(10);
	if (ret2.second)
	{
		cout << "第二次插入成功" << endl;
	}
	else
	{
		cout << "第二次插入失败" << endl;
	}

	multiset<int>s1;
	//允许插入重复值
	s1.insert(20);
	s1.insert(20);
	for (multiset<int>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << endl;
	}
	cout << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

七、pair对组创建

1.功能描述:成对出现的数据,利用对组可以返回两个数组

2.两种创建方式:

  • pair<type,type> p(value1,value2)
  • pair<type,type> p = make_pair(value1,value2)

3.示例

#include<string>
#include<iostream>
using namespace std;

//pair对组的创建
void test01()
{
	//第一种方式
	pair<string, int> p("Tom", 20);
	cout << "姓名:" << p.first << "   年龄:" << p.second << endl;

	pair<string, int> p2 = make_pair("Jerry", 30);
	cout << "姓名:" << p2.first << "   年龄:" << p2.second << endl;

}


int main()
{
	test01();
	system("pause");
	return 0;
}

?八、set容器排序

1.学习目标:

  • set容器默认排序规则为从小到大,掌握如何改进排序规则

2.主要技术点:

  • 利用仿函数,可以改变排序规则?

3.示例一:set存放内置数据类型

#include<iostream>
#include<set>
using namespace std;

//set容器排序

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


void test01()
{
	set<int>s1;

	s1.insert(10);
	s1.insert(40);
	s1.insert(20);
	s1.insert(50);
	s1.insert(30);
	for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	//指定排序规则为从大到小
	set<int, MyCompare>s2;
	s2.insert(10);
	s2.insert(40);
	s2.insert(20);
	s2.insert(50);
	s2.insert(30);
	for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++)
	{
		cout << *it << "  ";
	}
	cout << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

注意仿函数中,operator()重载“()”时需要加const
class MyCompare
{
public:
?? ?bool operator()(int v1, int v2) const
?? ?{
?? ??? ?return v1 > v2;
?? ?}
};
没加const报错的原因:通过在 operator() 函数后加上 const 修饰符,你告诉编译器这个函数不会修改对象的状态,因此可以在 const 对象上调用。这样应该能够解决与 C3848 错误相关的问题。

总结:利用仿函数指定set容器的排序规则

4.示例二:set存放自定义数据类型

#include<iostream>
#include<set>
#include<string>
using namespace std;

//set容器排序,存放自定义数据类型
class Person
{
public:
	Person(string name,int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	string m_Name;
	int m_Age;
};

class comparePerson
{
public:
	bool operator()(const Person & p1, const Person & p2) const
	{
		//按照年龄降序
		return p1.m_Age > p2.m_Age;
	}
};

void test01()
{
	//自定义的数据类型  都会指定排序规则
	set<Person,comparePerson> s1;


	//创建Person对象
	Person p1("刘备", 24);
	Person p2("张飞", 14);
	Person p3("关羽", 50);
	Person p4("Jerry", 28);
	Person p5("Tom", 39);

	s1.insert(p1);
	s1.insert(p2);
	s1.insert(p3);
	s1.insert(p4);
	s1.insert(p5);

	for (set<Person, comparePerson>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << "姓名:" << it->m_Name << "  年龄:" << it->m_Age << endl;
	}
}

int main()
{
	test01();

	system("pause");
	return 0;
}

map容器

一、map的基本概念

1.简介:

  • map中所有元素都是pair
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

2.本质:

  • map/multimap属于关联式容器,底层结构是二叉树

3.优点:

  • 可以根据key值快速查找到value值

4.map/multimap区别

  • map不允许容器中有重复key值元素
  • multimap允许容器有重复key值元素

二、map构造和赋值

1.功能描述:对map容器进行构造和赋值操作

2.函数原型:

构造:

  • map<T1,T2> mp;? ? //map默认构造
  • map(const map &mp);? ? //拷贝构造函数

赋值:

  • mp& operator = (const map &mp)? ?//重载等号运算符

3.示例:

#include<iostream>
#include<map>
using namespace std;

//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>(2, 30));
	m.insert(pair<int, int>(3, 30));

	printMap(m);

	//拷贝构造
	map<int, int>m2(m);
	printMap(m2);

	//赋值
	map<int, int>m3;
	m3 = m2;
	printMap(m3);
}

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:map中所以元素是成对出现,插入数据时要使用对组

二、map容器大小和交换

1.功能描述:统计map容器大小以及交换map容器

2.函数原型

  • size();? ? ? ? //返回容器中元素的数目
  • empty();? ? //判断容器是否为空
  • swap();? ? ?//交换两个集合

3.示例:

#include<iostream>
#include<map>
using namespace std;

//map容器  大小和交换

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

void test01()
{
	//大小
	map<int, int> m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(4, 30));
	m.insert(pair<int, int>(3, 20));


	if (m.empty())
	{
		cout << "m为空" << endl;
	}
	else
	{
		cout << "m不为空" << endl;
		cout << "m大小:" << m.size() << endl;
		cout << "m内容:" << endl;
		printMap(m);
	}
}

void test02()
{
	map<int, int> m;
	//for (int i = 1; i < 4; i++)
	//{
	//	m.insert(pair<int, int>(i, i*10));

	//}
	//printMap(m);

	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(3, 30));
	m.insert(pair<int, int>(2, 20));

	map<int, int>m2;
	m2.insert(pair<int, int>(4, 40));
	m2.insert(pair<int, int>(6, 60));
	m2.insert(pair<int, int>(3, 80));

	cout << "交换前:" << endl;
	cout << "m:" << endl;
	printMap(m);
	cout << "m2:" << endl;
	printMap(m2);
	cout << "-------------------------------" << endl;

	swap(m, m2);
	cout << "交换后:" << endl;
	cout << "m:" << endl;
	printMap(m);
	cout << "m2:" << endl;
	printMap(m2);

}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}

三、map容器插入和删除

1.功能描述:map容器进行插入数据和删除数据‘

2.函数原型:

  • insert(elem);? ? //在容器中插入元素
  • clear();? ? ? ? ? ? ?// 清除所以元素
  • erase(pos);? ? ? //删除pos迭代器所指的元素,返回下一个元素的迭代器
  • erase(beg,end);? ? ? //删除(beg,end)区间的元素,返回下一个元素的迭代器
  • erase(key);? ? ? ? ? ? //删除key值和其元素

3.示例:

#include<iostream>
#include<map>
using namespace std;

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(0, 10));

	//第四种
	m[4] = 40;

	//cout << m[5] << endl;//没有的时候默认插入0

	printMap(m);

	//删除
	m.erase(m.begin());
	printMap(m);

	m.erase(2);//按照key删除
	printMap(m);

	m.erase(m.begin(),m.end());//清空
	printMap(m);

	m.insert(pair<int,int>(0, 33));
	m.clear();//也是清空
	printMap(m);
}

int main()
{
	test01();

	system("pause");
	return 0;
}

四、map容器查找和统计

1.对map容器进行查找数据以及统计数据

2.函数原型

  • find(key);? ? //查找key是否存在,返回该键的元素的迭代器;若不存在,返回set.end()
  • count(key);? //统计key出现个数

3.示例:

#include<iostream>
#include<map>
using namespace std;

void test01()
{
	//查找
	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));


	map<int, int>::iterator pos = m.find(3);//find返回迭代器
	if (pos != m.end())
	{
		cout << "找到元素key = " << (*pos).first << "  value" << pos->second << endl;
	}
	else
	{
		cout << "未找到元素" << endl;
	}

	//统计   
	// map不允许插入重复key  对于count统计结果要么0,要么1
	//multimap允许插入重复key  对于count统计结果可以大于1
	int num = m.count(3);
	cout << "num = " << num << endl;

	multimap<int, int> m2;
	m2.insert(pair<int, int>(1, 10));	
	m2.insert(pair<int, int>(1, 10));
	m2.insert(pair<int, int>(1, 10));
	int num2 = m2.count(1);
	cout << "num2 = " << num2 << endl;


}

int main()
{
	test01();

	system("pause");
	return 0;
}

五、map容器排序

1.学习目标:map容器默认排序规则为? 按照key值进行从小到大排序,学习如何改变排序规则

2.技术要点:

  • 利用仿函数,可以改变排序规则

3.示例一:内置数据类型排序

#include<iostream>
#include<map>
using namespace std;

class myCompare
{
public:
	bool operator()(int v1, int v2) const
	{
		//降序
		return v1 > v2;
	}
};

void test01()
{
	map<int, int>m;
	m.insert(make_pair(1, 10));
	m.insert(make_pair(2, 20));
	m.insert(make_pair(5, 50));
	m.insert(make_pair(3, 30));
	m.insert(make_pair(4, 40));

	cout << "默认从小到大排序:" << endl;
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
	{
		cout << "key = " << it->first << "  value" << it->second << endl;
	}
	cout << endl;

	map<int, int, myCompare>m2;
	m2.insert(make_pair(1, 10));
	m2.insert(make_pair(2, 20));
	m2.insert(make_pair(5, 50));
	m2.insert(make_pair(3, 30));
	m2.insert(make_pair(4, 40));
	cout << "改变从大到小排序:" << endl;
	for (map<int, int, myCompare>::iterator it = m2.begin(); it != m2.end(); it++)
	{
		cout << "key = " << it->first << "  value" << it->second << endl;
	}
	cout << endl;

}

int main()
{
	test01();

	system("pause");
	return 0;
	
}

3.示例二:自定义数据类型排序

#include<iostream>
#include<map>
using namespace std;

class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

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

void test01()
{
	map<int, Person> f;
	
	Person p1("刘备", 24);
	Person p2("小阿备", 2); 
	Person p3("关羽", 20);
	Person p4("小阿飞", 3);

	f.insert(make_pair(1, p1));
	f.insert(make_pair(4, p4));
	f.insert(make_pair(3, p3));
	f.insert(make_pair(2, p2));

	cout << "----------默认排序----------" << endl;
	for (map<int, Person>::iterator it = f.begin(); it != f.end(); it++)
	{
		cout << "key = " << it->first << "  姓名:" << it->second.m_Name << "  年龄:" << it->second.m_Age << endl;
	}
	cout << endl;

	cout << "----------从大到小排序----------" << endl;
	map<int, Person, myCompare> f2;  //只能按照key值排序

	Person p11("刘备", 24);
	Person p12("小阿备", 2);
	Person p13("关羽", 20);
	Person p14("小阿飞", 3);

	f2.insert(make_pair(1, p11));
	f2.insert(make_pair(4, p14));
	f2.insert(make_pair(3, p13));
	f2.insert(make_pair(2, p12));

	for (map<int, Person, myCompare>::iterator it = f2.begin(); it != f2.end(); it++)
	{
		cout << "key = " << it->first << "  姓名:" << it->second.m_Name << "  年龄:" << it->second.m_Age << endl;
	}
	cout << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;

}

总结:自定义数据类型也只能按照key值排序,不能按照Person的年龄排序。

文章来源:https://blog.csdn.net/qq_26572229/article/details/135152826
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。