c++STL之关联式容器

目录

set容器

set的默认构造

set的插入与迭代器

set集合的元素排序

set集合的初始化及遍历

从小到大(默认情况下)

 从大到小

仿函数 

set的查找

pair的使用

multiset容器 

map和multimap容器 

map的插入与迭代器

map的大小

map的删除

map的查找


关联式容器(Associated containers),元素位置取决于特定的排序准则,和插入顺序无关

在c++STL中主要有set、multiset、map、multimap

set容器

  • set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
  • set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。

set的默认构造

set<int> setInt;            //一个存放int的set容器。

set<float> setFloat;     //一个存放float的set容器。

set<string> setString;     //一个存放string的set容器。

multiset<int> mulsetInt;            //一个存放int的multi set容器。

multi set<float> multisetFloat;     //一个存放float的multi set容器。

multi set<string> multisetString;     //一个存放string的multi set容器。

set的插入与迭代器

  • set.insert(elem);     //在容器中插入元素。
  • set.begin();  //返回容器中第一个数据的迭代器。
  • set.end();  //返回容器中最后一个数据之后的迭代器。
  • set.rbegin();  //返回容器中倒数第一个元素的迭代器。
  • set.rend();   //返回容器中倒数最后一个元素的后面的迭代器。

set集合的元素排序

  • set<int,less<int> >  setIntA;  //该容器是按升序方式排列元素。
  • set<int,greater<int>> setIntB;   //该容器是按降序方式排列元素。
  • set<int> 相当于 set<int,less<int>>。
  • less<int>与greater<int>中的int可以改成其它类型,该类型主要要跟set容纳的数据类型一致。

set集合的初始化及遍历

从小到大(默认情况下)

//集合 元素唯一 自动排序 不能按照[]方式插入元素
//默认情况下是从小到大
void main91()
{
	set<int> set1;
	for (int i = 0; i < 5; i++)
	{
		int tmp = rand();
		set1.insert(tmp);
	}
	set1.insert(100);
	set1.insert(100);
	set1.insert(100);
	for (set<int>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	while (!set1.empty())
	{
		set<int>::iterator it = set1.begin();
		cout << *it << " ";
		set1.erase(set1.begin());
	}
}

 从大到小

void main92()
{
	set<int,greater<int>> set1;
	for (int i = 0; i < 5; i++)
	{
		int tmp = rand();
		set1.insert(tmp);
	}
	set1.insert(100);
	set1.insert(100);
	set1.insert(100);
	for (set<int,greater<int>>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

}

仿函数 

对于复杂的数据类型set集合是通过用户自定义来排序的,主要利用的就是仿函数这个机制。

//仿函数
struct FuncStudent
{
	bool operator()(const Student& left, const Student& right) const
	{
		if (left.m_age < right.m_age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

void main93()
{
	set<Student, FuncStudent> set1;
	Student s1("s1", 32);
	Student s2("s2", 22);
	Student s3("s3", 16);
	Student s4("s4", 55);
	Student s5("s5", 32);

	set1.insert(s1);
	set1.insert(s2);
	set1.insert(s3);
	set1.insert(s4);
	set1.insert(s5);//两个一样的值
	//如何知道插入的结果

	//遍历
	for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << it->m_age << "\t" << it->m_name << endl;
	}
}

set的查找

  • set.find(elem);   //查找elem元素,返回指向elem元素的迭代器。
  • set.count(elem);   //返回容器中值为elem的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。
  • set.lower_bound(elem);  //返回第一个>=elem元素的迭代器。
  • set.upper_bound(elem);    //  返回第一个>elem元素的迭代器。
  • set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。

pair的使用

  • pair译为对组,可以将两个值视为一个单元。
  • pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。
  • pair.first是pair里面的第一个值,是T1类型。
  • pair.second是pair里面的第二个值,是T2类型。

set<int> setInt;

...  //往setInt容器插入元素1,3,5,7,9

pair< set<int>::iterator , set<int>::iterator > pairIt = setInt.equal_range(5);

set<int>::iterator itBeg = pairIt.first;

set<int>::iterator itEnd = pairIt.second;

//此时 *itBeg==5  而  *itEnd == 7

//如何判断insert的返回值
void main94()
{
	set<Student, FuncStudent> set1;
	Student s1("s1", 32);
	Student s2("s2", 22);
	Student s3("s3", 16);
	Student s4("s4", 55);
	Student s5("s5", 32);

	pair<set<Student, FuncStudent>::iterator, bool> pair1;
	pair1 = set1.insert(s1);
	if (pair1.second)
	{
		cout << "插入s1成功" << endl;
	}
	else
	{
		cout << "插入s1失败" << endl;
	}
	set1.insert(s2);
	set1.insert(s3);
	set1.insert(s4);
	pair1 = set1.insert(s5);//两个一样的值
	if (pair1.second)
	{
		cout << "插入s5成功" << endl;
	}
	else
	{
		cout << "插入s5失败" << endl;
	}
		//遍历
	for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << it->m_age << "\t" << it->m_name << endl;
	}
}

multiset容器 

  • multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
  • 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
void main101()
{
	multiset<int> set1;
	int tmp;

	cout << "请输入multiset集合的值:";
	scanf("%d", &tmp);
	while (tmp != 0)
	{
		set1.insert(tmp);
		cout << "请输入multiset集合的值:";
		scanf("%d", &tmp);
	}

	//遍历
	for (multiset<int>::iterator it = set1.begin(); it != set1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	while (!set1.empty())
	{
		multiset<int>::iterator it = set1.begin();
		cout << *it << " ";
		set1.erase(set1.begin());
	}
}

map和multimap容器 

  • map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。
  • map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  • map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。
  • map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  • multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

map的插入与迭代器

  • map.insert(...);    //往容器插入元素,返回pair<iterator,bool>
  • 在map中插入元素的三种方式:

假设  map<int, string> mapStu;

  • 一、通过pair的方式插入对象

mapStu.insert(  pair<int,string>(3,"小张")  );

  • 二、通过pair的方式插入对象

mapStu.inset(make_pair(-1, “校长-1”));

  • 三、通过value_type的方式插入对象

mapStu.insert(  map<int,string>::value_type(1,"小李")  );

  • 四、通过数组的方式插入值

mapStu[3] = “小刘";

mapStu[5] = “小王";

  • 前三种方法,采用的是insert()方法,该方法返回值为pair<iterator,bool>
  • 第四种方法非常直观,但存在一个性能的问题。插入3时,先在mapStu中查找主键为3的项,若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成“小刘”。若发现已存在3这个键,则修改这个键对应的value。
  • string strName = mapStu[2];   //取操作或插入操作
  • 只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。

map的大小

  • map.size(); //返回容器中元素的数目
  • map.empty();//判断容器是否为空

map的删除

  • map.clear(); //删除所有元素
  • map.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
  • map.erase(beg,end);     //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
  • map.erase(keyElem);     //删除容器中key为keyElem的对组。

map的查找

  • map.find(key);   查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
  • map.count(keyElem);   //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
//map的添加/遍历/删除
void main111()
{
	map<int, string> map1;
	
	//方法一
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));
	
	//方法二
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));
	
	//方法四
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	//容器的删除
	while (!map1.empty())
	{
		map<int, string>::iterator it = map1.begin();
		cout << it->first << "\t" << it->second << endl;
		map1.erase(it);
	}
}

//插入的四种方法异同
//前三种返回值是pair<iterator,bool>
//前三种方法若key已经存在则报错
//方法四    若key已经存在则覆盖
void main112()
{
	map<int, string> map1;

	//方法一
	pair<map<int, string>::iterator,bool> mypair1 = map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	//方法二
	pair<map<int, string>::iterator, bool> mypair3 = map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	pair<map<int, string>::iterator, bool> mypair5 = map1.insert(map<int, string>::value_type(5, "teacher05"));
	if (mypair5.second)
	{
		cout << mypair5.first->first << mypair5.first->second << endl;
	}
	else
	{
		cout << "key5 插入失败" << endl;
	}
	pair<map<int, string>::iterator, bool> mypair6 = map1.insert(map<int, string>::value_type(5, "teacher06"));
	if (mypair6.second)
	{
		cout << mypair6.first->first << mypair6.first->second << endl;
	}
	else
	{
		cout << "key5 插入失败" << endl;
	}
	//方法四
	map1[7] = "teacher07";
	map1[7] = "teacher77";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;
}

 

void main113()
{
	map<int, string> map1;

	//方法一
	map1.insert(pair<int, string>(1, "teacher01"));
	map1.insert(pair<int, string>(2, "teacher02"));

	//方法二
	map1.insert(make_pair(3, "teacher03"));
	map1.insert(make_pair(4, "teacher04"));

	//方法三
	map1.insert(map<int, string>::value_type(5, "teacher05"));
	map1.insert(map<int, string>::value_type(6, "teacher06"));

	//方法四
	map1[7] = "teacher07";
	map1[8] = "teacher08";

	//容器的遍历
	for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
	{
		cout << it->first << "\t" << it->second << endl;
	}
	cout << "遍历结束" << endl;

	//map的查找
	map<int, string>::iterator it2 = map1.find(100);
	if (it2 == map1.end())
	{
		cout << "key 100的值不存在" << endl;
	}
	else
	{
		cout << it2->first << "\t" << it2->second << endl;
	}

	//equal_range
	pair<map<int, string>::iterator, map<int, string>::iterator> mypair = map1.equal_range(5);//返回两个迭代器 形成一个pair
	//第一个迭代器>=5的位置
	//第二个迭代器>5的位置
	if (mypair.first == map1.end())
	{
		cout << "第一个迭代器不存在" << endl;
	}
	else
	{
		cout << mypair.first->first << "\t" << mypair.first->second << endl;
	}

	//使用第二个迭代器
	if (mypair.second == map1.end())
	{
		cout << "第一个迭代器不存在" << endl;
	}
	else
	{
		cout << mypair.second->first << "\t" << mypair.second->second << endl;
	}
}

 

猜你喜欢

转载自blog.csdn.net/qq_45526401/article/details/130185018