【C++】25.封装红黑树实现mymap和myset
文章目录
- 1. 源码及框架分析
- 2. 模拟实现map和set
- 2.1 实现出复用红黑树的框架,并支持insert
- 2.2 支持iterator的实现
- 2.2.1 iterator核心源代码
- 2.2.2 iterator实现思路分析
- 2.3 map支持[]
- 2.4 bit::map和bit::set代码实现
- Myset.h
- Mymap.h
- RBTree.h
1. 源码及框架分析
SGI-STL30
版本源代码,map
和set
的源代码在map/set/stl_map.h/stl_set.h/stl_tree.h
等几个头文件中。
map
和set
的实现结构框架核心部分截取出来如下:
// set
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_set.h>
#include <stl_multiset.h>
// map
#ifndef __SGI_STL_INTERNAL_TREE_H
#include <stl_tree.h>
#endif
#include <stl_map.h>
#include <stl_multimap.h>
// stl_set.h
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:
// typedefs:
typedef Key key_type;
typedef Key value_type;
private:
typedef rb_tree<key_type, value_type,
identity<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing set
};
// stl_map.h
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
// typedefs:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
};
// stl_tree.h
struct __rb_tree_node_base
{
typedef __rb_tree_color_type color_type;
typedef __rb_tree_node_base* base_ptr;
color_type color;
base_ptr parent;
base_ptr left;
base_ptr right;
};
// stl_tree.h
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc
= alloc>
class rb_tree {
protected:
typedef void* void_pointer;
typedef __rb_tree_node_base* base_ptr;
typedef __rb_tree_node<Value> rb_tree_node;
typedef rb_tree_node* link_type;
typedef Key key_type;
typedef Value value_type;
public:
// insert用的是第二个模板参数左形参
pair<iterator,bool> insert_unique(const value_type& x);
// erase和find用第一个模板参数做形参
size_type erase(const key_type& x);
iterator find(const key_type& x);
protected:
size_type node_count; // keeps track of size of tree
link_type header;
};
template <class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
typedef __rb_tree_node<Value>* link_type;
Value value_field;
};
- 通过下图对框架的分析,我们可以看到源码中
rb_tree
用了一个巧妙的泛型思想实现,rb_tree
是实现key
的搜索场景,不是key/value
的搜索场景不是直接写死的,而是由第二个模板参数Value
决定_rb_tree_node
中存储的数据类型。set
实例化rb_tree
时第二个模板参数给的是key
,map
实例化rb_tree
时第二个模板参数给的是pair<const key, T>
,这样一颗红黑树既可以实现key
搜索场景的set
,也可以实现key/value
搜索场景的map
。- 要注意一下,源码里面模板参数是用
T
代表value
,而内部写的value_type
不是我们我们日常key/value
场景中说的value
,源码中的value_type
反而是红黑树结点中存储的真实的数据的类型。rb_tree
第二个模板参数Value
已经控制了红黑树结点中存储的数据类型,为什么还要传第一个模板参数Key
呢?尤其是set
,两个模板参数是一样的,这是很多人的一个疑问。要注意的是对于map
和set
,find/erase
时的函数参数都是Key
,所以第一个模板参数是传给find/erase
等函数做形参的类型的。对于set
而言两个参数是一样的,但是对于map
而言就完全不一样了,map
insert
的是pair
对象,但是find
和ease
的是Key
对象。- 吐槽一下,这里源码命名风格比较乱,
set
模板参数用的Key
命名,map
用的是Key
和T
命名,而rb_tree
用的又是Key
和Value
,可见大佬有时写代码也不规范,乱弹琴。
2. 模拟实现map和set
2.1 实现出复用红黑树的框架,并支持insert
参考源码框架,map
和set
复用之前我们实现的红黑树。
我们这里相比源码调整一下,key
参数就用K
,value
参数就用V
,红黑树中的数据类型,我们使用T。
其次因为RBTree
实现了泛型不知道T
参数导致是K
,还是pair<K, V>
,那么insert
内部进行插入逻辑比较时,就没办法进行比较,因为pair
的默认支持的是key
和value
一起参与比较,我们需要时的任何时候只比较key
,所以我们在map
和set
层分别实现一个MapKeyOfT
和SetKeyOfT
的仿函数传给RBTree
的KeyOfT
,然后RBTree
中通过KeyOfT
仿函数取出T
类型对象中的key
,再进行比较,具体细节参考如下代码实现。
// pair的<运算符重载,用于比较两个pair对象
template <class T1, class T2>
bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{
// 先比较first,如果first相等再比较second
// 返回true的两种情况:
// 1. lhs.first小于rhs.first
// 2. first相等(!(rhs.first<lhs.first))且lhs.second小于rhs.second
return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second);
}
namespace bit
{
// map类模板:实现键值对的映射
template<class K, class V>
class map
{
// MapKeyOfT仿函数类,用于从pair中提取key
struct MapKeyOfT
{
// 重载()运算符,返回pair中的first作为键值
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
// 插入键值对
bool insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
private:
// 底层使用红黑树存储,K是键类型,pair<K,V>是实际存储的数据类型,MapKeyOfT用于提取键
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
// set类模板:实现集合
template<class K>
class set
{
// SetKeyOfT仿函数类,用于返回键值本身
struct SetKeyOfT
{
// 由于set中key就是value,直接返回key
const K& operator()(const K& key)
{
return key;
}
};
public:
// 插入元素
bool insert(const K& key)
{
return _t.Insert(key);
}
private:
// 底层使用红黑树存储,K既是键类型也是数据类型
RBTree<K, K, SetKeyOfT> _t;
};
}
// 定义红黑树节点的颜色
enum Colour
{
RED, // 红色节点
BLACK // 黑色节点
};
// 红黑树节点结构
template<class T>
struct RBTreeNode
{
T _data; // 节点数据
RBTreeNode<T>* _left; // 左子节点
RBTreeNode<T>* _right; // 右子节点
RBTreeNode<T>* _parent; // 父节点
Colour _col; // 节点颜色
// 节点构造函数
RBTreeNode(const T& data)
: _data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{}
};
// 红黑树类模板
// K: 键类型
// T: 数据类型
// KeyOfT: 从数据中提取键的仿函数类型
template<class K, class T, class KeyOfT>
class RBTree
{
private:
typedef RBTreeNode<T> Node; // 节点类型别名
Node* _root = nullptr; // 根节点指针
public:
// 插入数据
bool Insert(const T& data)
{
// 空树情况处理
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK; // 根节点必须为黑色
return true;
}
KeyOfT kot; // 创建KeyOfT对象用于提取键值
Node* parent = nullptr; // 记录父节点
Node* cur = _root; // 从根节点开始查找
// 查找插入位置
while (cur)
{
if (kot(cur->_data) < kot(data)) // 当前节点键值小于待插入键值,往右走
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data)) // 当前节点键值大于待插入键值,往左走
{
parent = cur;
cur = cur->_left;
}
else
{
return false; // 键值已存在,插入失败
}
}
// 创建新节点
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED; // 新节点默认为红色
// 连接新节点到父节点
if (kot(parent->_data) < kot(data))
{
parent->_right = cur; // 作为右子节点
}
else
{
parent->_left = cur; // 作为左子节点
}
cur->_parent = parent; // 设置父节点
// 这里省略了红黑树的平衡调整代码
return true;
}
};
2.2 支持iterator的实现
2.2.1 iterator核心源代码
// 红黑树基础迭代器结构
struct __rb_tree_base_iterator
{
// 定义节点指针类型别名
typedef __rb_tree_node_base::base_ptr base_ptr;
base_ptr node; // 当前节点指针
// 迭代器自增操作
void increment()
{
if (node->right != 0) { // 如果有右子树
node = node->right; // 先往右走一步
while (node->left != 0) // 然后一直往左走到底
node = node->left; // 找到右子树中的最小值
}
else { // 如果没有右子树
base_ptr y = node->parent; // 获取父节点
// 如果当前节点是父节点的右子节点,就继续往上找
while (node == y->right) {
node = y;
y = y->parent;
}
// 特殊情况处理:如果当前节点不是其右子节点
if (node->right != y)
node = y;
}
}
// 迭代器自减操作
void decrement()
{
// 特殊情况:如果是红节点且父节点的父节点是自己
// 说明这是一个header节点
if (node->color == __rb_tree_red &&
node->parent->parent == node)
node = node->right; // 转到最大节点
else if (node->left != 0) { // 如果有左子树
base_ptr y = node->left; // 转到左子树
while (y->right != 0) // 然后一直往右走到底
y = y->right; // 找到左子树中的最大值
node = y;
}
else { // 如果没有左子树
base_ptr y = node->parent; // 获取父节点
// 如果当前节点是父节点的左子节点,就继续往上找
while (node == y->left) {
node = y;
y = y->parent;
}
node = y; // 找到第一个不是左子节点的祖先
}
}
};
// 红黑树迭代器模板类,继承自基础迭代器
template <class Value, class Ref, class Ptr>
struct __rb_tree_iterator : public __rb_tree_base_iterator
{
typedef Value value_type; // 值类型
typedef Ref reference; // 引用类型
typedef Ptr pointer; // 指针类型
// 定义迭代器类型
typedef __rb_tree_iterator<Value, Value&, Value*> iterator;
// 构造函数
__rb_tree_iterator() {} // 默认构造
__rb_tree_iterator(link_type x) { node = x; } // 节点指针构造
__rb_tree_iterator(const iterator& it) { node = it.node; } // 拷贝构造
// 重载解引用操作符
reference operator*() const { return link_type(node)->value_field; }
// 重载箭头操作符(如果支持的话)
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif
// 重载前置自增/自减操作符
self& operator++() { increment(); return *this; }
self& operator--() { decrement(); return *this; }
};
// 重载相等操作符
inline bool operator==(const __rb_tree_base_iterator& x,
const __rb_tree_base_iterator& y) {
return x.node == y.node;
}
// 重载不等操作符
inline bool operator!=(const __rb_tree_base_iterator& x,
const __rb_tree_base_iterator& y) {
return x.node != y.node;
}
2.2.2 iterator实现思路分析
iterator实现的大框架跟list的iterator思路是一致的,用一个类型封装结点的指针,再通过重载运算符实现,迭代器像指针一样访问的行为。
这里的难点是operator++和operator–的实现。之前使用部分,我们分析了,map和set的迭代器走的是中序遍历,左子树->根结点->右子树,那么begin()会返回中序第一个结点的iterator也就是10所在结点的迭代器。
迭代器++的核心逻辑就是不看全局,只看局部,只考虑当前中序局部要访问的下一个结点。
迭代器++时,如果it指向的结点的右子树不为空,代表当前结点已经访问完了,要访问下一个结点是右子树的中序第一个,一棵树中序第一个是最左结点,所以直接找右子树的最左结点即可。
迭代器++时,如果it指向的结点的右子树空,代表当前结点已经访问完了且当前结点所在的子树也访问完了,要访问的下一个结点在当前结点的祖先里面,所以要沿着当前结点到根的祖先路径向上找。
如果当前结点是父亲的左,根据中序左子树->根结点->右子树,那么下一个访问的结点就是当前结点的父亲;如下图:it指向25,25右为空,25是30的左,所以下一个访问的结点就是30。
如果当前结点是父亲的右,根据中序左子树->根结点->右子树,当前当前结点所在的子树访问完了,当前结点所在父亲的子树也访问完了,那么下一个访问的需要继续往根的祖先中去找,直到找到孩子是父亲左的那个祖先就是中序要问题的下一个结点。如下图:it指向15,15右为空,15是10的右,15所在子树话访问完了,10所在子树也访问完了,继续往上找,10是18的左,那么下一个访问的结点就是18。
end()如何表示呢?如下图:当it指向50时,++it时,50是40的右,40是30的右,30是18的右,18到根没有父亲,没有找到孩子是父亲左的那个祖先,这是父亲为空了,那我们就把it中的结点指针置为nullptr,我们用nullptr去充当end。需要注意的是stl源码空,红黑树增加了一个哨兵位头结点做为end(),这哨兵位头结点和根互为父亲,左指向最左结点,右指向最右结点。相比我们用nullptr作为end(),差别不大,他能实现的,我们也能实现。只是–end()判断到结点时空,特殊处理一下,让迭代器结点指向最右结点。具体参考迭代器–实现。
迭代器–的实现跟++的思路完全类似,逻辑正好反过来即可,因为他访问顺序是右子树->根结点->左子树,具体参考下面代码实现。
set的iterator也不支持修改,我们把set的第二个模板参数改成const K即可, RBTree<K, const K, SetKeyOfT> _t;
map的iterator不支持修改key但是可以修改value,我们把map的第二个模板参数pair的第一个参数改成const K即可, RBTree<K, pair<const K, V>, MapKeyOfT> _t;
支持完整的迭代器还有很多细节需要修改,具体参考下面题的代码。
2.3 map支持[]
- map要支持[]主要需要修改insert返回值支持,修改RBtree中的insert返回值为pair<Iterator, bool> Insert(const T& data)
- 有了insert支持[]实现就很简单了,具体参考下面代码实现
2.4 bit::map和bit::set代码实现
Myset.h
#include"RBTree.h"
namespace bit {
template<class K>
class set {
// 仿函数类:用于set中获取键值
// 因为set中key就是value,所以直接返回key即可
struct SetKeyOfT {
const K& operator()(const K& key) {
return key;
}
};
public:
// 使用RBTree的迭代器类型
typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator const_iterator;
// 迭代器相关函数
iterator begin() {
return _t.Begin();
}
iterator end() {
return _t.End();
}
// const对象使用的迭代器接口
const_iterator begin() const {
return _t.Begin();
}
const_iterator end() const {
return _t.End();
}
// 插入函数:返回pair,包含迭代器和是否插入成功
pair<iterator, bool> insert(const K& key) {
return _t.Insert(key);
}
// 查找函数:返回指向目标位置的迭代器
iterator find(const K& key) {
return _t.Find(key);
}
private:
// 底层红黑树对象
RBTree<K, const K, SetKeyOfT> _t;
};
// 用于打印set内容的辅助函数
void Print(const set<int>& s) {
set<int>::const_iterator it = s.end();
while (it != s.begin()) {
--it;
// 注意:不支持修改值
//*it += 2;
cout << *it << " ";
}
cout << endl;
}
// set测试函数
void test_set() {
set<int> s;
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
// 插入数组中的所有元素
for (auto e : a) {
s.insert(e);
}
// 正向遍历打印
for (auto e : s) {
cout << e << " ";
}
cout << endl;
Print(s); // 反向打印
}
}
Mymap.h
#include"RBTree.h"
namespace bit {
template<class K, class V>
class map {
// 仿函数类:从pair中获取key
struct MapKeyOfT {
const K& operator()(const pair<K, V>& kv) {
return kv.first;
}
};
public:
// 定义迭代器类型
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator const_iterator;
// 迭代器接口
iterator begin() {
return _t.Begin();
}
iterator end() {
return _t.End();
}
const_iterator begin() const {
return _t.Begin();
}
const_iterator end() const {
return _t.End();
}
// 插入操作
pair<iterator, bool> insert(const pair<K, V>& kv) {
return _t.Insert(kv);
}
// 查找操作
iterator find(const K& key) {
return _t.Find(key);
}
// []运算符重载:支持通过key访问/插入value
V& operator[](const K& key) {
// 如果key不存在,插入pair(key, V())
// 如果key存在,返回对应的value引用
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
// 底层红黑树对象
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
// map测试函数
void test_map() {
map<string, string> dict;
// 测试insert
dict.insert({ "sort", "排序" });
dict.insert({ "left", "左边" });
dict.insert({ "right", "右边" });
// 测试[]操作符
dict["left"] = "左边,剩余";
dict["insert"] = "插入";
dict["string"]; // 插入默认值
// 遍历打印
map<string, string>::iterator it = dict.begin();
while (it != dict.end()) {
// 注意:不能修改first,可以修改second
//it->first += 'x'; // 错误
it->second += 'x'; // 正确
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
}
}
RBTree.h
// 定义红黑树节点的颜色
enum Colour {
RED,
BLACK
};
// 红黑树节点结构
template<class T>
struct RBTreeNode {
T _data; // 节点数据
RBTreeNode<T>* _left; // 左子节点
RBTreeNode<T>* _right; // 右子节点
RBTreeNode<T>* _parent; // 父节点
Colour _col; // 节点颜色
// 节点构造函数
RBTreeNode(const T& data)
: _data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
{}
};
// 红黑树的迭代器
template<class T, class Ref, class Ptr>
struct RBTreeIterator {
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node; // 当前节点指针
Node* _root; // 根节点指针
// 构造函数
RBTreeIterator(Node* node, Node* root)
:_node(node)
,_root(root)
{}
// 前置++:中序遍历的下一个节点
Self& operator++() {
if (_node->_right) {
// 如果有右子树,找右子树的最左节点
Node* leftMost = _node->_right;
while (leftMost->_left) {
leftMost = leftMost->_left;
}
_node = leftMost;
}
else {
// 如果没有右子树,向上找第一个作为左子树的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right) {
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
// 前置--:中序遍历的前一个节点
Self& operator--() {
if (_node == nullptr) { // 处理end()迭代器
// 找整棵树的最右节点
Node* rightMost = _root;
while (rightMost && rightMost->_right) {
rightMost = rightMost->_right;
}
_node = rightMost;
}
else if (_node->_left) {
// 有左子树,找左子树的最右节点
Node* rightMost = _node->_left;
while (rightMost->_right) {
rightMost = rightMost->_right;
}
_node = rightMost;
}
else {
// 没有左子树,向上找第一个作为右子树的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left) {
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
// 解引用操作
Ref operator*() {
return _node->_data;
}
// 箭头操作符
Ptr operator->() {
return &_node->_data;
}
// 比较操作符
bool operator!= (const Self& s) const {
return _node != s._node;
}
bool operator== (const Self& s) const {
return _node == s._node;
}
};
// 红黑树类模板
template<class K, class T, class KeyOfT>
class RBTree {
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T&, T*> Iterator;
typedef RBTreeIterator<T, const T&, const T*> ConstIterator;
// 获取树的起始迭代器
Iterator Begin() {
Node* leftMost = _root;
while (leftMost && leftMost->_left) {
leftMost = leftMost->_left;
}
return Iterator(leftMost, _root);
}
// 获取树的结束迭代器
Iterator End() {
return Iterator(nullptr, _root);
}
// const版本的迭代器接口
ConstIterator Begin() const {
Node* leftMost = _root;
while (leftMost && leftMost->_left) {
leftMost = leftMost->_left;
}
return ConstIterator(leftMost, _root);
}
ConstIterator End() const {
return ConstIterator(nullptr, _root);
}
// 默认构造函数
RBTree() = default;
// 析构函数
~RBTree() {
Destroy(_root);
_root = nullptr;
}
// 插入函数
pair<Iterator, bool> Insert(const T& data) {
// 空树情况处理
if (_root == nullptr) {
_root = new Node(data);
_root->_col = BLACK; // 根节点必须是黑色
return make_pair(Iterator(_root, _root), true);
}
KeyOfT kot;
Node* parent = nullptr;
Node* cur = _root;
// 查找插入位置
while (cur) {
if (kot(cur->_data) < kot(data)) {
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_data) > kot(data)) {
parent = cur;
cur = cur->_left;
}
else {
// 键值已存在,插入失败
return make_pair(Iterator(cur, _root), false);
}
}
// 创建新节点
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED; // 新节点默认为红色
// 连接新节点到父节点
if (kot(parent->_data) < kot(data)) {
parent->_right = cur;
}
else {
parent->_left = cur;
}
cur->_parent = parent;
// 维护红黑树性质
while (parent && parent->_col == RED) {
Node* grandfather = parent->_parent;
if (parent == grandfather->_left) {
Node* uncle = grandfather->_right;
// 情况1:uncle存在且为红
if (uncle && uncle->_col == RED) {
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else { // 情况2/3:uncle不存在或为黑
if (cur == parent->_left) {
// 单旋转
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else {
// 双旋转
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else { // 对称情况
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED) {
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else {
if (cur == parent->_right) {
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else {
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK; // 确保根节点为黑色
return make_pair(Iterator(newnode, _root), true);
}
// 查找函数
Iterator Find(const K& key) {
Node* cur = _root;
while (cur) {
if (cur->_kv.first < key) {
cur = cur->_right;
}
else if (cur->_kv.first > key) {
cur = cur->_left;
}
else {
return Iterator(cur, _root);
}
}
return End();
}
private:
// 左旋操作
void RotateL(Node* parent) {
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* parentParent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (parentParent == nullptr) {
_root = subR;
subR->_parent = nullptr;
}
else {
if (parent == parentParent->_left) {
parentParent->_left = subR;
}
else {
parentParent->_right = subR;
}
subR->_parent = parentParent;
}
}
// 右旋操作
void RotateR(Node* parent) {
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* parentParent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (parentParent == nullptr) {
_root = subL;
subL->_parent = nullptr;
}
else {
if (parent == parentParent->_left) {
parentParent->_left = subL;
}
else {
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
// 销毁树
void Destroy(Node* root) {
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
private:
Node* _root = nullptr; // 根节点指针
};