C++学习19:C++容器适配器:stack、queue和priority queue

本文详细介绍了C++标准库中的三种容器适配器:stack(栈)、queue(队列)和priority_queue(优先队列)。每种容器适配器都有其独特的应用场景和特点,文章通过具体实例展示了它们的使用方法。

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

C++标准库中提供了三个容器适配器:stack(栈)、queue(队列)和priority queue(优先队列)。这三种容器适配器提供了简单易用的接口,满足了编程中的特殊数据处理需求,本节将针对这三种容器适配器进行讲解。

stack 

stack中的元素具有后进先出的特点。stack只能从一端插入、删除、读取元素,不允许一次插入或删除多个元素,且不支持迭代器操作。stack存储结构如图7-17所示。下面分别介绍stack的常见用法。

图7-17 stack存储结构 

1.创建stack 

创建stack主要有两种方式,分别如下所示。

(1)创建空的stack。

创建空的stack,用于存储基本数据类型的元素,示例代码如下所示:

stack<int> st;

 (2)创建存储序列容器的stack。

创建存储序列容器的stack,stack的类型参数有两个,第一个类型参数为元素的数据类型,第二个类型参数为容器类型,示例代码如下所示:

vector<int> v = { 1,2,3 }; //创建vector容器v
stack<int,vector <int >> s(v); //创建stack容器适配器s,存储容器v

 2.元素访问

stack除了具有vector容器相同功能的成员函数,如empty()、size()、emplace()和swap()函数,还提供以下操作函数,如表7-3所示。

表7-3  stack元素操作函数含义 

下面通过案例演示stack的具体用法, 

测试1:

实例代码:

#include <iostream>
#include <iomanip>
#include<vector>
#include<deque>
#include<list>
#include<array>
#include<forward_list>
#include <set>
#include <functional>
#include <map>
#include <stack>

using namespace std;

template <class T>
void print_and_clear(stack<T ,vector<T>> &v)
{
    cout << "void print_and_clear(stack<T ,vector<T>> &v)" << endl;
    cout << "v.size() = " << v.size() << endl;
    while(!v.empty()){
        cout << v.top() << " ";
        v.pop();
    }
    cout << endl;
}

template <class T>
void init_stack(stack<T ,vector<T>> &s)
{
    vector<T> v = {1,2,3};
    typename vector<T>::iterator it;
    it = v.begin();
    while(it != v.end()){
        s.push(*it);
        it++;
    }
    s.push(4);
}


int main()
{
    stack<int ,vector<int>> s1;
    init_stack(s1);
    cout << s1.size() << endl;
    print_and_clear(s1);
    s1.emplace(5);
    print_and_clear(s1);
    cout << "--end--" << endl;
    return 0;
}

测试结果:

4
void print_and_clear(stack<T ,vector<T>> &v)
v.size() = 4
4 3 2 1
void print_and_clear(stack<T ,vector<T>> &v)
v.size() = 1
5
--end--

 测试2:自定义类,

进阶实例,看懂基本上就学会一半了,不是自己写的还未必能看的懂,估计我自己1个小时以后就忘,除非重写一遍,而且也没啥耐心研究。

#include <iostream>
#include <iomanip>
#include<vector>
#include<deque>
#include<list>
#include<array>
#include<forward_list>
#include <set>
#include <functional>
#include <map>
#include <stack>

using namespace std;

template <class T,int len>
class myclass
{
public:
    array<T,len> *arr;
    myclass(array<T,len> &a){
        cout << "myclass(array<T,len> &a)" << endl;
        arr = new array<T,len>(a);
        cout << "myclass init" <<endl;
    }
    ~myclass(){
        delete arr;
        cout << "myclass delete" <<endl;
    }
    myclass& operator=(myclass &a){
        cout << "myclass& operator=(myclass &a)" << endl;
        array<T,len> *p;
        p = new myclass<T,len>(a.arr);
        return *p;
    }
    void show()
    {
        cout << "void show()" << endl;
        typename array<T,len>::iterator it;
        it = this->arr->begin();
        while(it != this->arr->end()){
            cout << hex << *it << " ";
            it++;
        }
        cout << endl;
    }
};
int main()
{
    array<unsigned int,5> au = {0x89,0x65,0x12,0x31,0x03};
    myclass<unsigned int,5> m(au);
    vector<myclass<unsigned int,5>> v;
    v.push_back(m);
    cout << "v.size() = " << v.size() << endl;
    v[0].show();
    stack<myclass<unsigned int,5>,vector<myclass<unsigned int,5>>> s(v);
    cout << "s.size() = " << s.size() << endl;
    myclass<unsigned int,5> m2 = (myclass<unsigned int,5>)s.top();
    m2.show();
    cout << "--endl--" << endl;
    return 0;
}

执行结果:这个myclass类的析构函数被凌迟的四次,构造函数只调用了一次,这坑有点大啊。看看热闹就行了。

myclass(array<T,len> &a)
myclass init
v.size() = 1
void show()
89 65 12 31 3
s.size() = 1
void show()
89 65 12 31 3
--endl--
myclass delete
myclass delete
myclass delete
myclass delete

queue

queue中的元素具有先进先出的特点,元素只能从一端使用push()函数进行插入,从另一端使用pop()函数进行删除。queue的存储结构如图7-19所示。queue也不允许一次插入或删除多个元素,且不支持迭代器操作。queue创建对象的方式与stack相同,并且其接口与stack大部分都相同。除了提供了与vector相同的接口,queue还提供两个自己特有的成员函数,如表7-4所示。

 图7-19 queue的存储结构

表7-4  queue的操作函数含义 

 下面通过案例演示queue的用法:

实例代码:

#include <iostream>
#include <iomanip>
#include<vector>
#include<deque>
#include<list>
#include<array>
#include<forward_list>
#include <set>
#include <functional>
#include <map>
#include <stack>
#include <queue>

using namespace std;
template <class T>
void print(queue<T, list<T>> &q)
{
    while(!q.empty()){
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;
}

int main()
{
    list<int> l = {1,2,3};
    queue<int, list<int>> q(l);
    cout << q.front() << " " << q.back() << endl;
    cout << q.size() << endl;
    print(q);
    cout << q.size() << endl;
    q.push(4);
    q.emplace(5);
    cout << q.front() << " " << q.back() << endl;
    print(q);

    cout << "--endl--" << endl;
    return 0;
}

测试结果:

1 3
3
1 2 3
0
4 5
4 5
--endl--

 priority_queue

priority_queue中的元素可以按照自定义的方式进行动态排序。向priority_queue中插入或删除元素时,priority_queue会动态地调整,以保证元素有序。priority_queue的存储结构如图7-21所示。

图7-21 priority_queue的存储结构 

priority_queue创建方式与queue相同,只是在创建priority_queue时,可以指定优先规则,即最后一个模板参数可以是一个函数对象,指定元素排序规则。创建priority_queue的示例代码如下:

priority_queue<int,vector<int>,greater<int>> pq;

 priority_queue的接口与queue相同,使用比较简单。下面通过案例演示priority_queue的具体用法,

测试实例,其中有三个子测试:

#include <iostream>
#include <iomanip>
#include<vector>
#include<deque>
#include<list>
#include<array>
#include<forward_list>
#include <set>
#include <functional>
#include <map>
#include <stack>
#include <queue>

using namespace std;
template <class T>
void print(priority_queue<T> &q)
{
    while(!q.empty()){
        cout << q.top() << " ";
        q.pop();
    }
    cout << endl;
}
template <class T>
void print(priority_queue<T,vector<T>,greater<T>> &q)
{
    while(!q.empty()){
        cout << q.top() << " ";
        q.pop();
    }
    cout << endl;
}

void test_1()
{
    list<int> l = {1,12,3,15,4};
    priority_queue<int> q;
    list<int>::iterator it = l.begin();
    while(it != l.end()){
        q.push(*it);
        it++;
    }
    q.push(10);
    cout << q.size() << endl;
    print(q);
    cout << q.size() << endl;
}
void test_2()
{
    cout << endl;
    priority_queue<int,vector<int>,greater<int>> q;
    list<int> l = {1,12,3,15,4};
    list<int>::iterator it = l.begin();
    while(it != l.end()){
        q.push(*it);
        it++;
    }
    q.push(10);
    cout << q.size() << endl;
    print(q);
    cout << q.size() << endl;
}
template <class T>
class MyCompare{
public:
    bool operator()(T x,T y){
        return x > y;
    }
};
template <class T>
void print(priority_queue<T,vector<T>,MyCompare<int>> &q)
{
    while(!q.empty()){
        cout << q.top() << " ";
        q.pop();
    }
    cout << endl;
}
void test_3()
{
    cout << endl;
    priority_queue<int,vector<int>,MyCompare<int>> q;
    for(int  n: {21,12,23,15,24}){
        q.push(n);
    }
    q.push(19);
    cout << q.size() << endl;
    print(q);
    cout << q.size() << endl;
}
int main()
{
    test_1();
    test_2();
    test_3();
    cout << "--endl--" << endl;
    return 0;
}

 测试结果:

6
15 12 10 4 3 1
0

6
1 3 4 10 12 15
0

6
12 15 19 21 23 24
0
--endl--

小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千册

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值