树形结构关联式容器

编程入门 行业动态 更新时间:2024-10-24 16:23:07

树形结构关联式<a href=https://www.elefans.com/category/jswz/34/1771431.html style=容器"/>

树形结构关联式容器

目录

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

关联式容器

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

键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量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中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2​n
  7. set中的元素不允许修改
  8. set中的底层使用二叉搜索树(红黑树)来实现。

set使用

需要引入头文件

#include<set>
  • 创建一个空的set
	set<int> s;
  • 利用迭代器空间创建一个有值的set(默认递增)
	//利用迭代器空间创建一个有值的setint 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<functional>int arr[] = { 10,2,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:插入失败:已有数据迭代器,falsepair<set<int>::iterator, bool> ret = s2.insert(2);cout << ret.second << " " << *ret.first << endl;//insert:插入成功:新数据迭代器,trueret = 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;

map介绍

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型,value_type绑定在一起,为其取别名称为pair:
    typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的。
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  5. map支持下标访问符,即在[ ]中放入key,就可以找到与key对应的value。
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

map使用

  • 需要引入头文件
#include<map>
  • 构造一个空的map
	map<int, int> m;
  • 构造带值的map:通过迭代器构建,迭代器需要pair类型(包含key和value)
	//创建了一个pair类型数组,里面有四个pair类型对象pair<int, int> arr[] = { pair<int, int>(5, 5), pair<int, int>(1, 2),pair<int, int>(3,3), pair<int, int>(0,0) };//map中key不能重复,value可以重复map<int, int> m2(arr, arr + sizeof(arr) / sizeof(arr[0]));printMap(m2);printMap_r(m2);

其中map迭代器正向遍历(递增)输出实现如下:
不能直接解引用,而是通过指针指向输出值

template <class T1, class T2>
void printMap(const map<T1, T2>& m)
{//map中数据是pair//迭代器访问的顺序:按照key的中序遍历的顺序typename map<T1, T2>::const_iterator it = m.begin();while (it != m.end()){//不能直接输出pair对象cout << it->first << "-->" << it->second << endl;++it;}
}

其中map迭代器反向遍历(递减)输出实现如下:

template <class T1, class T2>
void printMap_r(const map<T1, T2>& m)
{//map中数据是pair//迭代器访问的顺序:按照key的中序遍历的顺序typename map<T1, T2>::const_reverse_iterator it = m.rbegin();while (it != m.rend()){//不能直接输出pair对象cout << it->first << "-->" << it->second << endl;++it;}
}

通过传入greater参数实现递减排序

	//通过传入greater参数实现递减排序map<int, int, greater<int>> m3(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto& p : m3){//范围for拿出来的p是已经进行过解引用了,因此使用.cout << p.first << "-->" << p.second << endl;}
  • [ ]:传入key值可以对key值对应的value进行读取以及修改
    如果key值不存在,则创建key值value为缺省值
    如果key值存在,则返回该key值对应的value值
	//对key值为1的value进行输出cout << m2[1] << endl;对key值为1的value进行修改m2[1] = 100;cout << m2[1] << endl;

operator[]:内部过程

  1. 创建一个pair对象,内容:k—value缺省值
  2. 插入第一步创建的pair对象
    a.插入成功:返回pair《pair对象的迭代器,true>
    b.插入失败:返回pair<已经存在的键值为k的pair对象迭代器,false>
  3. 获取插入返回值的first成员:是一个map中pair对象的迭代器
  4. 解引用第三步中的迭代器:解引用之后为map中的pair对象
  5. 获取第四步中的pair对象的second成员:其实就是k对应的v:
    a.如果插入成功:v是缺省值
    b.如果插入失败:v是之前已存在的值
  • at接口和operator[]区别:at执行插入的操作,如果key不存在,抛异常
	//at接口和operator[]区别:at执行插入的操作,如果key不存在,抛异常cout << m2.at(1000) << endl;
  • 两种常见的插入方式
  1. 调用pair构造函数创建对象
  2. 调用make_pair函数创建对象
	//两种常见的插入方式:map<int, int> m3;//1.调用pair构造函数创建对象auto ret = m.insert(pair<int, int>(1, 1));//ret是一个pair类型对象,该pair类型里面包含一个迭代器和bool值(插入成功或者失败)// 第一个.first是调出迭代器,第二个->first是调出key值cout << ret.first->first << "-->" << ret.first->second << ret.second << endl;//2.调用make_pair函数创建对象ret = m.insert(make_pair(2, 2));
  • erase():删除,返回值为返回删除个数,由于key值不能重复,因此返回只有0或1
	size_t num = m.erase(2);
  • find():查找操作
	//查找按照key值查找auto it = m.find(1);cout << it->first << "-->" << it->second << endl;//查找失败,返回end迭代器it = m.find(222);cout << (it == m.end()) << endl;

multiset使用

  • multiset:可以存放重复的数据。set去重
	int arr[] = { 1,10,2,5,3,33,12,44,32,2,2,1 };//multiset:可以存放重复的数据multiset<int> s(arr, arr + sizeof(arr) / sizeof(arr[0]));for (auto& e : s){cout << e << " ";}cout << endl;

其他接口类似。

multimap使用

  • multimap:key和value都可以重复
	multimap<int, int> m;m.insert(make_pair(10, 10));m.insert(make_pair(10, 11));m.insert(make_pair(10, 122));m.insert(make_pair(11, 10));m.insert(make_pair(10, 10));for (auto& p : m){cout << p.first << "-->" << p.second << endl;}

注意:multimap没有[ ]的操作,因为key值可以重复,没有唯一性,不知道给哪个key赋值。

更多推荐

树形结构关联式容器

本文发布于:2023-12-05 00:44:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1662602.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:容器   结构

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!