【C++】set和map

目录

一、set、map的介绍

1、set的介绍

2、map的介绍

二、红黑树的实现

1、具体框架

2、迭代器

三、set、map的实现

1、具体结构

2、仿函数

3、insert

4、迭代器

5、operator[ ]

四、完整代码


一、set、map的介绍

1、set的介绍

1. set是按照一定次序存储元素的容器
2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
子集进行直接迭代。
5. set在底层是用红黑树实现的。

set主要是用来查看元素是否在某一集合中,并且它默认在set中是升序的,且不含有重复元素

set是一个关联式容器,是K的模型,它不允许有键值冗余的情况发生

set模板具有三个参数,第一个是元素类型,第二个参数是一个仿函数,默认的缺省值是less,排的是升序

并且它的拷贝和赋值都是深拷贝,代价极大,拷贝的是整棵树

 

find是set常用的接口,插入元素之后需要查找是否存在,如果能够找到返回对应位置的迭代器,如果没有找到,返回的是end

set的遍历特征是有序+去重

#include <iostream>
#include <set>

using namespace std;

void test_set1()
{
    int a[] = {1, 2, 1, 6, 3, 8, 5};
    set<int> s(a, a + sizeof(a) / sizeof(int));
    for(const auto& e : s)
    {
        cout << e << endl;
    }
}

int main()
{
    test_set1();
    return 0;
}

 

 

接下来就是set的删除了

void test_set1()
{
    int a[] = {1, 2, 1, 6, 3, 8, 5};
    set<int> s(a, a + sizeof(a) / sizeof(int));
    for(const auto& e : s)
    {
        cout << e << " ";
    }
    s.erase(30);
    for(const auto& e : s)
    {
        cout << e << " ";
    }

    set<int>::iterator pos = s.find(20);
    s.erase(pos);
    for(const auto& e : s)
    {
        cout << e << " ";
    }
}

 我们发现上面我写了两种删除,那么这两种删除方式有什么区别吗?

我们先编译运行一下,我们先屏蔽掉下面删除20的代码

发现是没有任何问题的,我们寻找30,set中没有30它也不会报错,也不会删除

接下来我们使用下面的删除逻辑

 

然后我们发现他就崩了原因是:我们查找20,find没有找到它会返回end,然后我们删除end时,end指向的是最后一个元素的下一个位置,我们把它删除了,程序就会崩溃

这就是两种删除方式的区别。

正确做法

 


    set<int>::iterator pos = s.find(20);
    if(pos != s.end())
    {
        s.erase(pos);
    }
    for(const auto& e : s)
    {
        cout << e << " ";
    }

 

 

接下来是count这个函数,它会返回某元素的个数,对于set来说是没有用的,set内部相同元素个数就是1,没有就是0

 这个接口是为了保持接口一致性,主要是给multiset来使用的

multiset和set用法类似,不过就是允许键值冗余的现象存在

void test_multiset()
{
    int a[] = {1, 2, 1, 6, 3, 8, 5};
    multiset<int> ms(a, a + sizeof(a) / sizeof(int));
    for(const auto& e : ms)
    {
        cout << e << " ";
    }
    cout << endl;

    cout << ms.count(1) << endl;
}

 

这时我们再调用count,1的个数就变成了2

2、map的介绍

map与set也十分的相似,map是K/V的模型,set是K的模型

map也有两种

区别与set和multiset相同,只是键值是否允许冗余的差别

不过map的插入就比较特别了

 

我们发现insert的参数是一个value_type类型

 

然后我们发现它实际上是一个pair

template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};

 pair又叫做键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

也就是说我们每次插入时传入一个键值对

map<string, string> countMap;

countMap.insert(pair<string, string>("苹果", "apple"));

这样显得十分的麻烦,这时我们还可以借助其它函数来帮助我们自动生成pair,就不用我们每次手动传一个pair的匿名对象了

countMap.insert(make_pair("香蕉", "banana"));

同时我们还发现一个奇怪的点map的insert的返回值也是一个pair,那么这个pair中存的是什么呢?

 

通过前面的英文文档我们大概了解了返回值的含义

如果这个元素已经存在了,我们就返回该元素位置的迭代器,也就是pair的第一个参数,pair的第二个 参数就置为flase代表插入失败

如果这个元素不存在,就返回新插入元素的迭代器,返回true

insert的返回值实际上是为了[ ]操作符重载所设计的

map的operator[ ]与我们前面见到的[ ] 都不太一样

[ ]内传入的是V,返回的是K的引用

如果该元素不存在,就插入这个元素,并且调用V的默认构造

void test_map()
{
    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", 
"苹果", "香蕉", "苹果", "香蕉" };
    map<string, int> countMap;
    for(const auto& e : arr)
    {
        countMap[e]++;
    }
    for(const auto& e : countMap)
    {
        cout << e.first << " : " << e.second << endl;
    }
}

 

这与我们的预期一致,最开始的时候map中什么元素都没有,正常调用[ ]一定会崩,他没有崩并且还将其插入了。

总结:

1、map中有这个key,返回value的引用 (查找,修改value)

2、map中没有这个key,会插入一个pair(key, V()),返回value的引用  (插入+修改) 

二、红黑树的实现

1、具体框架

红黑树基本代码:

#pragma once
#include <iostream>
#include <utility>
#include <cassert>
#include <ctime>

using namespace std;

enum Colour
{
	RED,
	BLACK
};

template<class K,class V>
struct RBTreeNode
{
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;
	pair<const K, V> _kv;
	Colour _col;

	RBTreeNode(const pair<const K,V>& kv)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_kv(kv)
	{}
};

template<class K,class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	bool insert(const pair<const K, V> kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;
		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;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;

		//�����ڵ���ɫ
		//�ߵ��ջ��߸��׵���ɫ�Ǻ�ɫ����ֹͣ����
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			assert(grandfather);
			assert(grandfather->_col == BLACK);

			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
				{
					/*    g
					*   p
					* c
					*/
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   p    u
					*     c
					*/
					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
				{
					/*    g
					*         p
					*            c
					*/
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   u    p
					*      c
					*/
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}

	void InOrder()
	{
		_InOrder(_root);
	}

	bool IsBalance()
	{
		int benchmark = 0;
		return _PrevCheck(_root, 0, benchmark);
	}

private:

	bool _PrevCheck(Node* root, int blackNum, int& benchmark)
	{
		if (root == nullptr)
		{
			if (benchmark == 0)
			{
				benchmark = blackNum;
				return true;
			}

			if (blackNum != benchmark)
			{
				cout << "��ɫ�ڵ�����ͬ" << endl;
				return false;
			}
			else
			{
				return true;
			}
		}
		if (root->_col == BLACK)
		{
			blackNum++;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << "�������ĺ�ɫ�ڵ�" << endl;
			return false;
		}

		return _PrevCheck(root->_left, blackNum, benchmark)
			&& _PrevCheck(root->_right, blackNum, benchmark);
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_kv.first << " : " << root->_kv.second << endl;
		_InOrder(root->_right);
	}

	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 (_root == parent)
		{
			_root = subR;
			subR->_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->_right = parent;
		parent->_parent = subL;
		if (_root == parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
			subL->_parent = ppNode;
		}
	}

	Node* _root = nullptr;
};

void testRBTree()
{
	int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	RBTree<int, int> rb;
	/*for (const auto& it : a)
	{
		rb.insert(make_pair(it, it));
	}*/
	//rb.InOrder();
	const size_t N = 100000;
	srand(time(0));
	for (size_t i = 0; i < N; i++)
	{
		int x = rand();
		cout << x << endl;
		rb.insert(make_pair(x, x));
	}

	cout << rb.IsBalance() << endl;
}

我们前面已经实现了红黑树的基本功能,接下来就是我们将红黑树封装一下,让它能够既能是K模型也可以是K/V模型,并且给它加上迭代器


使两种模型都能够存在,我们就要将上述的红黑树的节点存储一个模板T

T可以是K也可以是pair,这就解决了一部分问题,接下来的问题就是我们要插入节点,一定会需要进行比较,我们无法区分pair和K,虽然pair库中已经帮我们实现了<和>但是,这种实现方式并不是我们想要的

 

我们的map是只比较pair的第一个元素,库中实现的无法满足我们的需求,我们只好借助与仿函数来实现,我们使用仿函数来获取pair的第一个元素,仿函数的具体实现我们并不关系

template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _data;
	Colour _col;

	RBTreeNode(const T& data)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_data(data)
	{}
};

树的节点内容已经变更为data

2、迭代器

红黑树的迭代器比较像我们的list的迭代器,它们同样不是连续的物理地址空间

template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
	typedef RBTreeNode<T> Node;
	typedef __RBTree_iterator<T, Ref, Ptr> self;

	Node* _node;
};

我们还是写一个结构体,重载它的操作符

对于迭代器来说解引用一定会返回这个节点的值,对于K模型来说就是K,对于K/V模型来说就是pair    ->操作符同样道理,只有指针才会有->操作,所以我们要返回的是节点的地址

	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;
	}

接下来就是++和--  我们先来看++

假如我们的迭代器现在指向8,按照中序遍历的规则,它的下一个元素就是10,它是8的右子树的最左节点

而如果我们的迭代器指向7呢?

就需要我们去寻找祖先里面孩子不是祖先的右的那个

	self& operator++()
	{
		if(_node->_right)
		{
			Node* cur = _node-> _right;
			while(cur->_left)
			{
				cur = cur->_left;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while(parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

对于--就完全跟++相反

	self& operator--()
	{
		if(_node->_left)
		{
			Node* cur = _node-> _left;
			while(cur->_right)
			{
				cur = cur->_right;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while(parent && cur == parent->_left)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

红黑树迭代器实现


template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
	typedef RBTreeNode<T> Node;
	typedef __RBTree_iterator<T, Ref, Ptr> self;

	Node* _node;
	__RBTree_iterator(Node* node)
		:_node(node)
	{}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->() 
	{
		return &_node->_data;
	}

	self& operator++()
	{
		if(_node->_right)
		{
			Node* cur = _node-> _right;
			while(cur->_left)
			{
				cur = cur->_left;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while(parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

	self& operator--()
	{
		if(_node->_left)
		{
			Node* cur = _node-> _left;
			while(cur->_right)
			{
				cur = cur->_right;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			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;
	}

};

接下来回到红黑树的整体框架

红黑树的begin一定是返回中序遍历的第一个节点,也就是我们的最左节点(如果最左节点存在) 

红黑树的end是中序遍历的最后一个节点的下一个节点,也就是nullptr

	typedef __RBTree_iterator<T, T&, T*> iterator;
	typedef __RBTree_iterator<T, const T&, const T*> const_iterator;

	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}
		return iterator(left);
	}

	const_iterator begin() const
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return iterator(left);
	}

	iterator end()
	{
		return iterator(nullptr);
	}

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

最后就剩下insert的修改了

insert就是将返回值修改为pair,再根据不同的情况返回不同的值

如果已经存在这个值了,再插入就返回该元素迭代器和false组成的pair

没有这个值,就插入再返回该元素迭代器和true组成的pair

	pair<iterator, bool> insert(const T& data)
	{
		KeyOfT k2t;
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (k2t(cur->_data) < k2t(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (k2t(cur->_data) > k2t(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}
		cur = new Node(data);
		Node* newNode = cur;
		cur->_col = RED;
		if (k2t(parent->_data) < k2t(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			assert(grandfather);
			assert(grandfather->_col == BLACK);

			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
				{
					/*    g
					*   p
					* c
					*/
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   p    u
					*     c
					*/
					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
				{
					/*    g
					*         p
					*            c
					*/
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   u    p
					*      c
					*/
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
				}
			}
		}
		_root->_col = BLACK;
		return make_pair(iterator(newNode), true);
	}

三、set、map的实现

set和map的底层都是红黑树,我们只要将红黑树稍微修改就可以实现set和map了

但是这里有一个问题,set是K的模型map是K/V的模型,它是两棵树,难道我们要写两棵红黑树,一个是K的模型,一个是K/V的模型吗?

其实并不需要,我们查看一下stl源码的实现

我们发现它的红黑树的参数T,set传的是K,map传的是一个pair这样就完美的解决了到底是K的模型还是K/V的模型的问题了。不过在我们find和insert的时候又会有其他的问题了,我们查找时,因为是红黑树,所以我们需要节点存的值进行比较,可是对于set来说还好直接比较K

但是map的T是一个pair,虽然pair库中已经帮我们实

 

1、具体结构

对于set和map而言,我们只需要封装红黑树的迭代器和insert就好了,set和map内部其实什么都没有,就好像栈和队列一样

#include "RBTree.hpp"

template<class K>
class set
{
    
public:

private:
    RBTree<K, K, K2T> _t;
};


template<class K, class V>
class map
{

public:

private:
    RBTree<K, pair<K, V>, K2T> _m; 
};

这就是最简单的

2、仿函数

根据是map还是set设计出的仿函数是不同的,不过都是返回K

//set仿函数

struct K2T
    {
        const K& operator()(const K& key)
        {
            return key;
        }
    };

//map仿函数

struct K2T
    {
        const K& operator()(const pair<K, V>& kv)
        {
            return kv.first;
        }
    };

3、insert

insert其实特别的简单,我们只需要调用红黑树的insert就可以了

//set
    pair<iterator, bool> insert(const K& key)
    {
        _t.insert(key);
    }


   
//map
 pair<iterator, bool> insert(const pair<K, V>& kv)
    {
        return _m.insert(kv);
    }



    

4、迭代器

同理调用红黑树的

   iterator begin()
    {
        return _t.begin();
    }

    const_iterator begin() const
    {
        return _t.begin();
    }

    iterator end()
    {
        return _t.end();
    }

    const_iterator end() const
    {
        return _t.end();
    }

5、operator[ ]

这个是map独有的,我们前面已经介绍了原理,所以我们直接拿出代码

   V& operator[](const K& key)
    {
        pair<iterator, bool> ret = insert(make_pair(key, V()));
        return ret.first->second;
    }

四、完整代码

//RBTree.hpp
#pragma once
#include <iostream>
#include <utility>
#include <cassert>
#include <ctime>

using namespace std;

enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _data;
	Colour _col;

	RBTreeNode(const T& data)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_data(data)
	{}
};

template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
	typedef RBTreeNode<T> Node;
	typedef __RBTree_iterator<T, Ref, Ptr> self;

	Node* _node;
	__RBTree_iterator(Node* node)
		:_node(node)
	{}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->() 
	{
		return &_node->_data;
	}

	self& operator++()
	{
		if(_node->_right)
		{
			Node* cur = _node-> _right;
			while(cur->_left)
			{
				cur = cur->_left;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			while(parent && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

	self& operator--()
	{
		if(_node->_left)
		{
			Node* cur = _node-> _left;
			while(cur->_right)
			{
				cur = cur->_right;
			}
			_node = cur;
		}
		else
		{
			Node* parent = _node->_parent;
			Node* cur = _node;
			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 __RBTree_iterator<T, T&, T*> iterator;
	typedef __RBTree_iterator<T, const T&, const T*> const_iterator;

	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}
		return iterator(left);
	}

	const_iterator begin() const
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return iterator(left);
	}

	iterator end()
	{
		return iterator(nullptr);
	}

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

	pair<iterator, bool> insert(const T& data)
	{
		KeyOfT k2t;
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (k2t(cur->_data) < k2t(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (k2t(cur->_data) > k2t(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}
		cur = new Node(data);
		Node* newNode = cur;
		cur->_col = RED;
		if (k2t(parent->_data) < k2t(data))
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
		cur->_parent = parent;

		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			assert(grandfather);
			assert(grandfather->_col == BLACK);

			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
				{
					/*    g
					*   p
					* c
					*/
					if (cur == parent->_left)
					{
						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   p    u
					*     c
					*/
					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
				{
					/*    g
					*         p
					*            c
					*/
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					/*    g
					*   u    p
					*      c
					*/
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
				}
			}
		}
		_root->_col = BLACK;
		return make_pair(iterator(newNode), true);
	}

private:

	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 (_root == parent)
		{
			_root = subR;
			subR->_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;
		subL->_right = parent;
		parent->_parent = subL;
		if (_root == parent)
		{
			_root = subL;
			subL->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
			subL->_parent = ppNode;
		}
	}

	Node* _root = nullptr;
};

//set.hpp
#pragma once
#include "RBTree.hpp"

template<class K>
class set
{
    struct K2T
    {
        const K& operator()(const K& key)
        {
            return key;
        }
    };
public:
    typedef typename RBTree<K, K, K2T>::iterator iterator;
    typedef typename RBTree<K, K, K2T>::const_iterator const_iterator;

    iterator begin()
    {
        return _t.begin();
    }

    const_iterator begin() const
    {
        return _t.begin();
    }

    iterator end()
    {
        return _t.end();
    }

    const_iterator end() const
    {
        return _t.end();
    }

    pair<iterator, bool> insert(const K& key)
    {
        _t.insert(key);
    }
private:
    RBTree<K, K, K2T> _t;
};


void test_set()
{
    set<int> s;
    s.insert(23);
    s.insert(34);
    s.insert(23);
    s.insert(67);
    s.insert(235);
    s.insert(12);
    s.insert(45);
    s.insert(98);
    s.insert(245);
    s.insert(2333);
    s.insert(123);
    set<int>::iterator it = s.begin();
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
   
    cout << endl;
}

//map.hpp
#pragma once
#include "RBTree.hpp"

template<class K, class V>
class map
{
    struct K2T
    {
        const K& operator()(const pair<K, V>& kv)
        {
            return kv.first;
        }
    };
public:
    typedef typename RBTree<K, pair<K, V>, K2T>::iterator iterator;
    typedef typename RBTree<K, pair<K, V>, K2T>::const_iterator const_iterator;

    iterator begin()
    {
        return _m.begin();
    }

    const_iterator begin() const
    {
        return _m.begin();
    }

    iterator end()
    {
        return _m.end();
    }

    const_iterator end() const
    {
        return _m.end();
    }

    pair<iterator, bool> insert(const pair<K, V>& kv)
    {
        return _m.insert(kv);
    }

    V& operator[](const K& key)
    {
        pair<iterator, bool> ret = insert(make_pair(key, V()));
        return ret.first->second;
    }

private:
    RBTree<K, pair<K, V>, K2T> _m; 
};

void test_map()
{
    string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };

	map<string, int> countMap;
	for (auto& str : arr)
	{
		countMap[str]++;
	}
	map<string, int>::iterator it = countMap.begin();
	while (it != countMap.end())
	{
		cout << it->first << ":" << it->second << endl;
		++it;
	}
    cout << endl;
	for (auto& kv : countMap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值