C++常用数据结构---------------队列

队列:

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

STL中的方法使用:

1.back() 返回一个引用,指向最后一个元素
2.empty() 如果队列空则返回真
3.front() 返回第一个元素
4.pop() 删除第一个元素
5.push() 在末尾加入一个元素
6.size() 返回队列中元素的个数

队列的特点:先进先出。

常用场景:广度优先搜索

队列中有两个值,一个是front去记录队头的位置,另一个是rear去记录队尾的位置。

在实际应用时,由于数组队列的缺点是由于一端插入一端删除,当不断从头部删除数据,头部会大量留有空闲内存,无法插入,造成空间流失,这种属于假溢出的情况。但如果将队头指针在每次删除之后往前移动一个位置,这是一个时间复杂度为O(n)的操作。因此,通常将队列设计为循环队列来克服上述问题。

循环队列可以看作是一个环形结构。有一个maxsize表示数组的长度。当队列未满,并且队头已经到达了maxsize的位置,再次插入数据的时候,队头则从0位置开始插入。

在设计的时候,一般要注意以下几点:

(1)队列初始化时,front和rear值都为零。

(2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置。

(3)当队列为空时,front与rear的值相等,但不一定为零。

循环队列满的时候会满足这个计算公式  : (rear+1)%maxsize=front

计算循环队列长度 :  (rear-front+maxsize)%maxsize
 

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>

using namespace std;

int main()
{
    queue<int> my_q;

    //加入一个元素
    my_q.push(1);
    my_q.push(2);
    my_q.push(3);

    //返回一个引用,指向最后一个元素
    cout<<my_q.back()<<endl;

    //返回第一个元素
    cout<<my_q.front()<<endl;

    //删除第一个元素
    my_q.pop();
    
    return 0;
}

 

 

优先队列:

常用场景:取出前K大的数据

一、相关定义

优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。

二、基本操作

和队列基本操作相同:

  • top 访问队头元素
  • empty 队列是否为空
  • size 返回队列内元素个数
  • push 插入元素到队尾 (并排序)
  • emplace 原地构造一个元素并插入队列
  • pop 弹出队头元素
  • swap 交换内容

示例代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>
#include<functional>  //很关键,不然小顶堆会报错

using namespace std;

//自定义优先级方式
struct cmp{
    bool operator ()(int x, int y)
    {
        return x > y; // x小的优先级高
    }
};

int main()
{
    //等同于 priority_queue<int, vector<int>, less<int> > my_pq;
    priority_queue<int> my_pq;     //默认是大顶堆

    //priority_queue<int, vector<int>,cmp> my_pq; //自定义优先级方式
    //小顶堆
    //priority_queue<int, vector<int>, greater<int> > my_pq;

    my_pq.push(1);
    my_pq.push(2);
    my_pq.push(3);
    my_pq.push(4);
    my_pq.push(5);
    my_pq.push(6);
    my_pq.push(7);

    my_pq.pop();
    //剩下三个元素就无法像下面这种方法访问了,所以一般访问第一个元素
    for (int i = 0; i < my_pq.size(); ++i) {
        cout<<my_pq.top()<<endl;
        //删除第一个元素(排序好后的)
        my_pq.pop();
    }
    cout<<my_pq.size()<<endl;

//这样才能正常输出全部数据
//    while (my_pq.size()){
//        cout<<my_pq.top()<<endl;
//        //删除第一个元素(排序好后的)
//        my_pq.pop();
//    }

    return 0;
}

 

双端队列:

常用场景:实现一个长度动态变化的窗口或者连续区间

deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。deque类常用的函数如下。

(1)    构造函数

deque():创建一个空deque

deque(int nSize):创建一个deque,元素个数为nSize

deque(int nSize,const T& t):创建一个deque,元素个数为nSize,且值均为t

deque(const deque &):复制构造函数

(2)    增加函数

void push_front(const T& x):双端队列头部增加一个元素X

void push_back(const T& x):双端队列尾部增加一个元素x

iterator insert(iterator it,const T& x):双端队列中某一元素前增加一个元素x

void insert(iterator it,int n,const T& x):双端队列中某一元素前增加n个相同的元素x

void insert(iterator it,const_iterator first,const_iteratorlast):双端队列中某一元素前插入另一个相同类型向量的[forst,last)间的数据

(3)    删除函数

Iterator erase(iterator it):删除双端队列中的某一个元素

Iterator erase(iterator first,iterator last):删除双端队列中[first,last)中的元素

void pop_front():删除双端队列中最前一个元素

void pop_back():删除双端队列中最后一个元素

void clear():清空双端队列中最后一个元素

(4)    遍历函数

reference at(int pos):返回pos位置元素的引用

reference front():返回手元素的引用

reference back():返回尾元素的引用

iterator begin():返回向量头指针,指向第一个元素

iterator end():返回指向向量中最后一个元素下一个元素的指针(不包含在向量中)

reverse_iterator rbegin():反向迭代器,指向最后一个元素

reverse_iterator rend():反向迭代器,指向第一个元素的前一个元素

(5)    判断函数

bool empty() const:向量是否为空,若true,则向量中无元素

(6)    大小函数

Int size() const:返回向量中元素的个数

int max_size() const:返回最大可允许的双端对了元素数量值

(7)    其他函数

void swap(deque&):交换两个同类型向量的数据

void assign(int n,const T& x):向量中第n个元素的值设置为x

 

示例代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <list>
#include <unordered_map>
#include <cstring>

using namespace std;

int main()
{
    deque<int> my_dq;

    my_dq.push_back(1);
    my_dq.push_back(2);
    my_dq.push_back(3);
    my_dq.push_back(4);
    my_dq.push_back(5);

    //删除2
    my_dq.erase(my_dq.begin()+1);

    while (!my_dq.empty())
    {
        cout<<my_dq.front()<<endl;
        my_dq.pop_front();
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值