总的来说set和map是关联式容器,而我们前面学习的vector和list的序列式容器。
set和map底层几乎是搜索二叉树,所以他们都可以进行排序和去重,走的是中序遍历
1、set(底层相当于key的搜索树)
具体可以看:https://legacy.cplusplus.com/reference/set/set/?kw=set
a、插入:
b、删除:
注:
2、multiset:
multiset与set的区别是multiset可以有重复的元素。
namespace k
{
template<class k>
//控制节点
struct BSTNode
{
k _key;
BSTNode<k>* _left;
BSTNode<k>* _right;
//构造
BSTNode(const k& key)
:_key(key)
, _left(nullptr)
, _right(nullptr)
{}
};
template<class k>
//控制二叉搜索树
class BST
{
typedef BSTNode<k> Node;
public:
BSTree() = default;
BSTree(const k& t)
{
_root = Copy(t._root);
}
~BSTree()
{
Destroy(_root);
_root = nullptr;
}
//查找函数
bool find(const k& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return true;
}
}
return false;
}
//插入函数
bool insert(const k& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
//删除函数(用改值来做到删除)
//分为(1)叶子和一个孩子(2)两个孩子
bool erase(const k& key)
{
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
//0或1个孩子
//只有右孩子
if (cur->_left == nullptr)
{
//cur为根节点
if (parent == nullptr)
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
parent->_right = cur->_right;
}
delete cur;
return true;
}
//只有左孩子
else if (cur->_right == nullptr)
{
//cur为根节点
if (parent == nullptr)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
parent->_right = cur->_left;
}
delete cur;
return true;
}
//有两个孩子
//找替代节点,右最小或左最大(满足二叉搜索树要求)
//左最大
else
{
Node* leftmax = cur->_left;
Node* leftmaxp = cur;
//左子树的最右边为最大
while (leftmax->_right)
{
leftmaxp = leftmax;
leftmax = leftmax->_right;
}
cur->_key = leftmax->_key;
if (leftmaxp->_left == leftmax)
{
leftmaxp->_left = leftmax->_left;
}
else
leftmaxp->_right = leftmax->_left;
delete leftmax;
return true;
}
//右最小
//else
//{
// Node* rightmin = cur->_right;
// Node* rightminp = cur;
// //右子树的最左边为最小
// while (rightmin->_left)
// {
// rightminp = rightmin;
// rightmin = rightmin->_left;
// }
// cur->_key = rightmin->_key;
// if (rightminp->_left == rightmin)
// {
// rightminp->_left = rightmin->_right;
// }
// else
// rightminp->_right = rightmin->_right;
// delete rightmin;
// return true;
// }
}
}
}
//中序遍历
void Inorder()
{
_Inorder(_root);
cout << endl;
}
private:
//若将该函数放在外边无法访问root
void _Inorder(Node* root)
{
if (root == nullptr)
{
return;
}
_Inorder(root->_left);
cout << root->_key << " ";
_Inorder(root->_right);
}
void Destroy(Node* root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
Node* Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newRoot = new Node(root->_key, root->_value);
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
return newRoot;
}
Node* _root = nullptr;
};
}
3、map(适用于一个值找另一个值)
https://legacy.cplusplus.com/reference/map/map/?kw=map
map可以通过key和value这对键对值实现部分操作。
template<class K, class V>
struct BSTNode
{
// pair<K, V> _kv;
K _key;
V _value;
BSTNode<K, V>* _left;
BSTNode<K, V>* _right;
BSTNode(const K& key, const V& value)
:_key(key)
, _value(value)
, _left(nullptr)
, _right(nullptr)
{}
};
template<class K, class V>
class BSTree
{
typedef BSTNode<K, V> Node;
public:
BSTree() = default;
BSTree(const BSTree<K, V>& t)
{
_root = Copy(t._root);
}
~BSTree()
{
Destroy(_root);
_root = nullptr;
}
bool Insert(const K& key, const V& value)
{
if (_root == nullptr)
{
_root = new Node(key, value);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key, value);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
bool Erase(const K& key)
{
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
// 删除
// 0-1个孩子的情况
if (cur->_left == nullptr)
{
if (parent == nullptr)
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_right;
else
parent->_right = cur->_right;
}
delete cur;
return true;
}
else if (cur->_right == nullptr)
{
if (parent == nullptr)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
parent->_left = cur->_left;
else
parent->_right = cur->_left;
}
delete cur;
return true;
}
else
{
// 2个孩子的情况
// 右子树的最小节点作为替代节点
Node* rightMinP = cur;
Node* rightMin = cur->_right;
while (rightMin->_left)
{
rightMinP = rightMin;
rightMin = rightMin->_left;
}
cur->_key = rightMin->_key;
if (rightMinP->_left == rightMin)
rightMinP->_left = rightMin->_right;
else
rightMinP->_right = rightMin->_right;
delete rightMin;
return true;
}
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << ":" << root->_value << endl;
_InOrder(root->_right);
}
void Destroy(Node* root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
Node* Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newRoot = new Node(root->_key, root->_value);
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
return newRoot;
}
private:
Node* _root = nullptr;
};
map中的operator[]
其底层是用插入函数实现的,而insert函数含有的值有两个,一个是所含的值,另一个是bool类型,若map中没改值则插入成功为true,若有则插入失败为false,其返回值是相关的迭代器。
4、multimap