C++ 标准模板库 STL(3)栈和队列

一、栈和队列的行为特征

        栈和队列与数组类似,但对于插入、访问、删除都有一定的限制。可将元素插入到什么位置或从什么位置删除决定了容器的行为特征。

1.1 栈

        栈是LIFO(后入先出)的容器,只能从栈顶插入或删除元素。可以将栈视为一叠盘子,最后放上去的盘子将最先被取下来。在C++中泛型STL容器std::stack模拟了栈的这种行为,需要包含如下头文件。

#include <stack>

1.2 队列

        队列是FIFO(先入先出)的容器,元素被插入到队尾,最先插入的元素最先删除。可将队列视为食堂窗口买饭的人,在没有插队的情况下,先加入队列的人先离开。要在C++中创建和使用队列容器需要包含如下头文件。

#include <queue>

二、使用STL stack类

        STL stack是一个模板类,允许在顶部插入和删除元素。

2.1 实例化

        std::stack的定义如下:

template<
    class elementType,
    class Container=deque<Type>
> class stack;

        参数elementType是stack存储的对象类型,第二个参数Container是stack使用的默认底层容器实现类。stack默认使用std::deque来存储数据,但可以指定使用vector或list来存储数据。实例化栈的代码类似于下面这样:

// 默认实例化整型栈
std::stack<int> stk;

// 创建自定义类对象的栈
std::stack<MyClass> stk;

// 创建不同底层容器的栈
std::stack<double, vector<double>> stk;

2.2 成员函数

        stack改变了另一种容器(如deque、list、vector)的行为,通过限制元素插入或删除的方式实现其功能。下表解释了stack的公有成员函数并演示了如何将这些函数用于整型栈。

std::stack的成员函数
函数描述
push()在栈顶插入元素,例如stk.push(25);
pop()删除栈顶的元素,例如stk.pop();
empty()检查栈是否为空并返回bool类型,例如bool res = stk.empty();
size()返回栈中的元素个数,例如int num = stk.size();
top()获取指向栈顶元素的引用,例如int n = stk.top();

三、使用STL queue类

        queue是一个泛型类,只允许在末尾插入元素,从开头删除元素。queue不允许访问中间的元素,但可以访问开头和末尾的元素。

3.1 实例化

        std::queue的定义如下:

template<
    class elementType,
    class Container=deque<Type>
> class queue;

        其中elementType是queue对象包含的元素的类型。Container是std::queue用于存储其数据的集合类型,可以将该模板参数设置为list、vector、deque。默认为deque。

        实例化queue的方式如下:

// 最基础的实例化
std::queue<int> que;

// 修改容器类型
std::queue<double, list<double>> dQue;

// 使用现有的queue来实例化新的queue
std::queue<int> copyQue(que);

3.2 成员函数

        std::queue的实现也是基于STL容器vector、list、deque的。其成员函数如下表所示:

std::queue的成员函数
函数描述
push()在队尾(即最后一个位置)插入一个元素。
pop()将队首(即最开始位置)的元素删除。
front()返回指向队首元素的引用。
back()返回指向队尾元素(即最后插入的元素)的引用。
empty()检查队列是否为空并返回一个bool类型。
size()返回队列中的元素数。

        值得注意的是,queue并没有提供begin()和end()等函数,这是有意为之的,旨在只允许对queue执行符合队列行为特征的操作。

四、使用STL优先级队列

        priority_queue与queue的不同之处在于,包含最大值(或二元谓词认为是最大值)的元素位于队首,且只能在队首执行操作。

4.1 实例化

        std::priority_queue类的定义如下:

template<
    class elementType,
    class Container=vector<Type>,
    class Compare=less<typename Container::value_type>
> class priority_queue;

        其中elementType是一个模板参数,指定了优先级队列将包含的元素的类型。第二个模板参数指定priority_queue在内部将使用哪个集合类来存储数据。第三个参数能够指定一个二元谓词,以帮助队列判断哪个元素应位于队首。如果没有指定二元谓词,priority_queue类将默认使用二元谓词std::less进行排序(新插入节点小于父节点),这将创建出大顶堆,即父节点比子节点大,而使用std::greater(新插入节点大于父节点)将创建小顶堆,即父节点比子节点小。

        实例化priority_queue可采用如下方式:

// 默认创建大顶堆
std::priority_queue<int> pq1;

// 创建小顶堆
std::priority_queue<int, deque<int>, greater<int>> pq2;

// 拷贝
std::priority_queue<int> copyQ(pq1);

4.2 成员函数

        queue提供了成员函数front()和back(),但priority_queue并没有。下表展示了priority_queue的成员函数与其功能。

std::priority_queue的成员函数
函数描述
push()在优先级队列中插入一个元素。
pop()删除队首的元素,默认为最大元素。
top()返回指向队列中队首元素的引用。
empty()检查优先级队列是否为空并返回一个bool类型。
size()返回优先级队列中的元素个数。

4.3 具体应用

题目描述:给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入: [3,2,1,5,6,4], k = 2 
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

        题目要求时间复杂度为 O(n) ,因此可以尝试使用priority_queue构建大顶堆实现堆排序选择出第 k 个最大的元素。代码如下所示:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // 构建大顶堆
        priority_queue<int, vector<int>, less<int>> pq;

        // 向大顶堆中添加元素
        for(int i=0; i<nums.size(); i++) {
            pq.push(nums[i]);
        }

        // 将前k-1个元素出队
        for(int i=0; i<k-1; i++) {
            pq.pop();
        }

        // 返回堆顶的元素
        return pq.top();
    }
};

        测试提交后所有测试用例均可通过。

  • 49
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值