一、容器适配器
stack
queue
priority_queue
stack、queue、priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/deque/list对象创建了一个先进后出容器;queue是用deque或list对象创建了一个先进先出容器;priority_queue是用vector/deque创建了一个排序队列,内部用二叉堆实现。
(一)、stack
首先来看示例代码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br></nobr>
|
#include<iostream>
#include<vector> #include<list> #include<stack> using namespacestd; intmain( void) { stack< int,list< int>>s; for( inti= 0;i< 5;i++) { s.push(i); } //for(size_ti=0;i<s.size();i++) //{ //cout<<s.top()<<'';Error:size()一直在变化 //s.pop(); //} while(!s.empty()) { cout<<s.top()<< ''; s.pop(); } cout<<endl; return 0; } |
再看stack 的源码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br></nobr>
|
//TEMPLATECLASSstack template< class_Ty, class_Container=deque<_Ty>> classstack { //LIFOqueueimplementedwithacontainer public: typedef_Containercontainer_type; typedef typename_Container::value_typevalue_type; typedef typename_Container::size_typesize_type; typedef typename_Container::referencereference; typedef typename_Container::const_referenceconst_reference; stack() :c() { //constructwithemptycontainer } explicitstack( const_Container&_Cont) :c(_Cont) { //constructbycopyingspecifiedcontainer } boolempty() const { //testifstackisempty return(c.empty()); } size_typesize() const { //testlengthofstack return(c.size()); } referencetop() { //returnlastelementofmutablestack return(c.back()); } const_referencetop() const { //returnlastelementofnonmutablestack return(c.back()); } voidpush( constvalue_type&_Val) { //insertelementatend c.push_back(_Val); } voidpop() { //eraselastelement c.pop_back(); } const_Container&_Get_container() const { //getreferencetocontainer return(c); } protected: _Containerc; //theunderlyingcontainer }; |
即有一个_Container 成员,默认是deque<_Ty> ,当然也可以传递vector, list 进去,只要支持push_back,pop_back 等接口。内部的函数实现
都借助了容器的函数,跟以前实现过的Stack 很像。
(二)、queue
先来看示例代码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br></nobr>
|
#include<iostream>
#include<vector> #include<list> #include<stack> #include<queue> using namespacestd; intmain( void) { //inta[]={1,2,3,4,5}; //vector<int>v(a,a+5); queue< int,list< int>>q; for( inti= 0;i< 5;i++) { q.push(i); } while(!q.empty()) { cout<<q.front()<< ''; q.pop(); } cout<<endl; return 0; } |
再来看queue 源码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br> 71<br> 72<br> 73<br> 74<br> 75<br> 76<br> 77<br> 78<br> 79<br> 80<br> 81<br> 82<br></nobr>
|
//TEMPLATECLASSqueue template< class_Ty, class_Container=deque<_Ty>> classqueue { //FIFOqueueimplementedwithacontainer public: typedef_Containercontainer_type; typedef typename_Container::value_typevalue_type; typedef typename_Container::size_typesize_type; typedef typename_Container::referencereference; typedef typename_Container::const_referenceconst_reference; queue() :c() { //constructwithemptycontainer } explicitqueue( const_Container&_Cont) :c(_Cont) { //constructbycopyingspecifiedcontainer } boolempty() const { //testifqueueisempty return(c.empty()); } size_typesize() const { //returnlengthofqueue return(c.size()); } referencefront() { //returnfirstelementofmutablequeue return(c.front()); } const_referencefront() const { //returnfirstelementofnonmutablequeue return(c.front()); } referenceback() { //returnlastelementofmutablequeue return(c.back()); } const_referenceback() const { //returnlastelementofnonmutablequeue return(c.back()); } voidpush( constvalue_type&_Val) { //insertelementatbeginning c.push_back(_Val); } voidpop() { //eraseelementatend c.pop_front(); } const_Container&_Get_container() const { //getreferencetocontainer return(c); } protected: _Containerc; //theunderlyingcontainer }; |
实现跟stack 是很类似的,只是queue不能用vector 实现,因为没有pop_front 接口。
(三)、priority_queue
先来看示例代码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br></nobr>
|
#include<iostream>
#include<functional> #include<vector> #include<list> #include<stack> #include<queue> using namespacestd; intmain( void) { inta[]={ 5, 1, 2, 4, 3}; priority_queue< int,vector< int>,greater< int>>q(a,a+ 5); while(!q.empty()) { cout<<q.top()<< ''; q.pop(); } cout<<endl; return 0; } |
再来看priority_queue 的源码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br> 67<br> 68<br> 69<br> 70<br> 71<br> 72<br> 73<br> 74<br> 75<br> 76<br> 77<br> 78<br> 79<br> 80<br> 81<br> 82<br> 83<br> 84<br> 85<br> 86<br> 87<br> 88<br> 89<br> 90<br> 91<br> 92<br> 93<br> 94<br> 95<br> 96<br> 97<br> 98<br> 99<br> 100<br> 101<br></nobr>
|
//TEMPLATECLASSpriority_queue template< class_Ty, class_Container=vector<_Ty>, class_Pr=less< typename_Container::value_type>> classpriority_queue { //priorityqueueimplementedwitha_Container public: typedef_Containercontainer_type; typedef typename_Container::value_typevalue_type; typedef typename_Container::size_typesize_type; typedef typename_Container::referencereference; typedef typename_Container::const_referenceconst_reference; priority_queue() :c(),comp() { //constructwithemptycontainer,defaultcomparator } explicitpriority_queue( const_Pr&_Pred) :c(),comp(_Pred) { //constructwithemptycontainer,specifiedcomparator } priority_queue( const_Pr&_Pred, const_Container&_Cont) :c(_Cont),comp(_Pred) { //constructbycopyingspecifiedcontainer,comparator make_heap(c.begin(),c.end(),comp); } template< class_Iter> priority_queue(_Iter_First,_Iter_Last) :c(_First,_Last),comp() { //constructbycopying[_First,_Last),defaultcomparator make_heap(c.begin(),c.end(),comp); } template< class_Iter> priority_queue(_Iter_First,_Iter_Last, const_Pr&_Pred) :c(_First,_Last),comp(_Pred) { //constructbycopying[_First,_Last),specifiedcomparator make_heap(c.begin(),c.end(),comp); } template< class_Iter> priority_queue(_Iter_First,_Iter_Last, const_Pr&_Pred, const_Container&_Cont) :c(_Cont),comp(_Pred) { //constructbycopying[_First,_Last),container,andcomparator c.insert(c.end(),_First,_Last); make_heap(c.begin(),c.end(),comp); } boolempty() const { //testifqueueisempty return(c.empty()); } size_typesize() const { //returnlengthofqueue return(c.size()); } const_referencetop() const { //returnhighest-priorityelement return(c.front()); } referencetop() { //returnmutablehighest-priorityelement(retained) return(c.front()); } voidpush( constvalue_type&_Pred) { //insertvalueinpriorityorder c.push_back(_Pred); push_heap(c.begin(),c.end(),comp); } voidpop() { //erasehighest-priorityelement pop_heap(c.begin(),c.end(),comp); c.pop_back(); } protected: _Containerc; //theunderlyingcontainer _Prcomp; //thecomparatorfunctor }; |
调用make_heap函数构造二叉堆,comp 主要是用于构造二叉堆时的判别,如果是less 则构造大堆,如果传递greater 则构造小堆.
注意,priority_queue 不能用list 实现,因为list 只支持双向迭代器,而不支持随机迭代器。
下面举个例子说明make_heap 函数的用法:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br></nobr>
|
#include<iostream>
#include<functional> #include<vector> #include<list> #include<stack> #include<queue> using namespacestd; intmain( void) { inta[]={ 5, 1, 2, 4, 3}; make_heap(a,a+ 5,less< int>()); copy(a,a+ 5,ostream_iterator< int>(cout, "")); cout<<endl; sort(a,a+ 5); //sort_heap(a,a+5,less<int>()); copy(a,a+ 5,ostream_iterator< int>(cout, "")); cout<<endl; return 0; } |
输出:
5 4 2 1 3
1 2 3 4 5
make_heap() 将容器的元素构造成二叉堆,传递的是less,即构造的是大堆,把大堆层序遍历的结果存入数组,再调用sort() 进行排序,内部调用
的实际算法不一定,可以是堆排序、插入排序、选择排序等等,跟踪进去发现调用的是插入排序;当然也可以直接指定使用堆排序 sort_heap(调用
者必须已经是堆了,也就是前面已经先调用了make_heap,而且大小堆类型得匹配),与make_heap 一样,第三个参数传递的都是函数对象的用
法。sort 和 sort_heap 默认都是从小到大排序,除非重载的版本传递了第三个参数,如下,第三个参数可以是函数指针,也可以是函数对象:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br></nobr>
|
//orderheapbyrepeatedlypopping,usingoperator< template< class_RanIt> inline voidsort_heap(_RanIt_First,_RanIt_Last); //orderheapbyrepeatedlypopping,using_Pred template< class_RanIt, class_Pr> inline voidsort_heap(_RanIt_First,_RanIt_Last,_Pr_Pred); |
传递greater 构造的是小堆,如下图所示:
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范