树形结构关联式容器--set介绍及使用

目录

  • 关联式容器
  • 键值对
  • 树形结构的关联式容器
    • set介绍
    • set使用

关联式容器

之前讲解的STL部分容器,如:vector、list、deque统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。
本文主要讲解关联式容器,关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的键值对,在数据检索时比序列式容器效率更高。

键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

树形结构的关联式容器

根据应用场景不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构
树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

set介绍

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的。

注意

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对set中只放value,但在底层实际存放的是由构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n
  7. set中的元素不允许修改
  8. set中的底层使用二叉搜索树(红黑树)来实现。

set使用

需要引入头文件

#include
  • 创建一个空的set
	set<int> s;
  • 利用迭代器空间创建一个有值的set(默认递增)
	//利用迭代器空间创建一个有值的set
	int arr[] = { 1,2,3,4,4 };
	//由于set里面不存放重复数据,因此只能存储4个元素:1,2,3,4
	//天然去重
	set<int> s2(arr, arr+sizeof(arr)/sizeof(arr[0]));
  • 利用迭代器空间创建一个有值的set(实现递减)
	//利用迭代器空间创建一个有值的set,递减顺序
	#include
	
	int arr[] = { 102,3,4,1 };
	set<int, greater<int>> s2(arr, arr+sizeof(arr)/sizeof(arr[0]));
  • 正向遍历(递增顺序):利用正向迭代器,set迭代器不支持修改操作
	//获取迭代器
	//set迭代器遍历,数据天然有序(递增):本质迭代器进行中序遍历
	set<int>::iterator it = s2.begin();
	while (it != s2.end())
	{
		cout << *it << " ";
		//set迭代器不支持修改,因为底层是二叉搜索树,不能随意修改。
		++it;
	}
	cout << endl;
  • 反向遍历(递减顺序):利用反向迭代器
	//反向遍历:递减
	set<int>::reverse_iterator rit = s2.rbegin();
	while (rit != s2.rend())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
  • insert:插入失败:已有数据迭代器,false
  • insert:插入成功:新数据迭代器,true
	//insert:插入失败:已有数据迭代器,false
	pair<set<int>::iterator, bool> ret = s2.insert(2);
	cout << ret.second << " " << *ret.first << endl;
	//insert:插入成功:新数据迭代器,true
	ret = s2.insert(100);
	cout << ret.second << " " << *ret.first << endl;
  • erase():可以传入值,和迭代器位置/区间。不能传入非法位置,比如end
	s2.erase(1);
	s2.erase(s2.begin());
  • find()接口:有返回值,如果查询的值存在,则返回该迭代器位置,如果不存在返回end位置
	auto it = s2.find(12);
	cout << (it != s2.end()) << endl;
	it = s2.find(3);
	cout << (it != s2.end()) << endl;
  • count():有返回值,返回值为查询值的个数,由于set里面的值不重复,因此返回值只有0或者1。
	cout << s2.count(3) << endl;
	cout << s2.count(12) << endl;

你可能感兴趣的:(c++)