map&set

来源:互联网 发布:批发衣服软件 编辑:程序博客网 时间:2024/05/17 22:40

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;//求sizecout<<"Size?"<<s.size()<<endl;//最大sizecout<<"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 onceusing 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"] = "喜欢";//求sizecout<<"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)是可以修改的


今天就总结到这里啦!!!吐舌头大笑奋斗











原创粉丝点击