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来处理。
- c++之容器(boolan)
- c++之list容器简述--(boolan)
- 简述容器之rb_tree及其应用--(boolan)
- boolan——c++学习笔记之容器
- boolan——c++学习笔记之容器探索
- C++ 容器——Boolan
- 【boolan c++】面向对象高级编程(下)week1
- c++primer之顺序容器(容器库概览)
- c++STL通用容器 之 bitset容器
- STL模板学习之set容器(C/C++)
- 浅谈c++之面向对象程序设计的几种小技巧系列之第一部分--(boolan)
- 【boolan c++】 带有指针成员的class
- C++STL之堆栈容器
- C++STL之set容器
- [C++]STL容器之priority_queue
- C++STL之vector容器
- C++STL之list容器
- C++STL之序列容器
- 【报表】ireport的闪退问题--jdk版本不对
- Spring boot 系列入门(一)
- 常用机器学习数据集网站
- WebRTC下的网络连接: STUN, TURN, ICE, TCP
- js 倒计时
- c++之容器(boolan)
- 基于分布式环境下限流系统的设计
- java数据存储
- LeetCode200 Number of Islands
- HDU 3037 Saving Beans(组合数学+Lucas定理)
- 处理数字类问题
- 细胞数量
- 前端零碎知识
- mysql中日期类型DATETIME和TIMESTAMP的区别