Set是一种关联容器,它用于存储数据,并且能从一个数据集合中取出数据。它的每个元素的值(key)必须唯一,而且系统会根据该值来自动将数据排序。
下面给出库里set的一些使用方法:
#include<set>
#include<string>
void test_set()
{
set<int> s; //定义一个set对象
//插入
s.insert(1);
s.insert(3);
s.insert(5);
//s.insert(4);
s.insert(8);
s.insert(10);
s.insert(2);
//判空
cout<<"Empty?"<<s.empty()<<endl;
//求size
cout<<"Size?"<<s.size()<<endl;
//最大size
cout<<"max_Size?"<<s.max_size()<<endl;
//删除
//s.erase(1);
//s.erase(2);
//s.erase(3);
//s.erase(4);
cout<<"Empty?"<<s.empty()<<endl;
set<int>::iterator it;
set<int>::iterator it1;
//查找
it = s.find(2);
cout<<*it<<endl;
//找大于等于多少,并且该元素必须存在
it = s.lower_bound (2);
//找小于等于多少,该元素可以不存在
//返回该元素的下一个元素,但不包括下一个元素
it1 = s.upper_bound (4);
s.erase(it,it1);
it = s.begin();
while(it != s.end())
{
cout<<*it<<" ";
++it;
}
cout<<endl;
}
【重点】内部结构采用红黑树的平衡二叉树。
首先,我们给出红黑树的简单实现:
#pragma once
using namespace std;
enum Colour
{
RED,
BLACK,
};
template<class ValueType>
struct RBTreeNode
{
//三叉链
RBTreeNode<ValueType>* _left;
RBTreeNode<ValueType>* _right;
RBTreeNode<ValueType>* _parent;
ValueType _valueField;
Colour _col; //颜色
RBTreeNode(ValueType value)
:_left(NULL)
,_right(NULL)
,_parent(NULL)
,_valueField(value)
,_col(RED)
{}
};
template<class T>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T> Self;
RBTreeIterator(Node* node)
:_node(node)
{}
T& operator*()
{
return _node->_valueField;
}
T* operator->()
{
return &(operator*());
}
Self operator++()
{
if(_node->_right)
{
Node* subLeft = _node->_right;
while(subLeft && subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && parent->_right == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
Self operator--()
{
if(_node->_left)
{
Node* subRight = _node->_left;
while(subRight && subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while(parent && parent->_left == cur)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
bool operator !=(const Self& s)
{
return _node != s._node;
}
bool operator ==(const Self& s)
{
return _node == s._node;
}
Node* _node;
};
template<class K,class T,class KeyOfValue>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T> Iterator;
RBTree()
:_root(NULL)
{}
Iterator Begin()
{
Node* left = _root;
while(left->_left)
{
left = left->_left;
}
return Iterator(left);
}
Iterator End()
{
return NULL;
}
Iterator RBegin()
{
Node* right = _root;
while(right->_right)
{
right = right->_right;
}
return Iterator(right);
}
Iterator REnd()
{
return NULL;
}
pair<Iterator,bool> Insert(const T& kv)
{
if(_root == NULL)
{
_root = new Node(kv);
_root->_col = BLACK;
return make_pair(Iterator(_root),true);
}
Node* parent = NULL;
Node* cur = _root;
while(cur)
{
if( KeyOfValue()(kv) > KeyOfValue()(cur->_valueField))
{
parent = cur;
cur = cur->_right;
}
else if(KeyOfValue()(kv) < KeyOfValue()(cur->_valueField))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(Iterator(cur),false);
}
}
cur = new Node(kv);
Node* newNode = cur;
if(KeyOfValue()(parent->_valueField) > KeyOfValue()(kv))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while(parent && parent->_col == RED)
//如果父亲存在并且父亲的颜色为红色,则代表两个红色节点相连
{
Node* grandfather = parent->_parent;
if(grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
//u存在并且u为红色,就把u和p都置为黑色,
//再把g置为红色,然后继续向上调整
if(uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else//u不存在,或者u存在并且u为黑色
{
if(cur == parent->_right) //双旋
{
RotateL(parent);
swap(parent,cur);
}
RotateR(grandfather); //单旋
parent->_col = BLACK;
grandfather->_col = RED;
break;
}
}
else //grandfather->_right == parent
{
Node* uncle = grandfather->_left;
if(uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
if(cur == parent->_left) //双旋
{
RotateR(parent);
swap(parent,cur);
}
RotateL(grandfather); //单旋
grandfather->_col = RED;
parent->_col = BLACK;
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存在的话
{
subRL->_parent = parent;
}
subR->_left = parent;
Node* parentParent = parent->_parent;
parent->_parent = subR;
if(parentParent == NULL)
{
_root = subR;
_root->_parent = NULL;
}
else
{
if(parentParent->_left == parent)
{
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;
}
subL->_right = parent;
Node* parentParent = parent->_parent;
parent->_parent = subL;
if(parentParent == NULL)
{
_root = subL;
_root->_parent = NULL;
}
else
{
if(parentParent->_left == parent)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
bool IsBalance()
{
if(_root == NULL)
{
return true;
}
if(_root && _root->_col == RED)
{
return false;
}
int blackNum = 0;
Node* left = _root;
while(left)
{
if(left->_col == BLACK)
{
++blackNum;
}
left = left->_left;
}
int num = 0;
return _IsBalance(_root,num,blackNum);
}
bool _IsBalance(Node* root,int num,const int blackNum)
{
if(root == NULL)
{
return true;
}
if(root->_col == RED && root->_parent->_col == RED)
{
cout<<"存在连续的红节点"<<endl;
return false;
}
if(root->_col == BLACK)
{
++num;
}
//num是根节点到当前节点的数量
if(root->_left == NULL && root->_right == NULL)
{
if(num != blackNum)
{
cout<<"黑色节点数量不相等"<<endl;
return false;
}
else
{
return true;
}
}
return _IsBalance(root->_left,num,blackNum)&&
_IsBalance(root->_right,num,blackNum);
}
protected:
Node* _root;
};
在红黑树的基础上我们给出set的简单实现:
#pragma once
#include"RBTree.h"
template<class K>
struct KeyOfValue
{
K operator()(const K& key)
{
return key;
}
};
template<class K,class KeyOfValue = KeyOfValue<K>>
class Set
{
public:
typedef typename RBTree<K,K,KeyOfValue> Tree;
typedef typename RBTreeIterator<K> Iterator;
Iterator Begin()
{
return _t.Begin();
}
Iterator End()
{
return _t.End();
}
pair<Iterator,bool> Insert(const K& key)
{
return _t.Insert(key);
}
protected:
Tree _t;
};
void TestSet()
{
Set<int> s;
s.Insert(2);
s.Insert(1);
s.Insert(3);
s.Insert(4);
Set<int>::Iterator it = s.Begin();
while(it != s.End())
{
cout<<*it<<" ";
++it;
}
cout<<endl;
}
multiset 跟set 类似,唯一的区别是允许键值重复!!!
我们来总结set的特性:
- set以RBTree作为底层容器
- 所存放的元素只有key没有value
- 不允许出现键值重复
- 所有的元素都会被自动排序
- 不能通过迭代器来改变set的值,因为set的值就是键
map里面存的是一些key-value对,其中key起到索引的作用, 而value则表示于索引相关联的数据。
比如字典就是一个很好使用map的例子,把单词当作key,解释当作value。
其实map类型也常称做关联数组,它和一般的数组类似,可以认为它的key就是数组的下标(只不过不必是整数),value则是数组存的值。
下面给出库里map的一些使用方法:
#include<map>
void test_map()
{
map<string,string> m;
m.insert(make_pair("hello","您好"));
m.insert(make_pair("cat","小猫"));
m.insert(make_pair("left","左边"));
m.insert(make_pair("flower","花儿"));
//operator[]没有会插入,有会修改
m["left"] = "剩余";
m["like"] = "喜欢";
//求size
cout<<"Size?"<<m.size()<<endl;
//判空
cout<<"Empty?"<<m.empty()<<endl;
//删除
m.erase("flower");
map<string,string>::iterator it1 = m.begin();
while(it1 != m.end())
{
cout<<it1->first<<":"<<it1->second<<endl;
++it1;
}
cout<<endl;
}
在红黑树的基础上,我们给出map的简单实现:
#pragma once
#include<vector>
class BitMap
{
public:
BitMap(size_t range)
{
_bitMap.resize((range>>3)+1,0);
}
void Set(size_t value)
{
size_t index = value >> 3;
size_t pos = value % 8;
_bitMap[index] |= (1<<pos);
}
void Reset(size_t value)
{
size_t index = value >> 3;
size_t pos = value % 8;
_bitMap[index] &= (~(1<<pos));
}
bool Test(size_t value)
{
size_t index = value >> 3;
size_t pos = value % 8;
return _bitMap[index] & (1<<pos);
}
private:
vector<char> _bitMap;
};
void TestBitMap()
{
BitMap bm(1000);
bm.Set(2);
bm.Set(17);
bm.Reset(2);
cout<<bm.Test(2)<<endl;
cout<<bm.Test(10)<<endl;
cout<<bm.Test(17)<<endl;
}
multimap 跟map 类似,唯一的区别是允许键值重复!!!
我们来总结map的特性:
- map以RBTree作为底层容器
- 所有元素都是键(key)+值(value)
- 不允许键(key)重复
- 所有元素是通过键进行自动排序的
- map的键是不能修改的,但是其键对应的值(value)是可以修改的
今天就总结到这里啦!!!