C++ map與set封裝實(shí)現(xiàn)過程講解
一、前情回顧
set 參數(shù)只有 key,但是map除了key還有value。我們還是需要KV模型的紅黑樹的:
#pragma once
#include <iostream>
#include <assert.h>
#include <time.h>
using namespace std;
enum Color
{
RED,
BLACK,
};
template<class K, class V >
struct RBTreeNode
{
pair<K, V> _kv;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
Color _col;
RBTreeNode(const pair<K,V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_col(RED)
{}
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = BLACK;
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
cur->_col = RED;
if (parent->_kv.first < kv.first)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
while (parent && parent->_col == RED)
{
Node* grandfater = parent->_parent;
if (parent == grandfater->_left)
{
Node* uncle = grandfater->_right;
//情況一:u存在且為紅
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfater->_col = RED;
//向上調(diào)整
cur = grandfater;
parent = cur->_parent;
}
else
{
//情況2
if (cur == parent->_left)
{
RotateR(grandfater);
parent->_col = BLACK;
grandfater->_col = RED;
}
//情況3
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandfater);
cur->_col = BLACK;
grandfater->_col = RED;
}
break;
}
}
else//parent==grandfater->_right
{
Node* uncle = grandfater->_left;
//情況1:u存在且為紅色
if (uncle && uncle->_col == RED)
{
uncle->_col = parent->_col = BLACK;
grandfater->_col = RED;
//向上調(diào)整
cur = grandfater;
parent = cur->_parent;
}
else
{
//情況2:u不存在/u存在為黑色
//g
// p
// c
if (cur == parent->_right)
{
RotateL(grandfater);
grandfater->_col = RED;
parent->_col = BLACK;
}
//情況3
// g
// p
// c
else
{
RotateR(parent);
RotateL(grandfater);
cur->_col = BLACK;
grandfater->_col = RED;
}
break;
}
}
}
//根變黑
_root->_col = BLACK;
return true;
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == nullptr)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
subL->_right = parent;
if (ppNode == nullptr)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
void InOrder()
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
bool Check(Node*root,int blackNum,int ref)
{
if (root == nullptr)
{
//cout << blackNum << endl;
if (blackNum != ref)
{
cout << "違反規(guī)則:本條路徑的黑色結(jié)點(diǎn)的數(shù)量根最左路徑不相等" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "違反規(guī)則:出現(xiàn)連續(xù)的紅色結(jié)點(diǎn)" << endl;
return false;
}
if (root->_col == BLACK)
{
++blackNum;
}
return Check(root->_left,blackNum,ref)
&& Check(root->_right,blackNum,ref);
}
bool IsBalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col != BLACK)
{
return false;
}
int ref = 0;
Node* left = _root;
while (left)
{
if (left->_col == BLACK)
{
++ref;
}
left = left->_left;
}
return Check(_root,0,ref);
}
private:
Node* _root = nullptr;
};二、簡(jiǎn)化源碼
翻開源碼一看
RBTree的結(jié)構(gòu)源碼:是KV結(jié)構(gòu)的紅黑樹
RBTree是通過傳入的Value的值來判斷類型,也就是一棵泛型的RBTree,通過不同的實(shí)例化,實(shí)現(xiàn)出了Map和Set:
對(duì)于map:傳key,對(duì)于set:傳pair

map的結(jié)構(gòu)簡(jiǎn)化源碼:

set的結(jié)構(gòu)簡(jiǎn)化源碼:

為了讓我們的紅黑樹能夠識(shí)別set與map我們?cè)黾右粋€(gè)模板參數(shù)T:
template<class K, class T> class RBTree
對(duì)于T模板參數(shù)可能是鍵值Key,也可能是由Key和Value共同構(gòu)成的鍵值對(duì)。
如果是set容器,那么它傳入底層紅黑樹的模板參數(shù)就是Key和Key:
template<class K>
class set
{
private:
RBTree<K,K> _t;
};
如果是map容器,傳入底層紅黑樹的模板參數(shù)就是Key和Key和value的鍵值對(duì):
class map
{
private:
RBTree<K, pair<const K,V>> _t;
};
通過上面,我們可以知道,對(duì)于set和map的區(qū)別:我們只要通過第二個(gè)模板參數(shù)就能進(jìn)行區(qū)分,那是不是第一個(gè)模板參數(shù)就沒有意義了呢?
對(duì)于insert(const Value&v)來說,需要放入存入的值,確實(shí)是這個(gè)樣子的,插入的值是value,對(duì)于set就是key,對(duì)于map就是pair。
但是對(duì)于find(const Key&key)來說,查找的參數(shù)不是value,找的不是pair而是Key,對(duì)于map容器來說就不行了。
**紅黑樹的節(jié)點(diǎn)**:set容器:K和T都是鍵值Key; map容器:K是鍵值Key,T由Key和Value構(gòu)成的鍵值對(duì);但是底層紅黑樹并不知道上層容器到底是map還是set,因此紅黑樹的結(jié)點(diǎn)當(dāng)中直接存儲(chǔ)T就行了,如果是set的時(shí)候,結(jié)點(diǎn)當(dāng)中存儲(chǔ)的是鍵值Key;如果是map的時(shí)候,結(jié)點(diǎn)當(dāng)中存儲(chǔ)的就是鍵值對(duì),所以紅黑樹的結(jié)點(diǎn)定義如下,由T類型來決定紅黑樹存的是key還是pair:
template<class T>
//三叉鏈結(jié)構(gòu)
struct RBTreeNode
{
T _data;
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
RBTreeNode(const T& data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
三、仿函數(shù)
這里存在一個(gè)問題??:插入的時(shí)候data的大小如何去進(jìn)行比較:我們并不知道是什么類型是key,還是pair的比較,而我們剛開始kv結(jié)構(gòu)就直接用kv.first去比較了。
對(duì)于set是Key,可以比較
對(duì)于map是pair,那我們要取其中的first來比較,但是pair的大小并不是直接按照first去進(jìn)行比較的,而我們只需要按照first去進(jìn)行比較
由于底層的紅黑樹不知道傳的是map還是set容器,當(dāng)需要進(jìn)行兩個(gè)結(jié)點(diǎn)鍵值的比較時(shí),底層紅黑樹傳入的仿函數(shù)來獲取鍵值Key,進(jìn)行兩個(gè)結(jié)點(diǎn)鍵值的比較:這個(gè)時(shí)候我們就需要仿函數(shù)了,如果是set那就是用于返回T當(dāng)中的鍵值Key,如果是map那就是用于返回pair的first:
仿函數(shù)/函數(shù)對(duì)象也是類,是一個(gè)類對(duì)象。仿函數(shù)要重載operator()。
namespace HWC
{
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
private:
RBTree<K, pair<const K,V>,MapKeyOfT> _t;
};
namespace HWC
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
private:
RBTree<K,K,SetKeyOfT> _t;
};
博主畫了個(gè)圖更加容易進(jìn)行比對(duì)

查找過程,此時(shí)就可以套上我們所寫的仿函數(shù)對(duì)象去進(jìn)行數(shù)據(jù)的大小比較了:
KeyOfT kot;//仿函數(shù)對(duì)象
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;
}
}
四、迭代器
紅黑樹的正向迭代器是對(duì)結(jié)點(diǎn)指針進(jìn)行了封裝,所以這里的正向迭代器就只有一個(gè)成員變量:結(jié)點(diǎn)的指針,并沒有什么其他的地方,迭代器的定義:
template<class T,class Ref,class Ptr>
struct __RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef __RBTreeIterator<T,Ref,Ptr> Self;
typedef __RBTreeIterator<T, T&, T*> iterator;
Node* _node;
__RBTreeIterator(Node*node)
:_node(node)
{}
//普通迭代器的時(shí)候,它是拷貝構(gòu)造
//const迭代器的時(shí)候,它是構(gòu)造,支持用普通迭代器構(gòu)造const迭代器
__RBTreeIterator(const iterator& s)
:_node(s._node)
{}
}
*:解引用操作,返回對(duì)應(yīng)結(jié)點(diǎn)數(shù)據(jù)的引用:
Ref operator*()
{
return _node->_data;
}
->:成員訪問操作符,返回結(jié)點(diǎn)數(shù)據(jù)的引用:
Ptr operator->()
{
return &_node->_data;
}
!=、==:比較簡(jiǎn)單
bool operator !=(const Self & s) const
{
return _node != s._node;
}
bool operator ==(const Self& s) const
{
return _node == s._node;
}
這里的迭代器重點(diǎn)是迭代器的++:
一個(gè)結(jié)點(diǎn)的正向迭代器進(jìn)行++操作后,根據(jù)紅黑樹中序(左、根、右)找到當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn),中序的第一個(gè)節(jié)點(diǎn)是最左,迭代器的++怎么去找:
如果節(jié)點(diǎn)的右子樹不為空,++就是找右子樹的最左節(jié)點(diǎn)
如果節(jié)點(diǎn)的右子樹為空,++就是找祖先(孩子是父親的左的那個(gè)祖先)
代碼實(shí)現(xiàn):
Self& operator++()
{
if (_node->_right)
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
迭代器的--
對(duì)于–,如果是根,–就是左子樹,找到左子樹最大的那一個(gè)(最右節(jié)點(diǎn))
如果節(jié)點(diǎn)的左子樹不為空,--找左子樹最右的節(jié)點(diǎn)
如果節(jié)點(diǎn)的左子樹為空,--找祖先(孩子是父親的右的祖先)
代碼實(shí)現(xiàn):
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max = max->_right;
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&&cur==parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
不要忘記迭代器的兩個(gè)核心成員:begin()與end()
begin():返回中序(左、根、右)第一個(gè)結(jié)點(diǎn)的正向迭代器,即最左節(jié)點(diǎn),返回的是最左節(jié)點(diǎn),直接找最左節(jié)點(diǎn)即可
end():返回中序(左、根、右)最后一個(gè)結(jié)點(diǎn)下一個(gè)位置的正向迭代器,這里直接用空指針
template<class K, class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTreeIterator<T> iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
}
五、set的實(shí)現(xiàn)
通過前面底層紅黑樹的接口進(jìn)行套用即可實(shí)現(xiàn)set的實(shí)現(xiàn):
值得注意的是??:typename:沒有實(shí)例化的模板,區(qū)分不了是靜態(tài)變量還是類型,typename告訴編譯器是類型
#pragma once
#include "RBTree.h"
namespace hwc
{
template <class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
//typename:沒有實(shí)例化的模板,區(qū)分不了是靜態(tài)變量還是類型,typename告訴編譯器是類型
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;//key不可以修改
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair<iterator,bool> insert(const K& key)
{
//底層紅黑樹的iterator是普通迭代器
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
return pair<iterator, bool>(ret.first, ret.second);//用普通迭代器構(gòu)造const迭代器
}
private:
RBTree<K, K,SetKeyOfT> _t;
};
void test_set()
{
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
set<int> s;
for (auto e : a)
{
s.insert(e);
}
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
}六、map的實(shí)現(xiàn)
同樣是套用上底層紅黑樹的接口,不過map的實(shí)現(xiàn)有一個(gè)很重要的地方,那就是[]的實(shí)現(xiàn)
#pragma once
#include "RBTree.h"
namespace hwc
{
template<class K,class V>
class map
{
struct MapkeyOfT
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
//typename:沒有實(shí)例化的模板,區(qū)分不了是靜態(tài)變量還是類型,typename告訴編譯器是類型
typedef typename RBTree<K, pair<const K, V>, MapkeyOfT>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapkeyOfT>::const_iterator
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<const K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
RBTree<K, pair<const K, V>, MapkeyOfT> _t;
};
void test_map()
{
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
map<int, int> m;
for (auto e : a)
{
m.insert(make_pair(e, e));
}
map<int, int>::iterator it = m.begin();
while(it!=m.end())
{
it->second++;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
map<string, int> countMap;
string arr[] = { "蘋果","西瓜","香蕉","蘋果"};
for (auto& e : arr)
{
countMap[e]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
}七、紅黑樹代碼
最后,在這里送上源碼:
#pragma once
#pragma once
#include <iostream>
#include <assert.h>
#include <time.h>
using namespace std;
enum Color
{
RED,
BLACK,
};
template<class T>
struct RBTreeNode
{
T _data;
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
RBTreeNode(const T& data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
template<class T,class Ref,class Ptr>
struct __RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef __RBTreeIterator<T,Ref,Ptr> Self;
typedef __RBTreeIterator<T, T&, T*> iterator;
Node* _node;
__RBTreeIterator(Node*node)
:_node(node)
{}
//普通迭代器的時(shí)候,它是拷貝構(gòu)造
//const迭代器的時(shí)候,它是構(gòu)造,支持用普通迭代器構(gòu)造const迭代器
__RBTreeIterator(const iterator& s)
:_node(s._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
if (_node->_right)
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max = max->_right;
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent&&cur==parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
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*> const_iterator;
const_iterator begin() const
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return const_iterator(left);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
pair<iterator,bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_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),false);
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
while (parent && parent->_col == RED)
{
Node* grandfater = parent->_parent;
if (parent == grandfater->_left)
{
Node* uncle = grandfater->_right;
//情況一:u存在且為紅
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfater->_col = RED;
//向上調(diào)整
cur = grandfater;
parent = cur->_parent;
}
else
{
//情況2
if (cur == parent->_left)
{
RotateR(grandfater);
parent->_col = BLACK;
grandfater->_col = RED;
}
//情況3
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandfater);
cur->_col = BLACK;
grandfater->_col = RED;
}
break;
}
}
else//parent==grandfater->_right
{
Node* uncle = grandfater->_left;
//情況1:u存在且為紅色
if (uncle && uncle->_col == RED)
{
uncle->_col = parent->_col = BLACK;
grandfater->_col = RED;
//向上調(diào)整
cur = grandfater;
parent = cur->_parent;
}
else
{
//情況2:u不存在/u存在為黑色
//g
// p
// c
if (cur == parent->_right)
{
RotateL(grandfater);
grandfater->_col = RED;
parent->_col = BLACK;
}
//情況3
// g
// p
// c
else
{
RotateR(parent);
RotateL(grandfater);
cur->_col = BLACK;
grandfater->_col = RED;
}
break;
}
}
}
//根變黑
_root->_col = BLACK;
return make_pair(iterator(newnode),true);
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* ppNode = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (ppNode == nullptr)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
subL->_right = parent;
if (ppNode == nullptr)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
void InOrder()
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
bool Check(Node* root, int blackNum, int ref)
{
if (root == nullptr)
{
//cout << blackNum << endl;
if (blackNum != ref)
{
cout << "違反規(guī)則:本條路徑的黑色結(jié)點(diǎn)的數(shù)量根最左路徑不相等" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "違反規(guī)則:出現(xiàn)連續(xù)的紅色結(jié)點(diǎn)" << endl;
return false;
}
if (root->_col == BLACK)
{
++blackNum;
}
return Check(root->_left, blackNum, ref)
&& Check(root->_right, blackNum, ref);
}
bool IsBalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col != BLACK)
{
return false;
}
int ref = 0;
Node* left = _root;
while (left)
{
if (left->_col == BLACK)
{
++ref;
}
left = left->_left;
}
return Check(_root, 0, ref);
}
private:
Node* _root = nullptr;
};到此這篇關(guān)于C++ map與set封裝實(shí)現(xiàn)過程講解的文章就介紹到這了,更多相關(guān)C++ map與set內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實(shí)現(xiàn)數(shù)獨(dú)游戲的求解
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)數(shù)獨(dú)游戲的求解,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
詳解C語言中sizeof如何在自定義函數(shù)中正常工作
在main函數(shù)中,sizeof是可以正常工作的,但是在自定義函數(shù)中就不可以了。所以本文將為大家詳細(xì)講解一下如何解決這一問題,感興趣的可以了解一下2022-05-05
淺談C++ Explicit Constructors(顯式構(gòu)造函數(shù))
下面小編就為大家?guī)硪黄獪\談C++ Explicit Constructors(顯式構(gòu)造函數(shù))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12
基于C語言實(shí)現(xiàn)簡(jiǎn)易三子棋游戲
這篇文章主要為大家詳細(xì)介紹了基于C語言實(shí)現(xiàn)簡(jiǎn)易三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下<BR>2022-01-01

