STL set、multiset| map multimap

STL Set、Multiset

参考文章: https://blog.csdn.net/weixin_45389639/article/details/121618243

  • ​ set/multiset以rb_tree为底层结构,因此有元素自动排序的功能,排序的依据是key,而set/multiset元素的value和key合一(Value就是Key)。
  • 注意:我们无法使用set/multiset的iterator改变元素值(因为key有其严谨的排列规则)。set/multiset的iterator是其底部rbtree的const-iterator。
  • set的insert()用的是rb_tree的inset_unique()。
  • multiset的insert()用的是rb_tree 的inset_equal()。

set定义

template<class Key,
         class Compare = less<Key>,
         class Alloc = alloc>
class set {
public:
    typedef Key key_type;
    typedef Key value_type;
    typedef Compare key_compare;
    typedef Compare value_compare;
private:
    typedef rb_tree <key_type, 
    				 value_type, 
    				 identity<value_type>, 
    				 key_compare, 
    				 Alloc> rep_type;
    rep_type t;		// 内部rb_tree容器
public:
	//迭代器,set不可以通过迭代器修改元素
    typedef typename rep_type::const_iterator iterator;
};

set中所有操作,使用红黑树做,set这里可以看成一个container adapter

map multimap

map与set区别,set中 key=value
map元素分为key和data,组合起来是value

在这里插入图片描述

Map/multimap以rb_tree为底层结构,因此有元素自动排序的功能,排序的依据是key。

​ 注意:我们无法使用map/multimap的iterator改变元素值(因为key有其严谨的排列规则),但可以用它来该改变元素的data。map/multimap内部自动将user指定的keytype设定为const,以便禁止user对元素的key赋值。

  • ​ map的insert()用的是rb_tree的inset_unique()。
  • multimap的insert()用的是rb_tree 的inset_equal()。
template<class key,Class T,class Compare=less<key>,class Alloc=alloc>
class map{
public:
   typedef key key_type;
   typedef T data_type;
   typedef T mapped_type;
   typedef pair<const key,T> value_type // 这里指定const key防止user修改key
   typedef Compare key_compare;
private:
   typedef rb_tree<key_type,value_type,select1st<value_type>,key_compare,Alloc> rep_type
   rep_type t;	//rb_tree
public:
    typedef typename rep_type::iterator iterator;
}

template<class Pair>
struct select1st:public unary_function<Pair,typename Pair::first_type>
{
    const typename Pair::first_type& operator()(const Pair& x){
        return x.first;
    }
}

map中特别的符号重载operator[]

operator[](const key_type& _k)

如果k存在,返回该iterator,不存在就在合适的位置创造该k

mapped_type& operator[](const key_type& _k){
    iterator _i = lower_bound(_k);
 	if(_i=end()||key_comp()(_k,(*_i).first))
        _i = insert(_i,value_type(_k,mapped_type()));
    return(*_i).second;
}

hashtable

当元素个数大于buckets时,进行rehashing。成长倍数(在GNUC下)为两倍,成长完成后所有元素重新排列,实现元素的散列分布。
GUNC选择质数作为篮子大小, 每次两倍扩充,使用扩充后附近的质数作为篮子大小
在这里插入图片描述

hashtable代码

//HashFcn 确定Hashtable中元素编号的方法,通常为函数对象(将存入对象转为编号)
//Extractkey 如果元素是一对pair,需要告诉提取key的方法
//Equalkey 比较key大小的方法
template<class value,
		class key,
		class HashFcn,
		class Extrackey,
		class EqualKey,
		class Alloc=alloc>
class hashtable{
public:
    typedef HashFnc hasher;
    typedef EqualKey key_equal;
    typedef size_t size_type;

private:
    hasher hash;
    key_equal equals;
    Extrackey get_key;

    typedef _hashtable_node<value> node;
    
    vector<node*,Alloc> buckets;
    size_type num_elements;
    
public:
    size_type bucket_count()const{return buckets.size();}
 ...
}

template<class value>
struct _hashtable_node{
	_hashtable_node* next;
    value val;
...
}

template<class value,class key,class HashFcn,class Extrackey,class EqualKey,class Alloc=alloc>
struct _hashtable_iterator{
	...
    node* cur;
    hashtable* ht;
}
                        
void hashtableTest(){
	hashtable<const char*,
              const char*,
    		  hash<const char*>,
    		  identity<const char*>,
    		  eqstr> 
    ht(50,hash<const char*>(),eqstr());
    ht.insert_unique("zsas");
	ht.insert_unique("asdfs");
}

struct eqstr{
    bool operator()(const char*s1,const char*s2)const{
        return strcmp(s1,s2)==0;
    }
}

怎样使用hashfunction

hashfun源码:

template<class key>struct hash{};

_STL_TEMPLATE_NULL struct hash<char>{size_t operator()(const char x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<short>{size_t operator()(const short x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<unsigned short>{size_t operator()(const unsigned short x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<int>{size_t operator()(const int x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<unsigned int>{size_t operator()(const unsigned int x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<long>{size_t operator()(const long x)const (return x;)};
_STL_TEMPLATE_NULL struct hash<unsigned long>{size_t operator()(const unsigned long x)const (return x;)};

_STL_TEMPLATE_NULL struct hash<char*>{size_t operator()(const char* s)const (return _stl_hash_string(s);)};
_STL_TEMPLATE_NULL struct hash<const char*>{size_t operator()(const char* s)const (return _stl_hash_string(s);)};

inline size_t _stl_hash_string(const char* s){
    unsigned long h=0;
    for(;*s;++s){
        h=5*h+*s;
    }
    return size_t(h);
}
//注意stl中没有提供string类型的hashfunc模板特化版本,需要自己提供
                        

Unordered容器使用

C++11引入的容器unordered_set、unordered_multiset、unordered_map和unordered_multimap更名自GCC2.9的下 容器hash_set、hash_multiset、hash_map和hash_multimap,其底层封装了hashtable.用法与set、multiset、map和multimap类似。

void UnorderedSetCompare() {
    unordered_multiset<string>s;
    char buf[10];
    for (long i = 0; i < INPUTSIZE; i++) {
        try
        {
            snprintf(buf, 10, "%d", rand());
            s.insert(string(buf));
        }
        catch (const std::exception& p)
        {
            cout << "i= " << i << " " << p.what() << endl;
            abort();
        }
    }
    cout << "milli-seconds: " << clock() << endl;
    cout << "s.size(): " << s.size() << endl;
    cout << "s.Max_Size(): " << s.max_size() << endl;
    cout << "s.bucket_count():" << s.bucket_count() << endl;
    cout << "unordered_multiset.load_factor()= " << s.load_factor() << endl;
    cout << "unordered_multiset.max_load_factor()= " << s.max_load_factor() << endl;
    cout << "unordered_multiset.max_bucket_count()= " << s.max_bucket_count() << endl;

    for (unsigned i = 0; i < 20; i++) {
        cout << "bucket #" << i << " has " << s.bucket_size(i) << " elemt " << endl;
    }
    string target = get_a_string_target();
    Clock_Time start_time = clock();

    auto ite = ::find(s.begin(), s.end(), target);

    cout << "::find(),milli-seconds: " << (clock() - start_time) << endl;
    if (ite != s.end()) {
        cout << "Find Value!" << endl;
    }
    else {
        cout << "Not Find Value" << endl;
    }

    start_time = clock();

    ite = s.find(target);	//比全局::sort函数快很多

    cout << "s.find(),milli-seconds: " << (clock() - start_time) << endl;
    if (ite != s.end()) {
        cout << "Find Value!" << endl;
    }
    else {
        cout << "Not Find Value" << endl;
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值