相信大家都对map,set不会陌生,这是非常好用的容器,它的底层是红黑树,红黑树在数据结构中,个人感觉是比较难的一种数据结构,尤其是一会染色,一会旋转的,弄来弄去把人给弄晕了。而我想说的是,红黑树不仅实现难,封装起来也不简单,下面是封装的代码:
#pragma once
#include
#include
#pragma once
#include "rbtree.h"
namespace cc
{
//可以写成内部类
template
struct setfunc
{
const K& operator()(const K& key)
{
return key;
}
};
template
class set
{
public:
typedef RB::RbTreeNode node;
typedef RB::Iterator iterator;
pair insert(const K& x)
{
return Rbtree.insert(x);
}
iterator find(const K& key)
{
return Rbtree.find(key);
}
iterator begin()
{
return Rbtree.begin();
}
iterator end()
{
return Rbtree.end();
}
private:
RB::RbTree> Rbtree;
};
}
#pragma once
#include "rbtree.h"
namespace cc
{
//可以写成内部类
template
struct mapfunc
{
const K& operator()(const pair& key)
{
return key.first;
}
};
template
class map
{
public:
typedef RB::RbTreeNode> node;
typedef RB::Iterator, pair&, pair*> iterator;
pair insert(const pair& x)
{
return Rbtree.insert(x);
}
iterator find(const K& key)
{
return Rbtree.find(key);
}
iterator begin()
{
return Rbtree.begin();
}
iterator end()
{
return Rbtree.end();
}
V& operator[](const K& x)
{
return Rbtree.insert(make_pair(x, V())).first->second;
}
private:
RB::RbTree, mapfunc> Rbtree;
};
}
#include"rbtree.h"
#include "map.hpp"
#include "set.h"
void test1()
{
//RB::RbTree rb;
//srand(time(0));
//for (size_t i = 0; i < 100; i++)
// rb.insert(rand());
///*rb.insert(1);
//rb.insert(2);
//rb.insert(3);
//rb.insert(4);
//rb.insert(5);
//rb.insert(6);
//rb.insert(7);
//rb.insert(8);
//rb.insert(9);
//rb.insert(10);*/
//rb.prin();
}
void test2()
{
/*cc::map m;
m.insert(make_pair(1, 1));
m.insert(make_pair(2, 1));
m.insert(make_pair(3, 1));
m.insert(make_pair(4, 1));
m.insert(make_pair(5, 1));
m.insert(make_pair(6, 1));
m.insert(make_pair(7, 1));
m.insert(make_pair(8, 1));
m.insert(make_pair(9, 1));
m.insert(make_pair(10, 1));
m.insert(make_pair(11, 1));
m.insert(make_pair(12, 1));
m.insert(make_pair(13, 1));
m.insert(make_pair(14, 1));
m.insert(make_pair(15, 1));
m.find(5);
cc::map::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << endl;
++it;
}*/
cc::map m;
///*int arr[] = { 1,1,1,1,1,1,1,1 };
//for (auto e : arr)
// m[e]++;*/
string arr[] = { "苹果","香蕉","梨","苹果","香蕉","香蕉" };
for (auto& e : arr)
m[e]++;
//for (auto& e : m)
//cout << e.first << ":" << e.second << endl;
auto it = m.begin();
for (auto& e : m)
cout << e.first << ":" << e.second << endl;
}
void test3()
{
srand(time(0));
cc::map m;
for (size_t i = 0; i < 1000; i++)
{
static int x = rand() % 1000;
m[x++]++;
}
for (auto& e : m)
cout << e.first << ":" << e.second << endl;
}
void test4()
{
cc::set s;
/*s.insert(1);
s.insert(2);
s.insert(3);
s.insert(5);
s.insert(2);
s.insert(10);
for (auto e : s)
{
cout << e << endl;
}*/
for (size_t i = 0; i < 1000; i++)
{
s.insert(rand());
}
for (auto e : s)
cout << e << endl;
}
int main()
{
//test1();
//test2();
//test3();
test4();
return 0;
}
上面是我的封装过程以及代码实现,其实我昨天封装了unordered_map,unordered_set这两个容器,今天封装map,set就感觉简单不少,但是也不是简单。其他的没啥要注意的地方,唯一一个要注意的就是迭代器,迭代器怎么说,还是要动一会脑子的。
首先就是,判断当前节点的右子树是不是空树,如果不是空树的话,那么代表的这个节点以及这个节点的做左子树已经访问完成,而右子树不为空,所还没有访问完这颗树,所以++之后就要找右子树的最左节点。而难得是如果右子树为空的话,那么就代表已经访问完了这课子树的所有节点,所以找他的父节点,而父节点应该已经是被访问了,所以就向上遍历,直到找到父节点不是祖父节点右孩子的节点为止。
这个思想还是有点绕人的,再就是其他的封装,如果看了我上一篇文章内容的伙伴,封装map,set应该还是很简单的。
希望大家支持一下吧!!谢谢!