【十九】【C++】 priority_queue简单使用和仿函数

priority_queue文档介绍翻译

优先队列是一种容器适配器,专门设计成其中的第一个元素始终是根据某种严格的弱排序准则最大的元素。

这种上下文类似于堆,其中元素可以在任何时刻插入,而只能检索最大堆元素(在优先队列中顶部的元素)。

优先队列被实现为容器适配器,这些适配器是使用特定容器类的封装对象作为其底层容器的类,提供一组特定的成员函数来访问其元素。元素从特定容器的“后面”弹出,这被称为优先队列的顶部。

底层容器可以是任何标准容器类模板或其他特定设计的容器类。容器必须通过随机访问迭代器进行访问,并支持以下操作:

  • empty()

  • size()

  • front()

  • push_back()

  • pop_back()

标准容器类vectordeque满足这些要求。默认情况下,如果没有为特定优先队列类实例化指定容器类,则使用标准容器vector

需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器会在需要时自动调用算法函数make_heappush_heappop_heap来完成这一点。

简单使用

优先队列(Priority Queue)是一种特殊的队列,它的出队顺序是按照元素的优先级决定的,而不是元素进入队列的先后顺序。在C++中,优先队列通常通过STL中的priority_queue容器来实现。priority_queue<queue>头文件中定义,它可以让你轻松地实现一个能够根据元素优先级进行动态排序的队列。

基本操作

插入元素(push):将一个元素添加到优先队列中。

获取顶部元素(top):返回优先级最高的元素,但不从队列中移除它。

删除顶部元素(pop):移除优先级最高的元素。

检查队列是否为空(empty):检查优先队列是否没有任何元素。

获取队列的大小(size):返回优先队列中的元素数量。

示例代码

下面是一个使用priority_queue的基本示例:

 
#include <iostream>
#include <queue>int main() {// 创建一个int类型的优先队列,默认是最大堆std::priority_queue<int> pq;// 插入元素pq.push(30);pq.push(10);pq.push(20);pq.push(5);// 循环直到优先队列为空while (!pq.empty()) {// 打印顶部元素std::cout << pq.top() << " ";// 移除顶部元素pq.pop();}return 0;
}

最小堆优先队列

默认情况下,C++的priority_queue使用std::less<T>作为比较函数,这意味着它将实现为一个最大堆,优先级最高的(值最大的)元素会被放在队列的前面。

如果你想创建一个最小堆,使得优先级最低的元素先出队,你可以通过传递一个比较函数来实现。例如:

 
#include <iostream>
#include <queue>
#include <vector>
#include <functional>int main() {// 创建一个最小堆优先队列std::priority_queue<int, std::vector<int>, std::greater<int>> pq;pq.push(30);pq.push(10);pq.push(20);pq.push(5);while (!pq.empty()) {std::cout << pq.top() << " ";pq.pop();}return 0;
}

优先队列默认创建最大堆

 
/*优先队列默认创建大堆*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;void TestPriorityQueue1(){// 默认按照less方式比较,创建的是大堆priority_queue<int> q;q.push(5);q.push(4);q.push(8);q.push(1);q.push(9);q.push(2);q.push(6);q.push(3);q.push(7);q.push(0);cout << q.size() << endl;cout << q.top() << endl;q.pop();q.pop();q.pop();cout << q.size() << endl;cout << q.top() << endl;}int main(){TestPriorityQueue1();}#endif

优先队列主动创建最小堆

 
/*优先队列默认创建最小堆*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
// greater是STL提供的以大于方式比较两个元素的类模板// 在使用时一定要<functional>的头文件
void TestPriorityQueue2(){// 如果要创建小堆,则元素必须按照大于的方式比较priority_queue<int,vector<int>, greater<int>> q;q.push(5);q.push(4);q.push(8);q.push(1);q.push(9);q.push(2);q.push(6);q.push(3);q.push(7);q.push(0);cout << q.size() << endl;cout << q.top() << endl;q.pop();q.pop();q.pop();cout << q.size() << endl;cout << q.top() << endl;}int main(){TestPriorityQueue2();}#endif

优先队列日期类创建最大堆

 
/*优先队列日期类最大堆*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return _day < d._day;}bool operator>(const Date& d)const{return _day > d._day;}void Show()const{cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}private:int _year;int _month;int _day;};void TestPriorityQueue3(){priority_queue<Date> q;Date d1(2023, 4, 22);Date d2(2023, 4, 21);Date d3(2023, 4, 23);q.push(d1);q.push(d2);q.push(d3);while (!q.empty()) {q.top().Show();q.pop();}}int main(){TestPriorityQueue3();}#endif

优先队列范围迭代器创建对象

 
/*优先队列范围迭代器创建对象*/
#if 1#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;void TestPriorityQueue5(){vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };priority_queue<int> q(v.begin(), v.end());}
int main(){TestPriorityQueue5();}#endif

优先队列日期类创建最小堆

 
/*优先队列日期类创建最小堆*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return _day < d._day;}bool operator>(const Date& d)const{return _day > d._day;}void Show()const{cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}private:int _year;int _month;int _day;};void TestPriorityQueue4(){priority_queue<Date, vector<Date>, greater<Date>> q;Date d1(2023, 4, 22);Date d2(2023, 4, 21);Date d3(2023, 4, 23);q.push(d1);q.push(d2);q.push(d3);while (!q.empty()) {q.top().Show();q.pop();}}
int main(){TestPriorityQueue4();}#endif

自定义判断函数,函数指针

 
/*自定义判断函数,函数指针*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return _day < d._day;}bool operator>(const Date& d)const{return _day > d._day;}void Show()const{cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}friend bool CompareDate(const Date* left, const Date* right);friend class Compare;
private:int _year;int _month;int _day;};bool CompareDate(const Date* left, const Date* right){return left->_day < right->_day;}typedef bool (*COM)(const Date* left, const Date* right);void TestPriorityQueue6(){priority_queue<Date*, vector<Date*>, COM> q(CompareDate);Date d1(2023, 4, 22);Date d2(2023, 4, 21);Date d3(2023, 4, 23);q.push(&d1);q.push(&d2);q.push(&d3);while (!q.empty()) {Date* top = q.top(); // 获取优先队列顶部元素top->Show();         // 显示日期q.pop();             // 移除顶部元素}}int main(){TestPriorityQueue6();}

typedef bool (*COM)(const Date* left, const Date* right);

这行代码定义了一个函数指针类型COM,用于指向一个特定的函数签名。这个签名要求函数接受两个指向Date对象的常量指针作为参数,并返回一个bool类型的结果。在这个上下文中,这样的函数通常用于比较两个Date对象,并根据比较结果(真或假)来排序或做出决策。

具体来说,typedef关键字在C++中用于为现有的类型定义一个新的名称。在这个例子中,它定义了COM作为一种新的类型,这种类型是指向函数的指针,这些函数具有特定的参数列表和返回类型:

  • 参数列表:两个const Date*类型的参数,表示指向常量Date对象的指针。使用指针允许函数不改变原始对象的状态,同时使用const确保函数内部不会修改这些对象。

  • 返回类型:bool,用于表示比较的结果。在排序或其他需要比较的场景中,返回值通常用于指示第一个参数是否在排序顺序上位于第二个参数之前。

priority_queue<Date*, vector<Date*>, COM> q(CompareDate);

这行代码创建了一个 std::priority_queue,其中包含了指向 Date 对象的指针。在这个 priority_queue 的声明中,使用了三个模板参数:

  • 元素类型:Date*,表示队列中存储的元素是指向 Date 对象的指针。

  • 底层容器:std::vector<Date*>,表示优先队列使用 std::vector 来存储这些指针。std::vector 是一个动态数组,适用于几乎所有类型的容器操作,而且在这里特别适合作为优先队列的底层数据结构。

  • 比较类型:COM,这是一个指向函数的指针类型,用于比较两个 Date 对象。在这个上下文中,COM 是通过之前定义的 typedef 创建的,指向一个接受两个 const Date* 类型参数的函数,并返回一个 bool 类型的结果。

接下来的部分 q(CompareDate);priority_queue构造函数调用,它接受一个名为 CompareDate 的函数作为参数。这个函数符合 COM 类型的要求,用于确定队列中元素的优先顺序。在这个例子中,CompareDate 函数基于日期对象的 _day 字段来比较日期,以决定它们在队列中的顺序。

这种方式允许自定义优先队列的排序准则,而不是仅依赖于元素类型的默认比较操作(例如,如果是基本类型或具有定义了 < 运算符的类型)。通过提供自定义比较函数,用户可以控制哪些元素应该被视为优先级更高,这在处理复杂数据类型或有特定排序需求的场合特别有用。

仿函数

在C++中,仿函数(Function Object或Functor)是一个行为类似函数的对象。具体来说,仿函数是通过重载 operator() 运算符的类实例,这让类的实例可以像函数一样被调用。仿函数提供了比普通函数指针更多的灵活性和功能,因为它们可以拥有自己的状态。

仿函数的优点

状态保持:与普通函数不同,仿函数可以有自己的状态。你可以在多次调用之间保持和修改这些状态。

内联调用:仿函数的调用可以被编译器内联,这意味着可以减少函数调用的开销,提高效率。

泛型编程:仿函数可以搭配标准模板库(STL)中的算法和容器使用,非常适合实现自定义的比较逻辑或操作。

示例:自定义比较仿函数

假设你想在 priority_queue 中使用自定义的比较逻辑,可以定义一个仿函数来实现这一点。以下是一个简化的 Date 类仿函数比较的例子:

 
#include <iostream>
#include <queue>
using namespace std;class Date {
public:int year, month, day;Date(int y, int m, int d) : year(y), month(m), day(d) {}
};// 自定义比较仿函数
class CompareDate {
public:bool operator()(const Date& lhs, const Date& rhs) const {// 比较逻辑:先年后月再日if (lhs.year != rhs.year) return lhs.year > rhs.year;if (lhs.month != rhs.month) return lhs.month > rhs.month;return lhs.day > rhs.day;}
};int main() {priority_queue<Date, vector<Date>, CompareDate> pq;pq.push(Date(2023, 4, 22));pq.push(Date(2023, 5, 21));pq.push(Date(2023, 3, 23));while (!pq.empty()) {Date d = pq.top();cout << d.year << "-" << d.month << "-" << d.day << endl;pq.pop();}return 0;
}

在这个例子中,CompareDate 是一个仿函数,它重载了 operator() 来提供 Date 对象的比较逻辑。这个逻辑首先比较年份,如果年份相同,则比较月份,如果月份也相同,最后比较日。这个仿函数可以用作 priority_queue 的比较类型参数,从而定制容器中元素的排列顺序。

优先队列与仿函数结合

 
/*优先队列与仿函数结合*/
#if 1
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return _day < d._day;}bool operator>(const Date& d)const{return _day > d._day;}void Show()const{cout<<_year<<"-"<<_month<<"-"<<_day<<endl;}friend bool CompareDate(const Date* left, const Date* right);friend class Compare;
private:int _year;int _month;int _day;};bool CompareDate(const Date* left, const Date* right){return left->_day < right->_day;}typedef bool (*COM)(const Date* left, const Date* right);
// 仿函数--函数对象:可以像函数一样使用的对象
class Compare
{
public:bool operator()(const Date* left, const Date* right){return left->_day < right->_day;}};void TestPriorityQueue7(){Date d1(2023, 4, 22);Date d2(2023, 4, 21);Date d3(2023, 4, 23);CompareDate(&d1, &d2);Compare com;com(&d1, &d2);com.operator()(&d1, &d2);priority_queue<Date*, vector<Date*>, Compare> q;q.push(&d1);q.push(&d2);q.push(&d3);while (!q.empty()) {Date* top = q.top(); // 获取优先队列顶部元素top->Show();         // 显示日期q.pop();             // 移除顶部元素}}int main(){TestPriorityQueue7();return 0;}
#endif

对于优先队列比较参数的探究

 
priority_queue<Date*, vector<Date*>, Compare> q;//仿函数
priority_queue<Date, vector<Date>, CompareDate> pq;//仿函数
priority_queue<Date*, vector<Date*>, COM> q(CompareDate);//函数指针
priority_queue<Date, vector<Date>, greater<Date>> q; //默认greater对象

我们发现第三个参数,比较大小的参数,可以有上面三种使用方法。第一个和第二个是一样的,都是仿函数,仿函数本质是对象,和第四个同样是传入对象,而第三个传入的是函数指针。说明第三个参数可以接收函数指针也可以接收对象。

仿函数和函数指针的区别

虽然从表面上看,仿函数(通过类重载的 operator())和函数指针(指向一个具体函数的指针)都可以作为排序准则传递给 std::priority_queue(或其他模板类),它们在底层实现和使用方式上存在一些关键差异:

仿函数(Function Objects):仿函数是通过类实例化的对象,这些对象通过重载 operator() 来实现。它们可以有自己的状态(成员变量)并可以携带更多的上下文信息。在模板参数中传递仿函数类型时,你实际上传递的是一个类型(而非对象实例本身),std::priority_queue 在内部会创建这个类型的实例来进行元素比较。如果需要传递状态或参数给仿函数,你需要在仿函数类中提供相应的构造函数。

函数指针:函数指针是指向函数的指针,它不能携带状态(除非使用全局变量或静态变量,但这通常不是一个好的设计选择)。在模板参数中使用函数指针时,如 COM 类型,你实际上是在传递一个指向函数的指针,这意味着传递的是一个地址值。当你在构造 std::priority_queue 时提供 CompareDate 函数作为参数,你实际上是在提供一个具体的函数指针值。

对象与地址的传递

对于仿函数,你传递的是一个类型,std::priority_queue 使用这个类型在内部构造一个对象实例。这个过程并不涉及显式的地址传递,而是类型信息的传递。

对于函数指针,传递的确实是一个地址值,即函数在内存中的位置。

默认比较对象

当使用如 std::greater<Date> 这样的默认比较对象时,同样是传递了一个类型给 std::priority_queue,它会构造这个类型的实例来进行比较。std::greater<T>std::less<T> 是标准库提供的比较函数对象类型,它们也是通过重载 operator() 实现的。

优先队列创建对象的方式

使用默认比较函数对象

默认情况下,std::priority_queue使用std::less<T>作为其比较函数对象,构造一个最大堆。这意味着没有指定比较函数时,队列中的最大元素将会位于顶部。

 
std::priority_queue<int> pq; // 默认为最大堆,使用 std::less<int> 比较元素

使用标准库比较函数对象

可以通过显式指定比较函数对象(如std::greater<T>)来改变优先队列的排序行为,例如构建一个最小堆。

 
std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;

使用自定义仿函数

通过定义一个自定义的比较类(仿函数),可以实现更复杂的比较逻辑。该类需要重载operator()

 
class Compare {
public:bool operator()(int a, int b) {// 自定义比较逻辑return a > b; // 示例:构建最小堆}
};
std::priority_queue<int, std::vector<int>, Compare> customHeap;

使用函数指针

如果你有一个静态比较函数,也可以将其地址作为优先队列的比较逻辑。这通常适用于简单的比较逻辑或C风格的代码。

 
bool compare(int a, int b) { return a > b; } // 函数指针比较
// 注意:直接使用函数指针作为模板参数在标准的 priority_queue 中不直接支持,需要包装或转换为对象。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/683914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stable Diffusion系列(五):原理剖析——从文字到图片的神奇魔法(扩散篇)

文章目录 DDPM论文整体原理前向扩散过程反向扩散过程模型训练过程模型生成过程概率分布视角参数模型设置论文结果分析 要想完成SD中从文字到图片的操作&#xff0c;必须要做到两步&#xff0c;第一步是理解文字输入包含的语义&#xff0c;第二步是利用语义引导图片的生成。下面…

Uipath 实现Excel 文件合并

场景描述 某文件夹下有多个相同结构(标题列相同)的Excel 文件&#xff0c;需实现汇总到一个Excel文件。 常见场景有销售明细汇总&#xff0c;订单汇总等。 解决方案 对于非IT 人员则可使用Uipath 新式Excel活动&#xff0c;通过拖拉实现。也可以通过内存表或使用VB脚本&…

寒假学习记录17:包管理器(包管理工具)

概念 包&#xff08;package&#xff09; 包含元数据的库&#xff0c;这些元数据包括&#xff1a;名称&#xff0c;描述&#xff0c;git主页&#xff0c;许可证协议&#xff0c;作者&#xff0c;依赖..... 库&#xff08;library&#xff0c;简称lib&#xff09; 以一个或多个模…

【教3妹学编程-算法题】子集中元素的最大数量

2哥 : 3妹&#xff0c;今年过年收到压岁钱了没呢。 3妹&#xff1a;切&#xff0c;我都多大了啊&#xff0c;肯定没收了啊 2哥 : 俺也一样&#xff0c;不仅没收到&#xff0c;小侄子小外甥都得给&#xff0c;还倒贴好几千 3妹&#xff1a;哈哈哈哈&#xff0c;2叔叔&#xff0c…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Navigation组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Navigation组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Navigation组件 鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#…

Python中多种生成随机密码超实用实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站零基础入门的AI学习网站~。 前言 密码是信息安全的基石&#xff0c;它用于保护我们的账户、数据和隐私。为了确保密码足够强大&#xff0c;…

clang前端

Clang可以处理C、C和Objective-C源代码 Clang简介 Clang可能指三种不同的实体&#xff1a; 前端&#xff08;在Clang库中实现&#xff09;编译驱动程序&#xff08;在clang命令和Clang驱动程序库中实现&#xff09;实际的编译器&#xff08;在clang-ccl命令中实现&#xff0…

kafka如何保证消息不丢?

概述 我们知道Kafka架构如下&#xff0c;主要由 Producer、Broker、Consumer 三部分组成。一条消息从生产到消费完成这个过程&#xff0c;可以划分三个阶段&#xff0c;生产阶段、存储阶段、消费阶段。 产阶段: 在这个阶段&#xff0c;从消息在 Producer 创建出来&#xff0c;…

c++阶梯之类与对象(下)

前文&#xff1a; c阶梯之类与对象&#xff08;上&#xff09;-CSDN博客 c阶梯之类与对象&#xff08;中&#xff09;-CSDN博客 c阶梯之类与对象&#xff08;中&#xff09;&#xff1c; 续集 &#xff1e;-CSDN博客 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&a…

【机器学习笔记】3 逻辑回归

分类问题 分类问题监督学习最主要的类型&#xff0c;主要特征是标签离散&#xff0c;逻辑回归是解决分类问题的常见算法&#xff0c;输入变量可以是离散的也可以是连续的 二分类 先从用蓝色圆形数据定义为类型1&#xff0c;其余数据为类型2&#xff1b;只需要分类1次&#x…

Java并发基础:SynchronousQueue全面解析!

内容概要 SynchronousQueue的优点在于其直接性和高效性&#xff0c;它实现了线程间的即时数据交换&#xff0c;无需中间缓存&#xff0c;确保了数据传输的实时性和准确性&#xff0c;同时&#xff0c;其灵活的阻塞机制使得线程同步变得简单而直观&#xff0c;适用于需要精确协…

相机图像质量研究(13)常见问题总结:光学结构对成像的影响--鬼影

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

TiDB 在医疗保障信息平台的应用实践

文章介绍了 TiDB 在医疗保障信息平台中的应用。东软医保云应用管理平台通过与 TiDB 联合&#xff0c;成功满足了医疗保障业务中高并发、实时性和复杂查询的要求。在某地市医疗保障信息平台的实践中&#xff0c;TiDB 分布式数据库有效实现了在线交易和实时分析服务&#xff0c;日…

C语言学习day14:数组定义和使用

定义变量&#xff1a; 数据类型 变量 值 数组定义&#xff1a; 数据类型 数组名[元素个数]{值1,值2,值3} 代码&#xff1a; int main() {//定义变量//数据类型 变量 值//数组定义//数据类型 数组名[元素个数]{值1,值2,值3}//数组下标 数组名[小标]//数组下标是…

.NET Core WebAPI中封装Swagger配置

一、创建相关文件 创建一个Utility/SwaggerExt文件夹&#xff0c;添加一个类 二、在Program中找到Swagger相关配置信息 三、添加方法&#xff0c;在Program中调用 在SwaggerExt类中添加方法&#xff0c;将相关配置添写入 /// <summary> /// swagger配置 /// </sum…

初识Qt | 从安装到编写Hello World程序

文章目录 1.前端开发简单分类2.Qt的简单介绍3.Qt的安装和环境配置4.创建简单的Qt项目 1.前端开发简单分类 前端开发&#xff0c;这里是一个广义的概念&#xff0c;不单指网页开发&#xff0c;它的常见分类 网页开发&#xff1a;前端开发的主要领域&#xff0c;使用HTML、CSS …

[经验] 欧阳修唐宋八大家之首是谁 #微信#知识分享#学习方法

欧阳修唐宋八大家之首是谁 1、唐宋八大家之首是谁 唐宋八大家是中国文学史上最具代表性的八位大文豪&#xff0c;他们的文学成就在中国文学史上占有重要地位&#xff0c;被誉为文学史上的“巨人”。 唐宋八大家之首&#xff0c;无疑是唐代著名诗人杜甫。他出生在一个贫苦的家…

牛客——IncDec Sequence(差分)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 给定一个长度为 n(n≤105)(n \leq 10^5 )(n≤105) 的数列a1,a2,…,an{a_1,a_2,…,a_n}a1​,a2​,…,an​&#xff0c;每次可以选择一个区间 [l,r]&#xff0c;使下标在这个区间内的数…

每日一题 力扣107 二叉树的层序遍历Ⅱ

107. 二叉树的层序遍历 II 题目描述&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20…

如何用 ChatGPT 做项目管理?

ChatGPT 可以通过创建和维护跨团队项目协作计划&#xff0c;让员工更容易理解他们的角色和职责。 这个协作计划里面会包括每个团队或个人要执行的具体任务&#xff0c;每个任务最后期限和任何事情之 间的依赖关系。 该场景对应的关键词库:(24 个) 项目管理、项目协作计划、跨…