【C++】二十五、标准模板库STL之关联容器

一、关联容器简介

(一)基本概念

关联容器也是存储数据的容器,但是和顺序容器有很大的区别。

【关联容器底层数据结构:】

底层存放红黑树。

  • BST:二叉搜索树,二叉排序树:保证中序遍历排列升序有序。所以在插入结点时,需要调整结点。
  • 红黑树:是一种特殊的BST树,把结点划分为红节点和黑节点,进行调整。

【关联容器分类:】

  • set:单集合容器
  • multiset:多集合容器
  • map:单映射容器
  • multimap:多重映射容器

(二)关联容器都有的函数

【构造函数】

  1. 默认的构造:直接开辟空间。如set<int> s。
  2. 传入迭代器(指针)区间的构造函数:传入起始位置,末尾位置,会把起始~末尾的迭代器区间元素传入容器。注意也可以传入数组,字符串的指针。如set<int> s(arr,arr+len),将arr~arr+len区间的数据传入容器。注意map的数组不是一维数组,所以尽量不使用区间构造map。

【其他函数】

函数名称 含义 使用
find查找函数 因为关联容器底层是红黑树,中序遍历有序,可以使用二分查找,所以关联容器实现了自己的find,利用二分查找实现元素,时间复杂度为O(logn),比泛型算法find时间复杂度O(n)速度快。 set<int>iterator fit=s.find(x);//在s容器中查找元素x
count计数函数 返回关联容器中值为x的元素个数 int co=s.count(x);//返回x的个数
清空函数 清空容器元素 c.clear()

【类型别名:】

类型别名 含义
key_value 容器的关键字类型
mapped_type 每个关键字关联的类型,只适用于map
value_type 对于set,与key_type相同;对于map,等同于pair<const key_type>,mapped_type>

迭代器需要进行自加操作,用到it++,++it:

  • it++:先使用旧值运算,再++;原理:先对a进行备份 ,产生临时量,内置类型的临时量是常量。整个运算过程中用的都是临时量,直到表达式结束时,把a自加。
  • ++it:先自加++后,再运算;原理:用it本身,进行自加,返回it本身

所以it=begin(),it++后,还是指向begin()位置;++it后向前走了一个,指向第二个位置。


二、set

set单集合,存放元素value,不允许重复,不允许修改,按照一定次序存储。 头文件为:

# include<set>

(一)对set容器的操作

1. 增

没有必要提供端点位置的数据插入(前插,尾插),因为尾插后,会将其调整,调整后不一定在最后,所以只需要提供任意位置插入函数即可插入时不需要传入位置,只需要传入数值即可,因为树形结构会进行调整。

插入方式:

插入方式 形式 含义
插入元素 insert(val) 将元素val插入set,插入后会自动调整排序
给指定位置插入元素 insert(index,val) 位置无效,只是为了和前面顺序容器兼容,你传入了位置,不一样插入指定的位置,因为存在自动调整
插入区间元素 insert(first,last) 在set中插入(first,last)区间的元素
2. 删

三种方式:

删除方式 形式 含义
删除区间元素 erase(first,last) 删除first~last之间的元素
删除指定位置的元素 erase(index) 删除set上index上的元素
删除元素 erase(val) 删除元素val
3. 访问

可以通过迭代器来访问set容器的元素,但是不能进行修改。

(二)特点

  • 不允许数据重复,即key关键字不允许重复,可以去重。
  • set的元素不能在容器中修改,因为:元素用const修饰,修改过后不能自己调整红黑树,导致序列乱序。所以修改一个元素可以先删除再插入。
  • set在插入元素时,会进行排序,默认按照红黑树中序遍历升序的方式排序, 所以 如果用set存储对象信息,需要在对象对应的类中提供比较方式,因为set在存储数据时,不知道怎么比较对象。
  • 基于关键字的快速查询

(四)演示

# include<iostream>
# include<deque>
# include<vector>
# include<list>
# include<algorithm>
# include<iterator>
# include<set>
template<typename Container>
void show(Container& con)
{
   
	typename Container::iterator it=con.begin();//iterator为从属名称,所以声明类型,否则编译器不知道
	for(;it!=con.end();it++)
	{
   
		std::cout<<*it<<" ";
	}
	std::cout<<std::endl;
}
int main()
{
   
	std::set<int> myiset;//无参构造
	int a[]={
   0,1,2,3,4,5,6,7};
	int len=sizeof(a)/sizeof(a[0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值