set和map的实现

在这里插入图片描述

1. 源码介绍

在这里插入图片描述
我们可以看到,set和map的底层是红黑树实现的,但是我们是如何复用红黑树的呢?
在这里插入图片描述
红黑树主要看的是第二个参数,它是以第二个参数来创建结点的。

那么第一个参数有什么作用呢
在我们写的一些函数比如find:
在这里插入图片描述
这样的函数需要知道key的类型,所以我们还是要传key的。

在set里面,我们比较key可以直接比较大小。但是map里面是pair,它是怎么比较大小的呢
在这里插入图片描述
库里面是这样去实现的,先比较第一个参数,如果第一个参数不是小于,比较第二个参数。但是我们map需要的是只比较第一个参数,不需要比较第二个参数。这该怎么办呢?而且pair比较是库里面实现的,我们还不能重载。
在这里插入图片描述
库里面增加了一个KeyOfvalue,它的作用是取出value对象中key的仿函数
在这里插入图片描述
在这里插入图片描述
这样我们去比较大小的时候就可以用这个仿函数来实现复用了。

2. 封装迭代器

这里的迭代器和list的迭代器是类似的,都是需要封装结点的指针了。
在这里插入图片描述
此时,我们重点要实现的是++和–这两个函数。

2.1 ++

那么我们该如何实现++呢

既然是++,那么二叉搜索树遍历是按照中序遍历的。所以解决方法如下:
我们需要判断当前位置结点的右子树是否为空?
不为空:就找右子树的最左结点。
为空:找孩子在父亲左边的那个父亲结点

在这里插入图片描述
假设it在5这个位置,它的右边为空,它在父亲的左边,所以下一个位置是6。6的右边不为空,就找右子树的最左结点,也就是7。7的右边为空,找孩子在父亲左边的那个父亲结点,7在6的右边,不符合,6在7的左边,符合。所以下一个位置就是8。
在这里插入图片描述
此时it在15这个位置,15的右边为空,找孩子在父亲左边的那个父亲结点。但是一直找到8,都没找到。然后8的父亲是空,也就结束。

代码实现:
在这里插入图片描述
后置++就可以套用一下:
在这里插入图片描述

2.2 - -

那么我们该如何实现- -呢

减减就和加加反着来就行了。
我们需要判断当前位置结点的左子树是否为空?
不为空:就找左子树的最右结点。
为空:找孩子在父亲右边的那个父亲结点

在这里插入图片描述

2.3 进行完善

在这里插入图片描述
这里在红黑树里面定义一个普通迭代器和一个const迭代器。

set迭代器定义:
在这里插入图片描述
set里面的迭代器都是const修饰的,原因是key不能被修改。
在这里插入图片描述
map迭代器就不需要,普通的就调用普通迭代器,const就调用const迭代器。

typename在这里的意思是:
因为我们要取一个类模板的内嵌类型,但是我们不能直接去取,因为还没有实列化。加这个意思是:告诉编译器它是一个类型,等实列化了再去取。

3. operator[ ]

首先,我们需要写一个find函数:
在这里插入图片描述
然后,我们需要把insert改造一下:
在这里插入图片描述
在这里插入图片描述
这里我们需要保存一下cur,因为在翻转的情况下,cur可能会改变。

那么set和map封装的情况如下:
在这里插入图片描述
这里set的insert的意思是从const迭代器里面构造一个普通迭代器。
在这里插入图片描述
map就不需要因为普通的和const是分开的。

最后我们用insert来完成[ ]:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学代码的咸鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值