侯捷STL学习笔记(三)--序列容器测试

本文对比了C++标准库中的multiset、multimap、unordered_multiset及unordered_multimap的性能,详细介绍了各容器的特性,如红黑树、哈希表实现原理,以及find()函数的效率测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用容器multiset(允许元素重复)

内部是红黑树,insert操作就保证了排好了序。
标准库有个::find()函数,大家都可以用。容器本身也有一个c.find(),通过键值对查找非常快!

测试

#include <set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj06
{
void test_multiset(long& value)
{
    cout << "\ntest_multiset().......... \n";

multiset<string> c;     
char buf[10];       
clock_t timeStart = clock();                                
    for(long i=0; i< value; ++i)
    {
        try {
            snprintf(buf, 10, "%d", rand());
            c.insert(string(buf));                  
        }
        catch(exception& p) {
            cout << "i=" << i << " " << p.what() << endl;   
            abort();
        }
    }
    cout << "milli-seconds : " << (clock()-timeStart) << endl;  
    cout << "multiset.size()= " << c.size() << endl;    
    cout << "multiset.max_size()= " << c.max_size() << endl;    //214748364

string target = get_a_target_string();  
    {
    timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);  //比 c.find(...) 慢很多 
    cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;     
    if (pItem != c.end())
        cout << "found, " << *pItem << endl;
    else
        cout << "not found! " << endl;  
    }

    {
    timeStart = clock();        
auto pItem = c.find(target);        //比 std::find(...) 快很多                          
    cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;         
    if (pItem != c.end())
        cout << "found, " << *pItem << endl;
    else
        cout << "not found! " << endl;  
    }   

    c.clear();
    //test_moveable(multiset<MyString>(),multiset<MyStrNoMove>(), value);                         
}                                                            
}

这里写图片描述

1)使用容器multimap(允许元素重复)
2)内部是红黑树,key-value键值对。
3)multiset不可用[]做insertion
4)c.insert(pair<long,string>(i,buff))
(*pItem).second

测试

#include <map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj07
{
void test_multimap(long& value)
{
    cout << "\ntest_multimap().......... \n";

multimap<long, string> c;   
char buf[10];

clock_t timeStart = clock();                                
    for(long i=0; i< value; ++i)
    {
        try {
            snprintf(buf, 10, "%d", rand());
            //multimap 不可使用 [] 做 insertion 
            c.insert(pair<long,string>(i,buf));                         
        }
        catch(exception& p) {
            cout << "i=" << i << " " << p.what() << endl;   
            abort();
        }
    }
    cout << "milli-seconds : " << (clock()-timeStart) << endl;  
    cout << "multimap.size()= " << c.size() << endl;
    cout << "multimap.max_size()= " << c.max_size() << endl;    //178956970 

long target = get_a_target_long();      
    timeStart = clock();        
auto pItem = c.find(target);                                
    cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;     
    if (pItem != c.end())
        cout << "found, value=" << (*pItem).second << endl;
    else
        cout << "not found! " << endl;    

    c.clear();                          
}                                                            
}

这里写图片描述

使用unordered_multiset容器

使用hashtable使用分离链地址方法实现
gnu C之前的名称hash_multiset
unorder_multiset.bucket_count篮子的个数
load_factor,max_load_factor,max_bucket_count方法
篮子后面的链表不能太长,元素的个数大于等于篮子的个数,就需要重新分配篮子的大小,重新进行插入元素
c.find()容器自身的find操作快很多
#include <unordered_set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>  //snprintf()
#include <iostream>
#include <ctime> 
namespace jj08
{
void test_unordered_multiset(long& value)
{
    cout << "\ntest_unordered_multiset().......... \n";

unordered_multiset<string> c;   
char buf[10];

clock_t timeStart = clock();                                
    for(long i=0; i< value; ++i)
    {
        try {
            snprintf(buf, 10, "%d", rand());
            c.insert(string(buf));                      
        }
        catch(exception& p) {
            cout << "i=" << i << " " << p.what() << endl;   
            abort();
        }
    }
    cout << "milli-seconds : " << (clock()-timeStart) << endl;      
    cout << "unordered_multiset.size()= " << c.size() << endl;
    cout << "unordered_multiset.max_size()= " << c.max_size() << endl;  //357913941
    cout << "unordered_multiset.bucket_count()= " << c.bucket_count() << endl;  
    cout << "unordered_multiset.load_factor()= " << c.load_factor() << endl;    
    cout << "unordered_multiset.max_load_factor()= " << c.max_load_factor() << endl;    
    cout << "unordered_multiset.max_bucket_count()= " << c.max_bucket_count() << endl;              
    for (unsigned i=0; i< 20; ++i) {
        cout << "bucket #" << i << " has " << c.bucket_size(i) << " elements.\n";
    }                   

string target = get_a_target_string();  
    {
    timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);  //比 c.find(...) 慢很多 
    cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl; 
    if (pItem != c.end())
        cout << "found, " << *pItem << endl;
    else
        cout << "not found! " << endl;  
    }

    {
    timeStart = clock();        
auto pItem = c.find(target);        //比 std::find(...) 快很多                          
    cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;     
    if (pItem != c.end())
        cout << "found, " << *pItem << endl;
    else
        cout << "not found! " << endl;  
    }       

    c.clear();
    test_moveable(unordered_multiset<MyString>(),unordered_multiset<MyStrNoMove>(), value);                                     
}                                                    
}
test_unordered_multiset()..........
    milli-seconds : 2209
    unordered_multiset.size()= 100000
    unordered_multiset.max_size()= 119304647
    unordered_multiset.bucket_count()= 131072
    unordered_multiset.load_factor()= 0.762939
    unordered_multiset.max_load_factor()= 1
    unordered_multiset.max_bucket_count()= 131072
    bucket #0 has 0 elements.
    bucket #1 has 0 elements.
    bucket #2 has 0 elements.
    bucket #3 has 0 elements.
    bucket #4 has 4 elements.
    target(0~32767)
    1111
    std::find(), milli-seconds : 29
    found, 1111
    c.find(), milli-seconds : 0
    found, 1111
    请按任意键继续. . .

测试结果

这个好理解。无序容器的内部是由一个个的bucket(桶)构成的,
每个bucket里面由相同hash的元素构成。
 因此无序容器的搜索是先根据hash值,定位到bucket,然后再在bucket里面搜索符合条件的元素。
buck_count - 就是无序容器内部bucket的数量;
size - 无序容器中总的元素数量;
max_load_factor - 就是bucket所容纳的最大平均元素的数量(可以是分数值)。
『例如』:如果一个容器中有100个元素,容器中bucket的最大平均元素值是12.5,那么需要多少个桶才能完全装下这100个元素呢? 100/12.5 = 8, 为确保有足够的桶,bucket数量起码是>8(即最少9个)。

使用unordered_multimap容器

    #include <unordered_map>
    #include <stdexcept>
    #include <string>
    #include <cstdlib> //abort()
    #include <cstdio>  //snprintf()
    #include <iostream>
    #include <ctime> 
    namespace jj09
    {
    void test_unordered_multimap(long& value)
    {
        cout << "\ntest_unordered_multimap().......... \n";

    unordered_multimap<long, string> c;     
    char buf[10];

    clock_t timeStart = clock();                                
        for(long i=0; i< value; ++i)
        {
            try {
                snprintf(buf, 10, "%d", rand());
                //multimap 不可使用 [] 進行 insertion 
                c.insert(pair<long,string>(i,buf));
            }
            catch(exception& p) {
                cout << "i=" << i << " " << p.what() << endl;   
                abort();
            }
        }
        cout << "milli-seconds : " << (clock()-timeStart) << endl;      
        cout << "unordered_multimap.size()= " << c.size() << endl;  
        cout << "unordered_multimap.max_size()= " << c.max_size() << endl;  //357913941 

    long target = get_a_target_long();      
        timeStart = clock();        
    auto pItem = c.find(target);                                
        cout << "c.find(), milli-seconds : " << (clock()-timeStart) << endl;         
        if (pItem != c.end())
            cout << "found, value=" << (*pItem).second << endl;
        else
            cout << "not found! " << endl;      
    }                                                            
    }

测试结果

test_unordered_multimap()..........
    milli-seconds : 1995
    unordered_multimap.size()= 100000
    unordered_multimap.max_size()= 107374182
    target(0~32767)
    11111
    c.find(), milli-seconds : 0
    found, value=22712

后面一篇对set,map进行介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值