c++之容器(boolan)

来源:互联网 发布:防止电脑安装软件 编辑:程序博客网 时间:2024/05/29 07:38
  •    简述: C++标准库中的代码几乎都是使用泛型编程(GP),而所谓的泛型编程:就是使用tmeplate为主要工具来编写程序。

  C++标准库( C++ standard library )
  对于STL标准模板库而言,standard template library标准库以hearderfile形式呈现,所以可以看到其内容。对于C++标准库:


  1).C++变准哭的hearder files 不带副档名(.h),例如#include


  2) .新式C hearder files 不带副档名(.h),例如#include


  3) .旧式 C hearder files(带有副档名 .h )任然可用,例如:#include

#include<iostream>#include<vector>#include<functional>#include<algorithm>#include<iterator>using namespace std;int main(){int ai[] = { 1, 23, 43, 13, 56, 75, 66, 98, 14,23,23 };vector<int, allocator<int>>vi(ai, ai + 11);cout << count_if(vi.begin(),vi.end(),bind2nd(less<int>(),40)) << endl;//小于40的个数cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40))) << endl;//大于等于40的元素个数return 0;}

  上面的一小段程序包括了所说的六大部件:


  使用了容器 vector,然后通过分配器allocator来给容器vector分配内存,而count_if()是算法表示如果满足条件则计数,vi.begin()和vi.end()则使用了迭代器,not1为函数适配器(function adaptor),bind2nh表示绑定第二参数(也是函数适配器的一种),最后的less()则为比大小的函数。这段程序运行的结果如下所示:


这里写图片描述


输出小于40的有6个数,大于40的有5个数。


  谈到了算法,谈到了容器,免不了会想到使用户哪一个,哪一个效率高,取决与数据的特性,根据特性选择适当的容器,这里面会牵扯到复杂度的问题(complexity,Big-oh)


  目前常见的Big-oh有下列几种形式:


这里写图片描述


  而刚才我们说到的使用哪一个,哪一个效率高的问题,以及本文的标题为几种容器的测试,那么接下来我们主要来说一下C++标准库中的几种容器,

这里写图片描述
  通过上图可以看出,在C++中的容器主要有两大类:sequence containers和associative containers两种,而unordered containers也是属于associative containers的一种。图中的“->”、“<-”代表指针。存内存的角度来说,vector容器的扩充是通过分配器进行扩充的,而Deque的扩充是一段一段的进行,链表list有两个指针,分别指向上一个和下一个结点,而Forward list这是一个单向的链表,每个结点只有一个指针并且其指向下一个结点,而不能指向上一个结点,同时list比Forward list要占内存,list都是通过指针串起来的,且每个元素带有两个指针。同时他们都属于sequence containers。


  那么如果我们的需求是要进行大量的查找的话,更多的时候Associative containers 的效率会比sequence containers的效率要高,对于关联型容器有:Set\MultiSet\Map\MultiMap然而对于set而言他的数据成员中key就是value,value就是key,而Map它的key和value是分开的(对于Map而言,它的一个数据成员由一个key和一个value组成);通常我们还会使用到哈希表(Harshtable)这种unordered containers也属于一种Associative containers它有unordered set\MultiSet、unordered Map\MultiMap。


  注意:如果选择的是Set,表示放的元素不能重复;如果选择的是Map,表示元素的key不能重复;但是如果选择的是MultiSet或者MultiMap的话则MultiSet的元素是可以重复的、MultiMap的key(键值)也是可以重复的。


  了解了又哪些容器之后,接下来我们来对这几种容器分别通过代码来进行分析,程序通过查找某一个long型元素long get_a_target_long(),或者string型字符串来进行测试。下面的代码为在一个命名空间中定义需要获取的long型元素函数、需要获取string型的元素函数、对long型元素进行大小比较的函数 int comparelongs(const void * a,const void b)、对string型字符串进行大小比较的函数int comparestrings(const void a, const void * b)……

#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<cstdio>#define snprintf _snprintfusing namespace std;namespace exp1{    long get_a_target_long()    {        long target = 0;        cout << "target(0~" << RAND_MAX << ")  ";        cin >> target;        return target;    }    string get_a_target_string()    {        long target = 0;        char buf[10];        cout << "target string(0~ " << RAND_MAX << ") ";        cin >> target;        snprintf(buf, 10, "%", target);//将 long 型的对象target 转化成字符串        return string(buf);    }    int comparelongs(const void * a,const void *b)    {        if (*(long *)a > *(long *)b)            return 1;        else if (*(long *)a < *(long *)b)            return -1;        else            return 0;        //return (*(long *)a-*(long *)b);    }    int comparestrings(const void * a, const void * b)    {        if (*(string *)a>*(string *)b)            return 1;        else if (*(string *)a < *(string *)b)            return -1;        else 0;    }}

  上述程序中* (long *)a的意思为将指针a转化成long型指针,然后再取它的地址。


  •   Array数组的测试程序:
#include<array>#include<cstdio>#include<cstdlib>#include<ctime>using namespace std;namespace test_array{const long ASIZE = 1000000;void test_array(){    cout << "\n test_array()......\n";    array<long, ASIZE>c;    clock_t timestate = clock();    long target =exp1:: get_a_target_long();    srand((int)time(NULL));//随机数种子    for (long i = 0; i < ASIZE; i++)    {        c[i] = rand();    }    //打印出数组的相关信息    cout << "milli-seconds of rand array c : " << (clock() - timestate) << endl;    cout << "array.front() = " << c.front() << endl;    cout << "array.back() = " << c.back() << endl;    cout << "array.size() = " << c.size() << endl;    cout << "array.data() = " << c.data() << endl;    timestate = clock();    ::qsort(c.data(),ASIZE,sizeof(long),exp1::comparelongs);//快速排序    long * PItem = (long *)bsearch(&target,c.data(),ASIZE,sizeof(long),exp1::comparelongs);    cout << "qsort()+bsearch(),milli-seconds : " << (clock() - timestate) << endl;    if (PItem != NULL)        cout << "found : " << *PItem << endl;    else        cout << "not found!" << endl;}}int main(){    test_array::test_array();    system("pause");    return 0;}

测试结果如下:


这里写图片描述


  其中bsearch为二分查找法,注意在使用二分查找法之前需要排好序,qsort()为快速排序法。测试的结果123为通过控制台输入的需要查找的字符串“123”,程序从开始到现在用时27856ms,数组的第一个元素为11186,数组的最后一个元素为24423,数组的长度为10万,数组的首地址为0173DE20,通过快速排序法后进行二分法查找字符串123用时121ms。


  •   vector容器的测试程序:
#include<iostream>#include<vector>#include<cstdio>#include<cstdlib>#include<algorithm>#include<string>#include<ctime>using namespace std;namespace test_vector{    void test_vector(long & value){        cout << "\n test_vector()........\n" << endl;        vector<string>s;        char buf[10];        clock_t timestate = clock();        srand((int)time(NULL));//随机数种子        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());//将随机生成的 long 型数据变成 string 类型的字符串                //将每一个字符串 压入 s 中                s.push_back(string(buf));//在尾部增加一个数据            }/*************************************************************************************************/            catch (exception & p){//捕获并处理异常                cout << "i = " << i << "  " << p.what() << endl;                /*如果new杂调用分配器分配存储空间时出现错误(错误信息被保存了一下),就会catch到                一个bad_alloc 类型的异常,其中的what()函数,就是提取这个错误的基本信息,*/                abort();//程序终止            }        }        cout << "milli-seconds of rand vector s : " << (clock() - timestate) << endl;        cout << "vector s.size() = " << s.size() << endl;        cout <<"vector s.front() = " << s.front() << endl;        cout << "vector s.back() = " << s.back() << endl;        cout << "vector s.max_size() = " << s.max_size() << endl;//得到vector最大可能是多少        cout <<  "vector s.data() = " << s.data() << endl;//传回数组在内存里面的起点的地址        cout << "vector s.capacity() = " << s.capacity() << endl;//capacity 表示当前vector分配的大小        string target = exp1::get_a_target_string();        {//测试循序查找法 fine 的效率            timestate = clock();            auto PItem = ::find(s.begin(), s.end(), target);//循序查找法,找target            cout << "::find milli-seconds : " << (clock() - timestate) << endl;            if (PItem != s.end())                cout << "found the vector target: " << *PItem << endl;            else                cout << "not found vector target!" << endl;        }        //使用二分法进行查找需要的时间与循序查找法进行对比,但是需要注意的是,使用二分法查找时        //首先需要对其进行排序,然后才能 bsearch .        {            timestate = clock();            sort(s.begin(), s.end());/*************** 注意算法调用时他的参数个数  *****************/            string * PItem = (string *)::bsearch(&target,s.data(),value,sizeof(string),exp1::comparestrings);            cout << "sort()+bsearch(),milli-seconds : " << (clock() - timestate) << endl;            if (PItem!=NULL)                cout << "found the vector target: " << *PItem << endl;            else                cout << "not found vector target!" << endl;        }    }}int main(){    long value =500000;    test_vector::test_vector(value);    system("pause");    return 0;}

  测试结果如下:


这里写图片描述


  随机生成50万个元素,然后再50万个元素中分别使用::find()以及bsearch()进行查找123字符串。


  **注意:**1.在写测试程序的时候,将每一个小的测试程序放在一个namespace中,每个namespace中的任何定义,任何变量不会与其他namespace相冲突,而且在每个namespace的上头会有这个namespace所需要的头文件,头文件可以重复#include,因为其自身有保护机制(#ifndef…#define…#endif).


  **注意:**2.变量的申明在写正规程序的时候放在程序的开始。


  **注意:**3.vector的空间时两倍增长的,当放第一个元素时它占用的内存空间是1,再加上一个元素后占用的内存空间时2;此时若是再加上一个元素后,它此时的内存占用空间不是3而是4,因为他的内存空间的增长是两倍两倍的增长的。


  **注意:**4.在上述的程序大家会看到使用可try…catch…的写法,这样的话程序执行到这一块后如果发生了异常则会终止程序abort()。


  •   list容器的测试程序
#include<iostream>#include<ctime>#include<cstdio>#include<cstdlib>#include<list>#include<algorithm>using namespace std;namespace test_list{    void test_list(long & value)    {        cout << "\n test_list()......\n" << endl;        list<string>l;        char buf[10];        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf,10,"%d",rand());                l.push_back(string(buf));            }            catch (exception & p){                cout << "i = " << i <<" "<< p.what() << endl;                abort();            }        }        cout << "milli-seconds of rand list l : " << (clock() - timestate) << endl;        cout << "list l.size() = " << l.size() << endl;        cout << "list l.max_size() = " << l.max_size() << endl;        cout << "list l.front() = " << l.front() << endl;        cout << "list l.back() = " << l.back() << endl;    //上述程序已经生成了 value 个元素的链表        string target = exp1::get_a_target_string();        {            timestate = clock();            auto PItem = ::find(l.begin(), l.end(), target);            cout << "::find the list target  milli-seconds : " << (clock() - timestate) << endl;            if (PItem != l.end())                cout << "found the list target : " << *PItem << endl;            else                cout << "not found the list " << endl;        }        timestate = clock();        l.sort();        cout << "the list of the  l.sort(),milli-seconds : " << (clock() - timestate)<<endl;    }}int main(){    long value =500000;    test_list::test_list(value);    system("pause");    return 0;}

  •   forward_list容器的测试程序
#include<iostream>#include<ctime>#include<cstdlib>#include<cstdio>#include<forward_list>using namespace std;namespace test_forward_list{    void test_forward_list(long & value)    {        cout << "\n test_forward_list()........\n" << endl;        char buf[10];        forward_list<string>f;        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                f.push_front(string(buf));            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of rand froward_list  f : " << (clock() - timestate) << endl;        cout << "froward_list f..max_size() = " << f.max_size() << endl;        cout << "froward_list f.front() = " << f.front() << endl;        string target = exp1::get_a_target_string();        {            timestate = clock();            auto PItem = ::find(f.begin(), f.end(), target);            cout << "::find the forward_list target  milli-seconds : " << (clock() - timestate) << endl;            if (PItem != f.end())                cout << "found the forward_list target : " << *PItem << endl;            else                cout << "not found the forward_list " << endl;        }        timestate = clock();        f.sort();        cout << "the forward_list of the  f.sort(),milli-seconds : " << (clock() - timestate) << endl;    }}int main(){    long value =500000;    test_forward_list::test_forward_list(value);    system("pause");    return 0;}

  •   deque容器的测试程序
#include<iostream>#include<ctime>#include<cstdlib>#include<cstdio>#include<deque>using namespace std;namespace test_deque{    void test_deque(long & value)    {        cout << "\n test_deque()........\n" << endl;        char buf[10];        deque<string>d;        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                d.push_front(string(buf));            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of rand test_deque  f : " << (clock() - timestate) << endl;        cout << "test_deque d.max_size() = " << d.max_size() << endl;        cout << "test_deque d.front() = " << d.front() << endl;        string target = exp1::get_a_target_string();        {            timestate = clock();            auto PItem = ::find(d.begin(), d.end(), target);            cout << "::find the test_deque target  milli-seconds : " << (clock() - timestate) << endl;            if (PItem != d.end())                cout << "found the test_deque target : " << *PItem << endl;            else                cout << "not found the test_deque " << endl;        }    }}int main(){    long value =500000;    test_deque::test_deque(value);    system("pause");    return 0;}

  •   stack栈的测试程序
#include<iostream>#include<ctime>#include<cstdlib>#include<cstdio>#include<stack>using namespace std;namespace test_stack{    void test_stack(long & value)    {        cout << "\n test_stack()........\n" << endl;        char buf[10];        stack<string>st;        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                st.push(string(buf));            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of rand test_stack  st : " << (clock() - timestate) << endl;        cout << "test_stack st.size() = " << st.size() << endl;        cout << "test_stack st.top() = " << st.top()<<endl;            st.pop();        cout << "test_stack st.size() = " << st.size() << endl;        cout << "test_stack st.top() = " << st.top() << endl;/**********************************************************************************************/        //给 stack (栈)中元素排序需要先定义一个暂时缓冲栈        //以下为给栈 st 中的元素进行排序        timestate = clock();        stack<string>Help;        while (!st.empty())        {            string Curvalue = st.top();//先将栈顶元素给一个中间字符串元素            st.pop();            while (!Help.empty() && Curvalue > Help.top())//在另外一个栈中寻找插入位置            {                st.push(Help.top());                Help.pop();            }            Help.push(Curvalue);        }        while (!Help.empty())        {            string val = Help.top();            st.push(val);            //cout << Help.top() << "  ";            Help.pop();        }        cout << endl;        cout << "sort  of  stack,milli-seconds : " << (clock() - timestate) << endl;/**********************************************************************************************/    }}int main(){    long value =500000;    test_stack::test_stack(value);    system("pause");    return 0;}

  •   queue堆的测试程序
#include<iostream>#include<ctime>#include<cstdlib>#include<cstdio>#include<queue>using namespace std;namespace test_queue{    void test_queue(long & value)    {        cout << "\n test_queue()........\n" << endl;        char buf[10];        queue<string>que;        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                que.push(string(buf));            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of the test_queue  que : " << (clock() - timestate) << endl;        cout << "test_queue st.size() = " << que.size() << endl;        cout << "test_queue st.front() = " << que.front() << endl;        cout << "test_queue st.back() = " << que.back() << endl;        que.pop();        cout << "test_queue st.size() = " << que.size() << endl;        cout << "test_queue st.front() = " << que.front() << endl;        cout << "test_queue st.back() = " << que.back() << endl;    }}int main(){    long value =500000;    test_queue::test_queue(value);    system("pause");    return 0;}

  上述的几个测试程序都是sequence containers类型,那么对于Associatice containers类型的容器又会如何呢?下面给出了Multiset和MultiMap类型的容器的测试程序:


  •   multiset容器的测试程序
/***********             ***********///测试associative container 的效率/***********             ***********/#include<iostream>#include<ctime>#include<set>#include<cstdlib>#include<cstdio>using namespace std;namespace test_multiset{    void test_multiset(long & value)    {        cout << "\n test_multiset().........\n";        char buf[10];        multiset<string>mu;        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                mu.insert(string(buf));//插入数据            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of the test_multiset mu : " << (clock() - timestate) << endl;        cout << "test_multiset  mu.size() = " << mu.size() << endl;        cout << "test_multiset mu.max_size()" << mu.max_size() << endl;        string target = exp1::get_a_target_string();        {            timestate = clock();            auto PItem = ::find(mu.begin(), mu.end(), target);            cout << "tets_multiset ::find  milli-seconds : " << (clock() - timestate) << endl;            if (PItem != mu.end())                cout << "test_multiset ::find the target : " << *PItem << endl;            else                cout << "test_multiset not found the target ! " << endl;        }        {            timestate = clock();            auto PItem = mu.find(target);//multiset 自身的find算法            cout << "tets_multiset find  milli-seconds : " << (clock() - timestate) << endl;            if (PItem != mu.end())                cout << "test_multiset find the target : " << *PItem << endl;            else                cout << "test_multiset not found the target ! " << endl;        }    }}int main(){    long value =500000;    test_multiset::test_multiset(value);    system("pause");    return 0;}

  •   multiMap容器的测试程序
#include<iostream>#include<map>#include<ctime>#include<cstdio>#include <stdexcept>#include <string>#include <cstdlib> //abort()#include <cstdio>  //snprintf()#include<utility>using namespace std;namespace test_multimap{    void test_multimap(long & value){        cout << "\n test_multimap()........\n" << endl;        char buf[10];        multimap<long, string>mu_map;//定义一个multimap的对象        clock_t timestate = clock();        srand((int)time(NULL));        for (long i = 0; i < value; i++){            try{                snprintf(buf, 10, "%d", rand());                //multimap 不可使用 [] 做 insertion                 mu_map.insert(pair<long, string>(i, buf));//************插入时为键+值            }            catch (exception & p){                cout << "i = " << i << "  " << p.what() << endl;                abort();            }        }        cout << "milli-seconds of the test_multimap mu_map : " << (clock() - timestate) << endl;        cout << "test_multimap mu_map.max_size() = " << mu_map.max_size() << endl;        cout << "test_multimap mu_map.size() = " << mu_map.size() << endl;        long target = exp1::get_a_target_long();        {        timestate = clock();        auto PItem = ::find(mu_map.begin(), mu_map.end(), target);        cout << "milli-secpnds ::find test_multimap : " << (clock() - timestate) << endl;            if (PItem != mu_map.end())                cout << "test_multimap ::  found," << (*PItem).second << endl;            else                cout << "test_multimap not found !" << endl;        }        {            timestate = clock();            auto PItem = mu_map.find(target);            cout << "milli-secpnds find test_multimap : " << (clock() - timestate) << endl;            if (PItem != mu_map.end())                cout << "test_multimap ::  found," << (*PItem).second << endl;            else                cout << "test_multimap not found !" << endl;        }    }}int main(){    long value =500000;    test_multimap::test_multimap(value);    system("pause");    return 0;}

  •   补充:下面主要补充一下try\catch\throw的 使用

  1.“try”总是与“catch”一同出现,伴随一个try语句,至少应该有一个catch()语句,try随后的block是可能抛出异常的地方。


  2.“catch”带有一个参数,参数类型以及参数名字都由程序指定,名字可以忽略。如果在catch随后的block中并不打算引用这个异常对象的。参数类型可以是build-intype,例如int、long、char等,也可以是一个对象,一个对象指针或者引用,如果希望捕获任意类型的异常,可以使用“…”作为catch的参数。


  3.“catch”不一定要全部捕获tryblock中抛出的异常,剩下没有捕获的可以交给上一级函数处理。


  4.“throw”throw类型后面带一个类型的实例,它和catch的关系就像是函数的调用,catch指定形参,throw给出实参。编译器按照catch给定的顺序以及catch指定的参数类型,确定一个异常由哪一个catch来处理。