set和map容器——STL

pair对组

创建
//第一种方法:构造函数
pair<string,int> p ("Tom",10);
cout<<"姓名:"<<p.first<<" "<<"年龄:"<<p.second<<endl;

//第二种方法:make_pair函数
pair<string,int>p = make_pair("jerry",18);
cout<<"姓名:"<<p.first<<" "<<"年龄:"<<p.second<<endl;



关联式容器(set)

set的特性是:所有元素都会根据元素的键值自动被排序。set和map不同,map可以同时拥有实值和键值,而set只能拥有键值,set的元素既是键值又是实值。set不允许两个相同元素有相同的键值。

不能通过set的迭代器改变set的元素,因为set的元素值就是其键值,而键值有关系到set元素的排序,如果随意改变set中的元素值,那么就会打乱排好的顺序,会严重破坏set组织。换句话说:set的iterator是一种cosnt_iterator。

set拥有和list某些相同的性质,当对容器中的元素进行插入或者删除的时候,其他位置元素的迭代器不会受影响。

multiset特性和用法和set相同,唯一的差别在于它允许键值重复。其两者的底层实现是红黑树(这也是为什么不能通过迭代器来修改元素值的原因,会导致平衡二叉搜索树的顺序被打乱)。


插入和删除
insert(elem);//在容器中插入元素   没有push_back,直接讲元素插入即可
clear();//清除所有元素	
erase(pos);//删除pos迭代器所指的元素
erase(beg,end);//删除区间[beg,end)的所有元素
erase(elem);//删除容器中值为elem的元素,类似remove()用法

大小操作
size()//返回容器中元素的个数
empty()//判断容器是否为空

赋值操作
set& operator=(const set &lst)//重载等号=运算符
swap(lst)//交换两个集合容器

独有:查找操作
find(key)//查找键key是否存在。若存在,返回该键的元素迭代器;若不存在,返回set.end();
//string容器中也有find函数,其中返回的是首字符的数组下标,是int类型的,这里set容器中的find函数返回的是迭代器。
count(key)//查找键key元素的个数,注意在set中非0即1.返回值是int类型数据
lower_bound(keyElem)//返回第一个key>=keyElem元素的迭代器
upper_bound(keyElem)//返回第一个key>keyElem元素的迭代器
equal_range(keyElem)//返回容器中key与keyELem相等的上下限的两个迭代器
//find用法:
int main()
{
	set<int> s;
	s.insert(10);
	s.insert(20);
	s.insert(40);
	s.insert(30);

	set<int>::iterator pos = s.find(30);
	if (pos != s.end())
	{
		cout << "找到了元素:" << *pos << endl;
	}
	else
	{
		cout << "没有找到" << endl;
	}
	return 0;
}
//equal_range的用法:
int main()
{
	set<int> s;
	s.insert(10);
	s.insert(20);
	s.insert(40);
	s.insert(30);

	pair<set<int>::iterator, set<int>::iterator> ret = s.equal_range(30);
	if (ret.first != s.end())
	{
		cout << "equal_range中的lower_bound的值为:" << *ret.first << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}

	if (ret.second != s.end())
	{
		cout << "equal_range中的upper_bound的值为:" << *ret.second << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}
}


set不允许插入相同的值,multiset允许插入相同的值
//set容器的insert函数的返回值是pair<iterator,bool>类型的队组。
//multiset容器的insert函数的返回值是iterator迭代器。
//检查两次插入元素10是否成功
int main()
{
	set<int>s;
	pair<set<int>::iterator, bool> ret = s.insert(10);
	if (ret.second)
	{
		cout << "成功" << endl;
	}
	else
	{
		cout << "失败" << endl;
	}
	ret = s.insert(10);
	if (ret.second)
	{
		cout << "成功" << endl;
	}
	else
	{
		cout << "失败" << endl;
	}
	return  0;
}
//最终的结果是:成功 失败,所以说只有第一次插入成功。

从大到小排列

set容器中的元素是按照从小到大的顺序排列的,set容器的迭代器是只读的,也就是说只要插入,那么整个容器就已经是确定好的,无法对其中元素进行修改。那怎么讲元素按照从大到小来排列呢?

//set<int, >s; 如果想要得到从大到小排列的set容器,那么在插入元素之前就应该将set设计好。在< >中加入仿函数。这里是不能加入回调函数的,因为在<>中的int是数据类型,所以应该在<>中加入的应该还是数据类型,那么就用仿函数。仿函数就是一个类。
class myCompareInt
{
public:
	bool operator()(int v1, int v2) const
	{
		return v1 > v2;
	}
};

int main()
{
	set<int, myCompareInt> s;
	s.insert(10);
	s.insert(30);
	s.insert(20);
	s.insert(40);


	for (set<int, myCompareInt>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << endl;
	}
	return  0;
}

对于自定义的数据类型

例如自定义类型person,有两个属性(年龄和姓名),但是set不知道如何进行排列,所以如果直接将person类型的数据存入set容器中是会报错的。所以可以考虑使用仿函数来进行排序规则的规定(仿函数:写一个类,重载()来进行比较两个person对象)。

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()(const Person& p1, const Person& p2) const//这个const还是需要的
	{
		//按照年龄的升序
		return p1.m_age < p2.m_age;
	}
};

int main()
{
	set<Person,myCompare>s;
	Person p1("aa", 10);
	Person p2("bb", 20);
	Person p3("cc", 30);
	Person p4("dd", 40);

	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);

	for (set<Person,myCompare>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << (*it).m_name <<" "<<(*it).m_age << endl;
	}

	return  0;
}





关联式容器(map)

map的特性:所有元素都会根据元素的键值自动排序。map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值(通过key可以访问到value)。map不允许两个元素有相同的键值。

不可以通过map的迭代器改变map的键值,因为map的键值关系到map元素的排列规则。任意改变map键值将会严重破坏map组织;如果想修改元素的实值是可以的。map和list拥有某些相同的特性,当对容器中的元素进行新增操作和删除操作的时候,其他的迭代器不会受到影响。

Multimap和map的操作相同,唯一的区别是multimap键值可以重复。他俩都是以红黑树为底层实现机制。


插入和删除
insert(elem);//在容器中插入元素   没有push_back,直接讲元素插入即可。
//1,m.insert(pair<int,int>(1,1));匿名对组
//2,m.insert(make_pair(2,20));
//3,m.insert(map<int,int>::value_type(3,30)); 不推荐。
//4,m[4]=40; 不推荐,因为只要写出m[5],就会将这个元素创建出来。
clear();//清除所有元素	
erase(pos);//删除pos迭代器所指的元素
erase(beg,end);//删除区间[beg,end)的所有元素
erase(keyElem);//删除容器中key为keyElem的队组,set中是删除对应elem值的元素。类似remove()用法

大小操作
size()//返回容器中元素的个数
empty()//判断容器是否为空

赋值操作
map& operator=(const map &lst)//重载等号=运算符
swap(mp)//交换两个集合容器

独有:查找操作
find(key)//查找键key是否存在。若存在,返回该键的元素迭代器;若不存在,返回map.end();
//string容器中也有find函数,其中返回的是首字符的数组下标,是int类型的,这里set容器中的find函数返回的是迭代器。
count(keyElem)//查找键key为keyElem的队组的个数,对map来说非0即1.返回值是int类型数据,对multimap来说,值可能大于1.
lower_bound(keyElem)//返回第一个key>=keyElem元素的迭代器
upper_bound(keyElem)//返回第一个key>keyElem元素的迭代器
equal_range(keyElem)//返回容器中key与keyELem相等的上下限的两个迭代器
//find用法:
int main()
{
	map<int, int> s;
	s.insert(pair<int, int>(1, 10));
	s.insert(pair<int, int>(2, 20));
	s.insert(pair<int, int>(3, 30));
	s.insert(pair<int, int>(4, 40));

	map<int, int>::iterator pos = s.find(2);
	if (pos != s.end())
	{
		cout << "找到了元素:" << pos->first<<" "<<pos->second << endl;
	}
	else
	{
		cout << "没有找到" << endl;
	}
	return 0;
}
//equal_range(keyElem)用法:
	pair<map<int, int>::iterator, map<int, int>::iterator> ret2 = m.equal_range(3);
	if (ret2.first != m.end())
	{
		cout << "找到了equal_range中的lower_bound的key= " << ret2.first->first << "value=" << ret2.first->second << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}
	if (ret2.second != m.end())
	{
		cout << "找到了equal_range中的upper_bound的key= " << ret2.second->first << "value=" << ret2.second->second << endl;
	}


从大到小排列
//还是需要利用仿函数
class myCompareInt//仿函数的类
{
public:
	bool operator()(int v1,int v2) const
	{
		return v1 > v2;
	}
};

int main()
{
	map<int, int, myCompareInt> m;
	m.insert(make_pair(1, 10));
	m.insert(make_pair(3, 30));
	m.insert(make_pair(2, 20));
	m.insert(make_pair(4, 40));

	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) 
	{
		cout << (*it).first << "  " << (*it).second << endl;
	}
	return 0;
}
//这就完成了g键值从大到小的
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小明同学啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值