C++ 模拟实现 map 和 set:掌握核心数据结构

C++ 模拟实现 map 和 set:掌握核心数据结构


文章目录

  • [C++ 模拟实现 map 和 set:掌握核心数据结构](#C++ 模拟实现 map 和 set:掌握核心数据结构)
  • [一、set 和 map 的结构](#一、set 和 map 的结构)
    • [1.1 set的结构](#1.1 set的结构)
    • [1.2 map的结构](#1.2 map的结构)
  • 二、对红黑树的改造
    • [2.1 改造红黑树的节点](#2.1 改造红黑树的节点)
    • [2.2 改造红黑树](#2.2 改造红黑树)
      • [2.2.1 仿函数的使用](#2.2.1 仿函数的使用)
      • [2.2.2 插入函数的改造](#2.2.2 插入函数的改造)
      • [2.2.3 删除函数的改造](#2.2.3 删除函数的改造)
  • 三、对迭代器的改造
    • [3.1 *、->、!=、==](#3.1 *、->、!=、==)
    • [3.2 begin和end](#3.2 begin和end)
    • [3.3 ++ 和 --](#3.3 ++ 和 --)
    • [3.4 const迭代器](#3.4 const迭代器)
    • [3.5 复用红黑树接口实现set/map中的成员函数](#3.5 复用红黑树接口实现set/map中的成员函数)
      • [3.5.1 set成员函数](#3.5.1 set成员函数)
      • [3.5.2 map成员函数](#3.5.2 map成员函数)
  • 四、源代码总结
    • [4.1 Myset.h](#4.1 Myset.h)
    • [4.2 Mymap.h](#4.2 Mymap.h)
    • [4.3 RBTree.h](#4.3 RBTree.h)

一、set 和 map 的结构

STL中set和map底层是一颗红黑树,模拟set和map需要一颗红黑树作为我们的成员变量
点击这里了解红黑树


1.1 set的结构

set结构就是 K模型,所以set容器对红黑树的封装如下:


1.2 map的结构

map结构就是 KV模型,所以map容器对红黑树的封装如下


二、对红黑树的改造


2.1 改造红黑树的节点

其中红黑树的节点类型就是模版参数T


2.2 改造红黑树

2.2.1 仿函数的使用



然后我们将所有需要比较key的函数利用仿函数进行替换,我们以Find为例


2.2.2 插入函数的改造

代码如下(示例):

c 复制代码
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->_value) < kot(data))
        {
            parent = cur;
            cur = cur->_right;
        }
        else if (kot(cur->_value) > kot(data))
        {
            parent = cur;
            cur = cur->_left;
        }
        else
        {
            return make_pair(iterator(cur), false);
        }
    }
    //找到插入位置
    cur = new Node(data);
    Node* newnode = cur;
    if (kot(parent->_value) < 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;
            //情况三:如果叔叔存在且为红
            if (uncle && uncle->_col == RED)
            {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }
            else
            {
                //情况四:叔叔不存在/存在且为黑,且cur在parent的左侧
                if (cur == parent->_left)
                {
                    //     g  
                    //   p   u
                    // c 
                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else//情况五:叔叔不存在 / 存在且为黑,cur在parent的右侧
                {
                    //     g
                    //   p   u
                    //     c
                    RotateLR(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
            {
                //情况四:叔叔不存在/存在且为黑,且cur在parent的左侧
                if (cur == parent->_right)
                {
                    //    g
                    //  u   p
                    //        c
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else // 情况五:叔叔不存在 / 存在且为黑,cur在parent的右侧
                {
                    //    g
                    //  u   p
                    //    c
                    RotateRL(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                //这时该子树的根节点变为黑色,不需要继续调整
                break;
            }
        }

    }
    //防止情况三改到根节点变为红色
    _root->_col = BLACK;
    return make_pair(iterator(newnode), true);
}
 

2.2.3 删除函数的改造

代码如下(示例):

c 复制代码
else //待删除结点的左右子树均不为空
{
    //替换法删除
    //寻找待删除结点右子树当中key值最小的结点作为实际删除结点
    Node* minParent = cur;
    Node* minRight = cur->_right;
    while (minRight->_left)
    {
        minParent = minRight;
        minRight = minRight->_left;
    }
    // 原本直接可以赋值
    // cur->_value = minRight->_value 
    //将待删除结点的键值改为minRight的键值
    Node* newnode = new Node(minRight->_value,cur->_col);
    Node* parent = cur->_parent;
    //重新链接祖父孙三代节点关系
    cur->_left->_parent = newnode;
    cur->_right->_parent = newnode;
    if (parent)
    {
        if (parent->_left == cur)
        {
            parent->_left = newnode;
        }
        else
        {
            parent->_right = newnode;
        }
    }
    else
    {
        //如果是根节点
        _root = newnode;
    }
    newnode->_parent = parent;
    newnode->_left = cur->_left;
    newnode->_right = cur->_right;
    //如果minParent是cur
    if (minParent == cur)
    {
        minParent = newnode;
    }
    delete cur;
    delParent = minParent; //标记实际删除的父节点
    delCur = minRight; //标记实际删除的结点
}

三、对迭代器的改造

3.1 *、->、!=、==

代码如下(示例):

c 复制代码
template<class T, class Ref, class Ptr>
struct __RBTreeIterator
{
    typedef RBNode<T> Node;
    typedef __RBTreeIterator<T, Ref, Ptr> Self;
    Node* _node;
    //构造
    __RBTreeIterator(Node* node)
        :_node(node)
    {}
    Ref operator*()
    {
        return _node->_value;
    }
    Ptr operator->()
    {
        return &_node->_value;
    }
    //判断两个正向迭代器是否不同
    bool operator!=(const Self& s) const
    {
        return _node != s._node;
    }
    //判断两个正向迭代器是否相同
    bool operator==(const Self& s) const
    {
        return _node == s._node;
    }
    Node* getNode()
    {
        return _node;
    }
};

3.2 begin和end

代码如下(示例):

c 复制代码
typedef __RBTreeIterator<T, T&, T*> iterator;//普通迭代器
typedef __RBTreeIterator<T, const T&, const T*> const_iterator;//const迭代器
//最左节点
iterator begin()
{
    Node* cur = _root;
    while (cur && cur->_left)
    {
        cur = cur->_left;
    }
    return iterator(cur);
}
iterator end()
{
    return iterator(nullptr);
}
//const版本begin和end
const_iterator begin()const
{
    Node* cur = _root;
    while (cur && cur->_left)
    {
        cur = cur->_left;
    }
    return const_iterator(cur);
}

const_iterator end()const
{
    return const_iterator(nullptr);
}

3.3 ++ 和 --

代码如下(示例):

c 复制代码
 //前置++
 Self& operator++()
 {
     //如果右子树不为空
     if (_node->_right)
     {
         //寻找该结点右子树当中的最左结点
         Node* left = _node->_right;
         while (left->_left)
         {
             left = left->_left;
         }
         _node = left;
     }
     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->_left) //结点的左子树不为空
     {
         //寻找该结点左子树当中的最右结点
         Node* right = _node->_left;
         while (right->_right)
         {
             right = right->_right;
         }
         _node = right;
     }
     else
     {
         //寻找孩子不在父亲左的祖先
         Node* cur = _node;
         Node* parent = cur->_parent;
         while (parent && cur == parent->_left)
         {
             cur = parent;
             parent = parent->_parent;
         }
         _node = parent;
     }
     return *this;
 }
 

3.4 const迭代器

代码如下(示例):

c 复制代码
//普通迭代器构造const迭代器
__RBTreeIterator(const __RBTreeIterator<T,T&,T*>& it)
    :_node(it._node)
{}

3.5 复用红黑树接口实现set/map中的成员函数

3.5.1 set成员函数

代码如下(示例):

c 复制代码
template<class K>
class set
{
    struct SetKeyOfT
    {
        const K& operator()(const K& key)
        {
            return key;
        }
    };
public:
    //typename声明是一个类型而不是静态变量
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
    typedef typename RBTree<K, K, SetKeyOfT>::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 K& key)
    {
        return _t.Insert(key);
    }
    //删除函数
    void erase(const K& key)
    {
        _t.Erase(key);
    }
    //查找函数
    iterator find(const K& key)
    {
        return _t.Find(key);
    }
private:
    RBTree<K, K, SetKeyOfT> _t;
};

3.5.2 map成员函数

代码如下(示例):

c 复制代码
template<class K, class V>
class map
{
	//仿函数
	struct MapKeyOfT
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};
public:
	//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<K,V>& key)
	{
		return _t.Insert(key);
	}
	//删除函数
	void erase(const K& key)
	{
		_t.Erase(key);
	}
	//查找函数
	iterator find(const K& key)
	{
		return _t.Find(key);
	}
	//[]运算符重载
	V& operator[](const K& key)
	{
		pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
		return ret.first->second;
	}
private:
	RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};


四、源代码总结

4.1 Myset.h

代码如下(示例):

c 复制代码
#pragma once
// Myset.h
#include"RBTree.h"
namespace bit
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		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_iterator begin() const
		{
			return _t.Begin();
		}
		const_iterator end() const
		{
			return _t.End();
		}
		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;
	};
	void Print(const set<int>& s)
	{
		set<int>::const_iterator it = s.end();
		while (it != s.begin())
		{
			--it;
			// 不⽀持修改
			//*it += 2;
			cout << *it << " ";
		}
		cout << endl;
	}
	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);
	}
}

4.2 Mymap.h

代码如下(示例):

c 复制代码
#pragma once
#include"RBTree.h"
namespace bit
{
	template<class K, class V>
	class map
	{
		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);
		}
		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()
	{
		map<string, string> dict;
		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;
	}
}

4.3 RBTree.h

代码如下(示例):

c 复制代码
#pragma once
#include<iostream>
using namespace std;

// 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()
		{
			// --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);
	}
	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;
			// g
			// p u
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					// u存在且为红 -》变⾊再继续往上处理
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					// u存在且为⿊或不存在 -》旋转+变⾊
					if (cur == parent->_left)
					{
						// g
						// p u
						//c
						//单旋
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// g
						// p u
						// c
						//双旋
						RotateL(parent);
						RotateR(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				// g
				// u p
				Node* uncle = grandfather->_left;
				// 叔叔存在且为红,-》变⾊即可
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					// 继续往上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else // 叔叔不存在,或者存在且为⿊
				{
					// 情况⼆:叔叔不存在或者存在且为⿊
					// 旋转+变⾊
					// g
					// u p
					// c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// g
						// u p
						// c
						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;
};