当前位置: 首页 > news >正文

queue和priority_queue及其函数

 

目录

queue和priority_queue

priority_queue和queue的差别

queue

queue的成员函数

queue成员函数目录

front()

back()

push()

pop()

size()

swap()

emplace()

empty()

priority_queue

priority_queue的成员函数

priority_queue的成员函数目录

priority_queue的优先级设定

priority_queue的完整格式

优先级的自定义


queue和priority_queue

    queue称为队列,而priority_queue称为优先级队列,两者除了基础功能相同且都遵循先进先出的规则外,两个对队列内元素处理方式不同

    两个队列的使用都需要头文件queue 


priority_queue和queue的差别

( 此处为引子,相关知识请查看本文章的相关知识点 )

代码演示

#include <iostream>
#include <queue>
using namespace std;
void Print1(priority_queue<int> t)
{while (!t.empty()){cout << t.top() << " ";t.pop();}cout << endl;
}
void Print2(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}
int main()
{cout << "两个都按顺序插入5,1,10,2" << endl;//设置一个队列queue<int> q2;//插入操作q2.push(5);q2.push(1);q2.push(10);q2.push(2);cout << "queue:";//上方写的打印函数Print2(q2);//设置一个优先队列priority_queue<int> q1;q1.push(5);q1.push(1);q1.push(10);q1.push(2);cout << "priority_queue:";Print1(q1);return 0;
}

运行结果:

    可以看到,即使插入的元素以及顺序相同·,输出的元素顺序却不同,这就是优先级队列和队列的差别,优先级队列按照设定的优先级进行比较排序,而队列则不做处理



queue

    queue名为队列,队列是一种容器适配器,专门设计用于在 FIFO (先进先出)中运行,其中元素插入到容器的一端并从另一端提取( 一端入,一端出 )
    队列作为容器适配器实现,这些适配器是使用特定容器类的封装对象作为其基础容器的类,提供一组特定的成员函数来访问其元素。元素被推入特定容器的 “back”(队列尾) 并从其 “front” (队列头)弹出。

队列的图示

 


补充知识(queue所有元素的打印)

     队列无法像其他容器和数组一样直接访问中间任意下标的元素,只能访问到队列的头元素和队列的尾元素( 因为没有at函数和重载运算符 [ ] ,只有 front 和 back 函数访问头和尾 )

    所以想要访问,就需要不断出队(移除队头元素)来对队头元素进行访问

代码演示:

#include <iostream>
#include <queue>
using namespace std;
int main()
{queue<int> q;//push为入队,在队尾加入一个元素q.push(1);q.push(2);q.push(3);//当前队列里有1,2,3这3个元素while (!q.empty())//判断是否为空{//开始对队头的元素进行打印cout << q.front() << " ";//pop为出队,移除第一个元素q.pop();}cout << endl;//我们可以测试队列是否为空//结果判断为空cout << "当前q是否为空:" << q.empty() << endl;return 0;
}

 

     当然,上方代码存在问题,即为访问队列需要出队,这就导致了每次打印都会让队列清空,此时我们可以设置其为一个函数,并且通过拷贝的方式传给其函数,通过拷贝出来的队列进行出队打印操作将不会影响原队列

代码演示:

#include <iostream>
#include <queue>
using namespace std;void Print(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}int main()
{queue<int> q;q.push(1);q.push(2);q.push(3);//当前队列里有1,2,3这3个元素//调用写好的打印函数Print(q);//判断为当前队列不为空cout << "当前q是否为空:" << q.empty() << endl;return 0;
}

 

     可以看到,打印后我们判断原队列是否为空是给出了0,到此我们解决了队列元素的打印问题


queue的成员函数

queue成员函数目录

  • front():访问队列中的第一个元素
  • back():访问队列中的最后一个元素
  • push():在队列尾部插入新元素
  • pop():删除队列的队头元素
  • size():返回队列的大小
  • swap():将容器适配器中的内容进行交换
  • emplace():在队列尾添加新元素
  • empty():判断队列是否为空

front()

  front()函数的作用:访问队列中的第一个元素

front()函数的格式

  • value_type& front();
  • const value_type& front() const;

front()的代码演示将和下面的back()代码演示一起


back()

  back()函数的作用:访问队列最后一个元素

back()函数的格式

  • value_type& back();
  • const value_type& back() const;

代码演示

#include <iostream>
#include <queue>
using namespace std;void Print(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}int main()
{queue<int> q;q.push(10);q.push(55);q.push(75);cout << "原队列:";Print(q);//可对其进行访问cout << "front():" << q.front() << endl;cout << "back():" << q.back() << endl;//也可对其进行修改q.back() -= q.front();Print(q);return 0;
}

运行结果:


push()

  push()函数的作用:在队列尾部插入新元素

push()函数的格式

  • void push (const value_type& val);

代码演示

#include <iostream>
#include <queue>
using namespace std;void Print(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}int main()
{queue<int> q;q.push(1); Print(q);q.push(2); Print(q);q.push(3);Print(q);return 0;
}

运行结果图


pop()

  pop()函数的作用:删除队列的队头元素

pop()函数的格式

  • void pop();

代码演示

#include <iostream>
#include <queue>
using namespace std;void Print(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}int main()
{queue<int> q;q.push(1); q.push(2); q.push(3);cout << "原队列:";Print(q);q.pop();cout << "pop操作后的队列:";Print(q);q.pop();cout << "pop操作后的队列:";Print(q);return 0;
}

运行结果图


size()

  size()函数的作用:返回队列的大小

size()函数的格式

  • size_type size() const;

代码演示


swap()

  swap()函数的作用:将容器适配器中的内容进行交换

swap()函数的格式:

  • void swap (queue& x) noexcept(/*see below*/);

代码演示

#include <iostream>
#include <queue>
using namespace std;void Print(queue<int> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}int main()
{queue<int> q1, q2;q1.push(10); q1.push(20); q1.push(30);q2.push(1); q2.push(2);cout << "原q1元素:";Print(q1);cout << "原q2元素:";Print(q2);q1.swap(q2);cout << "改后q1元素:";Print(q1);cout << "改后q2元素:";Print(q2);return 0;
}

运行结果图


emplace()

  emplace()函数作用:在队列尾添加新元素( 和push一样 )

emplace()函数的格式:

  • template <class... Args> void emplace (Args&&... args);

代码演示

#include <iostream>
#include <queue>
using namespace std;void Print(queue<string> t)
{while (!t.empty()){cout << t.front() << " ";t.pop();}cout << endl;
}
int main()
{queue<string> q;q.emplace("First");q.emplace("Second");q.push("Three");cout << "队列有:";Print(q);cout << "队列大小有:" << q.size() << endl;return 0;
}

运行结果图: 

    可以看到,emplace 和 push 的插入都是一样的


empty()

  empty()函数作用:判断队列是否为空

empty()函数的格式:

  • bool empty() const;

代码演示

  可以看到,我们在设置一个空队列后直接对其进行empty返回的是1,证明其为空队列

  随后我们插入元素后进行empty返回的是0,证明其已经不为空



priority_queue

    priority_queue称为优先级队列,优先级队列是一种容器适配器,专门设计使其第一个元素始终是它包含的元素中最大的,根据一些严格的弱排序标准

    其是一个特殊的队列,类似于堆的队列,其的特殊在于用堆的特性,对队列进行自动排序


priority_queue的成员函数

priority_queue的成员函数目录

  • top():返回队列头元素
  • push():在队列尾部插入新元素
  • pop():删除队列的队头元素
  • size():返回队列的大小
  • swap():将容器适配器中的内容进行交换
  • emplace():在队列尾添加新元素
  • empty():判断队列是否为空

    priority_queue的所有函数都与普通的queue函数用法相同,只是priority_queue访问队头元素的函数改成了 top() 函数,所以不做演示

    需要注意的是,priority_queue没有类似 back() 的函数,所以无法访问队列尾的元素


priority_queue的优先级设定

    开头priority_queue和queue的差别时提到的priority_queue的优先级设定,这个设定决定了优先队列的排序方式,其默认为大堆(即从大到小),而我们也可以改变这个优先级的设定,让其按照需求进行排序

priority_queue的完整格式

priority_queue<int,vector<int>,less<int> >q;
  • 第一个参数(int)为传入数据的类型
  • 第二个参数(vector<int>)为存放的容器(需要存放在什么容器里,默认为vector)
  • 第三个参数(less<int>)为优先级的设定(默认为less<int>(大堆,大到小),还有一个已经写好的设定为greater<int>(小堆,小到大),此外还可以自己设定优先级)

    先来看下方案例,通过修改优先级,其排序的规则也进行了改变,输出结果也变得不同


优先级的自定义

    相信你可能有疑问,明明已经给了大堆和小堆优先级的规则设定可以进行替换,为何还要自己写优先级的设定呢?

    答案是当我们自定义类型且有多个参数在这类型中时,原先给的规则将不再适用

    就如我们设定一个包含两个参数的自定义类型,一个表示年龄,一个表示编号,此时原先的队列规则就不知道比较年龄来排序还是比较编号排序

   所以我们就需要自定义优先级的规则来给优先级队列进行排序

优先级定义样例

//定义一个自定义类型node
struct node
{int x, y;//运算符重载,改变其比较大小的规则bool operator<(const node& b)const {return this->x > b.x;}
};

  代码解释:

  • bool operator<(const node& b)const 就是优先级规则的定义,可通过重载运算符的方式,来比较返回所需要比较的参数
  • const node& b 中的 b 只是引用,可随意修改
  • b 可修改之外bool operator<(const node& b)const 不作修改
  • return 中间对比用的对比符可以改变,其就是决定大堆和小堆的关键因素 
  • this 为隐藏的指针

    运算符重载后就自动调用相关的优先级规则,就像下方,只需要定义相关类型的队列时便开始调用,不需要替换掉原先的规则

代码运行图(完整代码在最下方):

  下面为小堆的排序,此时返回为 this->x > b.x

 

    上面优先级定义样例时说了,return的对比符可以改变,下面代码就改变了对比符,改变为了大堆,此时返回为 this->x < b.x

 

补充知识:

    运算符重载还可以定义在自定义类型外,只是定义在自定义类型外时,没有了隐藏的this指针,需要主动上传两个参数,如下方代码

//定义一个自定义类型node
struct node
{int x, y;
};
bool operator<(const node& a, const node& b){return a.x < b.x;
}

 

完整代码:

#include <iostream>
#include <queue>
using namespace std;//定义一个自定义类型node
struct node
{int x, y;//运算符重载,改变其比较大小的规则//在自定义类型里进行重载bool operator<(const node& b)const {return this->x < b.x;}
};//在自定义类型外进行重载
//bool operator<(const node& a, const node& b) {
//    return a.x < b.x;
//}//打印x
void Print1(priority_queue<node> t)
{while (!t.empty()){cout << t.top().x << " ";t.pop();}cout << endl;
}
//打印y
void Print2(priority_queue<node> t)
{while (!t.empty()){cout << t.top().y << " ";t.pop();}cout << endl;
}
int main()
{priority_queue<node> q;//自定义类型的输入//可以是//q.push({ x, y });//也可以是//node temp;//temp.x=1;temp.y=10;//q.push(temp);q.push({ 1, 10 });q.push({ 3, 20 });q.push({ 2, 30 });q.push({ 8, 50 });q.push({ 5, 15 });cout << "原先输入q的x值顺序为:1 3 2 8 5" << endl;cout << "原先输入q的y值顺序为:10 20 30 50 15" << endl;cout << "q的x值:";Print1(q);//打印xcout << "q的y值:";Print2(q);//打印yreturn 0;
}

 到此,我们今天的学习就结束了,感谢观看

\\\\٩( 'ω' )و ////

相关文章:

  • 【438. 找到字符串中所有字母异位词】
  • Python训练营---Day34
  • 【昇腾开发者训练营:Dify大模型部署实战】MindIE + Dify + DeepSeek + Embedding模型 + Rerank模型
  • springboot集成日志配置文件
  • 信息学奥赛及各种程序设计竞赛中常见的名词解释
  • 通过contenteditable实现仿豆包智能输入框
  • 生成模型——PixelRNN与PixelCNN
  • 常见算法题目2 - 给定一个字符串,找出其中最长的不重复子串
  • MySQL慢日志——动态开启
  • (15)关于窗体的右键菜单的学习与使用,这关系到了信号与事件 event
  • 《C 语言内存函数超详细讲解:从 memcpy 到 memcmp 的原理与实战》
  • vue——v-pre的使用
  • 安装openEuler操作系统
  • 强者的本质是什么?
  • Leetcode 2792. 计算足够大的节点数
  • mysql语句执行流程
  • Femap许可证升级说明
  • LTSPICE仿真电路:(二十九)T型反馈比例器
  • VirtualBox 4.3.10 经典版安装教程 - Windows 7/10 下载与设置指南
  • ASUS华硕ROG枪神9P笔记本G815LP(G615LW,G635LR,G835LX)原装出厂Win11系统,开箱状态oem系统
  • 大学生想做网站/教育培训机构报名
  • 国内设计欣赏网站/百度天眼查公司
  • 桥东企业做网站/信息流广告文案
  • 简述建设网站建设的基本流程/网络营销课程
  • 做网站有意思吗?/关于搜索引擎的搜索技巧
  • 网站描本链接怎么做/大连网站搜索排名