`
aspnetwinform
  • 浏览: 89849 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
社区版块
存档分类
最新评论

从零开始学C++之STL(十一):容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例

 
阅读更多

一、容器适配器
stack
queue
priority_queue


stack、queue、priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是vector/deque/list对象创建了一个先进后出容器;queue是用deque或list对象创建了一个先进先出容器;priority_queue是用vector/deque创建了一个排序队列,内部用二叉堆实现。


(一)、stack

首先来看示例代码:

C++ Code
<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>

usingnamespacestd;

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;
return0;
}

再看stack 的源码:

C++ Code
<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;
typedeftypename_Container::value_typevalue_type;
typedeftypename_Container::size_typesize_type;
typedeftypename_Container::referencereference;
typedeftypename_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

先来看示例代码:

C++ Code
<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>

usingnamespacestd;

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;

return0;
}

再来看queue 源码:

C++ Code
<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;
typedeftypename_Container::value_typevalue_type;
typedeftypename_Container::size_typesize_type;
typedeftypename_Container::referencereference;
typedeftypename_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

先来看示例代码:

C++ Code
<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>

usingnamespacestd;

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;

return0;
}

再来看priority_queue 的源码:

C++ Code
<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;
typedeftypename_Container::value_typevalue_type;
typedeftypename_Container::size_typesize_type;
typedeftypename_Container::referencereference;
typedeftypename_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
};


priority_queue 的实现稍微复杂一点,可以传递3个参数,而且有两个成员,comp 即自定义比较逻辑,默认是less<value_type>,在构造函数中

调用make_heap函数构造二叉堆,comp 主要是用于构造二叉堆时的判别,如果是less 则构造大堆,如果传递greater 则构造小堆.

注意,priority_queue 不能用list 实现,因为list 只支持双向迭代器,而不支持随机迭代器。


下面举个例子说明make_heap 函数的用法:

C++ Code
<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>

usingnamespacestd;

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;

return0;
}

输出:

5 4 2 1 3

1 2 3 4 5

make_heap() 将容器的元素构造成二叉堆,传递的是less,即构造的是大堆,把大堆层序遍历的结果存入数组,再调用sort() 进行排序,内部调用

的实际算法不一定,可以是堆排序、插入排序、选择排序等等,跟踪进去发现调用的是插入排序;当然也可以直接指定使用堆排序 sort_heap(调用

者必须已经是堆了,也就是前面已经先调用了make_heap,而且大小堆类型得匹配),与make_heap 一样,第三个参数传递的都是函数对象的用

法。sort 和 sort_heap 默认都是从小到大排序,除非重载的版本传递了第三个参数,如下,第三个参数可以是函数指针,也可以是函数对象:

C++ Code
<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++编程规范


分享到:
评论

相关推荐

    c++stack_和_queue用法

    ### C++ STL中Stack和Queue的使用详解 #### 一、引言 在C++标准模板库(STL)中,提供了许多高效的容器类,其中包括`stack`和`queue`。这两种容器非常适合处理需要先进后出(FILO, First In Last Out)或先进先出(FIFO,...

    C++ STL Adaptor stack、queue和vector的使用.doc

    C++ STL Adaptor stack、queue和vector的使用 C++ STL 提供了多种容器类,包括 stack、queue 和vector 等,这些容器类都是基于 Adaptor 模式实现的。下面我们将详细介绍这些容器类的使用方法和常见操作。 Stack ...

    c++STL容器适配器习题答案.docx

    - **栈的实现**:示例代码展示了如何使用`stack`容器适配器,包括`push()`、`pop()`、`empty()`、`top()`和`size()`函数的用法,体现栈的特性。 - **双端队列的实现**:示例代码展示了如何使用`deque`容器,以及`...

    C++STL详解PPT

    顺序容器包括 vector、deque、list 等,关联容器包括 set、multiset、map、multimap 等,容器适配器包括 stack、queue、priority_queue 等。 顺序容器是 STL 中的一种基本容器,用于存放各种类型的数据。顺序容器...

    STL.rar_C++ STL_C++ STL_STL_STL c++_STL教程

    - 特殊容器如stack(栈)、queue(队列)和priority_queue(优先队列)的使用场景和操作方法。 - 泛型编程的概念,理解模板和模板函数在STL中的作用。 - STL容器和算法的性能分析,如时间复杂度和空间复杂度。 通过...

    C++高手之STL学习资料

    5. 适配器:适配器允许将现有容器或迭代器转换为其他形式,例如stack(栈)、queue(队列)和priority_queue(优先队列)是容器适配器,reverse_iterator(反向迭代器)是迭代器适配器。 《STL_Programmer_Guide....

    EffectiveSTL_STL_C++_experience_gas841_C++STL_

    5. 特殊容器和组件:如stack(栈)、queue(队列)和priority_queue(优先队列)等,它们是基于现有容器实现的抽象数据类型,Meyers会指导读者如何有效地利用它们。 6. 模板元编程:Meyers还涉及了模板元编程这一...

    source-stl.rar_STL 源码_stl source_stl 代码

    5. **适配器**:适配器是一种设计模式,STL中有两种主要类型的适配器:容器适配器(如stack、queue和priority_queue)和迭代器适配器。它们可以将现有的容器或迭代器转换为其他形式,以满足特定需求。 6. **内存...

    stl的学习:c++ STL

    STL的主要组成部分包括容器、迭代器、算法和函数对象,这些组件共同构成了一个强大的工具集,极大地简化了C++程序中的数据管理和操作。 1. 容器: - **向量(Vector)**:动态数组,支持在任意位置插入和删除元素...

    SGI_STL源码(附带个人详细)

    5. 配接器(Adapters):如`stack`、`queue`和`priority_queue`,它们将底层容器包装成特定的抽象数据类型,简化了编程模型。 6. 适配器函数:如`bind1st`和`bind2nd`,以及`mem_fun`系列,它们用于封装成员函数,...

    c++标准库STL手册

    - 适配器类如`stack`, `queue`, `priority_queue`将基本容器转换为特定用途的数据结构。 - 容器适配器提供了一种方式,使得开发者可以使用已有的容器实现栈、队列或优先级队列的功能。 6. **智能指针** - 智能...

    C++的STL源代码(STLport-5.2.1_src)

    6. **适配器(Adapters)**:适配器可以改变容器、迭代器或函数对象的行为,如stack和queue是容器适配器,将底层的容器(如deque)转换为栈或队列;priority_queue则是优先级队列适配器。 7. **STLport的实现特点**...

    STL 应用例子 包括各容器的使用

    适配器如`std::stack`,`std::queue`,`std::priority_queue`将基本容器转化为特定用途的数据结构。 7. **算法的使用**: `sort_test`可能展示了如何使用`std::sort`对容器进行排序,`randfunc`可能涉及随机数...

    c++STL容器讲义与演示

    主要有四大类容器:顺序容器(如vector、deque、list)、关联容器(如set、map)、容器适配器(如stack、queue、priority_queue)以及未分类容器(如unordered_set、unordered_map)。这些容器各自有不同的特性和...

    c++ STL 库使用示例

    C++ STL(Standard Template Library,标准模板库)是C++编程语言中不可或缺的一部分,它提供了一组高效、灵活且可重用的容器、迭代器、算法和函数对象(也称为仿函数)。STL的主要目标是简化代码,提高性能,并遵循...

    C++ STL--数据结构与算法实现(余文溪)示例程序代码.rar

    5. 配接器(Adapters):如栈(`stack`)、队列(`queue`)、优先队列(`priority_queue`)等,它们将现有容器包装成特定的抽象数据类型。 6. 适配器(Adaptors):包括迭代器适配器(如反向迭代器)和函数对象...

    侯捷STL课件_C++_候捷课件stl_c++侯捷课件_

    例如,stack和queue是基于deque的适配器,priority_queue是基于heap的适配器。侯捷会详细解析这些适配器的工作原理和使用方法。 6. **内存管理(Memory Management)**:STL容器通常使用智能指针(如auto_ptr、...

    C++ - SGI 版本 STL源码

    **C++ SGI版STL源码详解** STL(Standard Template Library,标准模板库)是C++编程语言中的一个重要组成部分,它提供了高效且灵活的数据结构和算法。SGI(Silicon Graphics, Inc.)公司在90年代为C++社区贡献了一...

    c++ STL 范例大全

    总结来说,本文档提供了一个关于C++ STL容器的全面介绍,包括了各种容器的基本用法、构造方法以及成员函数的使用示例。这些例子可以帮助初学者更好地理解和掌握C++ STL中的容器概念,进而提高编程效率。

Global site tag (gtag.js) - Google Analytics