C++ map/set(1)

1.什么是map和set

map和set 

就是二叉树的value和key模型

map是value模型    set是key模型

map和set都是基于红黑树实现的

红黑树具有平衡性质        

那么思考一下   算法库里面的find函数和STL里面的find函数有什么区别

2.函数find

iterator find( const Key& key ); const_iterator find( const Key& key ) const;

算法里面的find是暴力搜索 一个一个搜索 时间复杂度是O(n)

但是STL的find只用搜索高度次就可以了实践复杂度是O(logn)(红黑树具有平衡性质)

参数:key 是要查找的元素的值。 返回值: 如果找到与 key 相等的元素,返回指向该元素的迭代器。 如果未找到,返回指向 std::set 容器末尾的迭代器(即 end())。

set可以实现去除(把重复的数据剔除)

map可以实现重复出现的数据统计次数

此外set的迭代器遍历默认是中序遍历

3.函数lower_bound

用于在 std::set 中查找第一个不小于给定值的元素。

参数:key 是用于查找的参考值。 返回值: 如果 std::set 中存在不小于 key 的元素,返回指向第一个这样元素的迭代器。 如果 std::set 中所有元素都小于 key,则返回 std::set::end()

4.函数upper_boundhan

用于在 std::set 中查找第一个大于给定值的元素。

参数:key 是用于查找的参考值。 返回值: 如果 std::set 中存在大于 key 的元素,返回指向第一个这样元素的迭代器。 如果 std::set 中所有元素都小于等于 key,则返回 std::set::end()。

为啥lower_bound是找<=

而upper_boundhan是找>

这样设计的好处是什么

 好处是我如果erase的区间是(itlow,itup)

刚好涵盖了25到60(包括25和60)的全部数

5.函数equal_range

参数:key 是要查找的键值。 返回值:返回一个 std::pair 对象

其中 first 是指向第一个不小于 key 的元素的迭代器(等同于 lower_bound(key) 的返回值)

second 是指向第一个大于 key 的元素的迭代器(等同于 upper_bound(key) 的返回值)。

在 std::set 中,如果 key 存在,first 指向该元素,second 指向该元素的下一个位置;

如果 key 不存在,first 和 second 相等,都指向第一个大于 key 的元素(或者在没有更大元素时指向 std::set::end())。

这个接口在set上是没有意义的 但是为了保持统一就保留了 但是在multiset上是有意义的

6.multiset

multiset和普通set的区别在哪?

普通set是排序+去重的功能

而multiset是排序的功能

那么思考一下 如果multiest可以插入多个同样的值

那么我们find函数找到的是第一个insert的吗?

答案不一定 

find找到的是中序遍历第一个找到的

multiset其他接口和set是一样的

7.map和set区别

map和set的key都是不可以被修改的

但是map的value是可以被修改的!

map和set处理方式是iterator和const_iterator的是实现都是const_iterator

 那么map是怎么处理的呢?

但是区别是map的value_type是pair类型的

pair的定义

放在map中    first就是const key_type   second就是mapped_type

first代表的就是key   key是不能改变的   second就是value是可以改变的

这个地方为什么不弄两个模板参数 而是要把key和value单独放到一个类里面呢?

当我们去写operator*的时候  我们返回值要写*得到的东西

但是这个地方应该返回key和value  但是C++只能返回一个值啊!

所以我们就把它们封装起来放到pair这个类里面去了

同理 我们发现pair也没有重载流插入和流提取

我们无法直接打印pair对象

但是可以这样写用.或者→

8.如何使用map

那我们再来思考一下怎么使用map(以insert为例子 其他同理)

(1)make_pair 

既然要传pair类型过去

我就直接通过make_pair这个函数造一个pair传过去

​
map<string, string> aaa;
aaa.insert(make_pair("abc", "def"));

​

那么这个地方make_pair会产生效率问题吗?

不会  因为make_pair会被编译器处理成内联函数

(2) pair

我们自己写一个pair传过去也可以

	map<string, string> aaa;
	pair<string, string> bbb("abc","abc");
	aaa.insert(bbb);

(3)匿名对象

当然匿名对象也可以

	map<string, string> aaa;
	aaa.insert(pair<string, string> ("abc", "abc"));

(4)隐式类型转换也可以

	map<string, string> aaa;
	aaa.insert({ "abc", "abc" });

这个地方为什么可以?

C++11增加了可以多参数的构造函数类型转换 但是前提是要加{}

这个地方原本是构造函数+拷贝构造

编译器直接优化成了构造函数了

但是+了引用就不能隐式类型转换了

为什么?

因为隐式类型转换会产生临时变量

临时变量具有常性

但是引用权限不能放大

一定要+引用必须在前面加上一个const

	const pair<string, string>& bbb = {"abc","abc"};

此外

记得区分具有常性的int类型和const int类型!

当然上面的几种方法 pair函数中我们传进去的key可以不是const的 编译器会帮我们处理成const类型的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值