【C++数据结构与算法】队列

C++队列

队列:queue

API: C++ queue

队列是一种FIFO(先进先出)的数据结构

头文件:# include<queue>

定义一个队列:queue<T> queueName; ,和stack一样,队列也可以包含pair元素

queue<char, list<char>> q1;
queue<int, deque<int>> q2;

基本函数

函数名作用
front()访问第一个元素
back()访问最后一个元素
empty()检查容器是否为空
size()返回元素数
push()尾端插入元素
emplace()【C++11】在尾部原位构造元素(比起push省了复制操作)
pop()移除首位元素
swap()【C++11】交换内容,交换a、b两个队列容器中的内容

经典例题

双端队列:deque

API: C++ deque

std::deque 是有索引的序列容器,允许在首尾两端快速插入和删除元素。(任意端的插入删除操作不会使指向其他元素的指针(or 引用)失效)

特性:①非连续存储 ②索引访问必须进行二次指针解引用 ③存储按需自动扩张&收缩 ④拥有较大的最小内存开销(只保有一个元素的 deque 必须分配它的整个内部数组)

存储方式:典型实现采用一系列单独分配的固定尺寸数组,外加额外的簿记数据

常见操作复杂度:

  • 随机访问——常数 O(1)
  • 在结尾或起始插入或移除元素——常数 O(1)
  • 插入或移除元素——线性 O(n)

成员类型

待补充,在实战中学习

基础函数

带*为C++11新特性

访问与赋值
函数作用失效
assign()将值赋给容器【详见
at()带越界检查访问指定索引的元素
front()访问第一个元素
back()访问最后一个元素
begin()
*cbegin()
返回指向起始的迭代器
end()
*cend()
返回指向末尾的迭代器
rbegin()
*crbegin()
返回指向起始的逆向迭代器
rend()
*crend()
返回指向末尾的逆向迭代器
容量
函数作用
empty()判空
size()返回元素数
max_size()返回可容纳的最大元素数
shrink_to_fit()释放未使用的内存,减少内存的使用
修改器
函数作用失效
clear()清除内容
insert()插入元素详见
*emplace()原位构造元素(pos, &&args)
erase()擦除元素(参数为迭代器(pos) OR 迭代器begin和end)
push_back()尾端添加元素
*emplace_back()尾端原位构造元素
pop_back()移除尾端元素
push_front()在首端添加元素
*emplace_front()首端原位构造元素
resize()改变存储元素的个数详见
swap()交换内容
详细说明:assign()

使用方式

std::deque<char> characters;

// 用法1
void assign(size_type count, const T& value);
characters.assign(5, 'a');  // 容器:a a a a a

// 用法2
void assign( InputIt first, InputIt last );
const std::string extra(6, 'b');
characters.assign(extra.begin(), extra.end()); //容器:bbbbbb

// 用法3
void assign( std::initializer_list<T> ilist ); // C++11新特性
characters.assign({'C', '+', '+', '1', '1'});  // 容器:C++11
  1. 用count个value副本替换容器中的内容
  2. 以[first, last)中的元素替换(其中有任一实参是指向*this中的迭代器时行为未定义)
  3. 以来自ilist 的元素替换内容。
详细说明:insert()
// 用法1
iterator insert( const_iterator pos, const T& value );
iterator insert( const_iterator pos, T&& value ); //C++11 起

// 用法3
iterator insert( const_iterator pos, size_type count, const T& value );

// 用法4
iterator insert( const_iterator pos, InputIt first, InputIt last );

// 用法5 C++11起
iterator insert( const_iterator pos, initializer_list<T> ilist );
  • 用法1、2:在pos前插入value
  • 用法3:在pos前插入value个count副本
  • 用法4:在 pos 前插入来自范围 [first, last) 的元素。
  • 用法5:在pos前插入ilist元素
详细介绍:resize()

重设容器大小以容纳count个元素

void resize( size_type count );
void resize( size_type count, const value_type& value );

如果deque.size() > count:减少容器到它的前count个元素

如果deque.size() <= count:①追加额外的默认插入元素②追加额外的value的副本

双端例题:LC103 二叉树的锯齿形层序遍历

题目

返回Z字型顺序下,树的节点值数组(层层遍历,从左往右,从右往左,交替)

每层存一个数组,最后返回元素是数组的数组

解答:

class Solution
{
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode *root)
    {
        if (!root)
        {
            return {};
        }
        // 使用双端队列
        deque<TreeNode *> treeq;
        treeq.push_back(root);
        // 判断当前,队列从头pop还是从尾pop
        bool lTor = true;
        vector<vector<int>> answer;
        while (!treeq.empty())
        {
            deque<TreeNode *> temp = treeq;
            treeq.clear();
            // 遍历当前层级
            TreeNode *curnode;
            // 层级节点值
            vector<int> levelVec = {};
            while (!temp.empty())
            {
                // 从左至右出,从头出
                // 子节点从尾端进入,按前序遍历
                if (lTor)
                {
                    curnode = temp.front();
                    temp.pop_front();
                    levelVec.push_back(curnode->val);
                    if (curnode->left)
                        treeq.push_back(curnode->left);
                    if (curnode->right)
                        treeq.push_back(curnode->right);
                }
                else
                {
                    // 从右至左,从尾出
                    // 子节点从首端进入,后序遍历
                    curnode = temp.back();
                    temp.pop_back();
                    levelVec.push_back(curnode->val);
                    if (curnode->right)
                        treeq.push_front(curnode->right);
                    if (curnode->left)
                        treeq.push_front(curnode->left);
                }
            }
            lTor = !lTor;
            answer.push_back(levelVec);
        }
        return answer;
    }
};

优先队列:priority_queue

头文件:<queue>

初始化与定义

// elemtype为队列中元素的类型
// what_vector为,存储元素的底层容器是什么
// class_type是一个类,用于比价
std::priority_queue<elem_type, what_vector, class_type> pq;

// 创建一个大根堆,默认情况下
std::priority_queue<int> max_heap; 
// 创建一个小根堆
std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap; 

// 自定义比较器
struct compare{
    // 需要重载()运算符
    bool operator()(int a, int b){
        return a > b;
    }
};

std::priority_queue<int, std::vector<int>, compare> custom_min_heap;

成员函数

  • pop()
  • push()
  • top()
  • front()

【关于优先队列的比较器】

我们可以把堆想象成一个水平横向的会场,最右端为入口(即top)

更尊贵的客人更深入会场,即更靠近会场左端。

而更为尊贵的客人,是在比较器中获得true的那一位。

所以,less重载了operator<,我们获取的却是大根堆,因为更小的元素往里走了。

参考文章

例题:LC264 丑数 II(使用优先队列实现小根堆)

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值