堆结构和lambda表达式的应用(IPO问题)

本文介绍了C++中的lambda表达式及其在优先级队列(PriorityQueue)中的应用,讨论了如何使用lambda表达式自定义比较器。接着,文章通过IPO问题阐述了如何利用堆(最大堆和最小堆)实现贪心算法求解最大资本。最后,提供了资源分享,包括完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章和资源同步更新至微信公众号:算法工程师之路

之前有篇文章讲解了堆结构以及堆排序,堆可以分为大根堆和小根堆,那么我们如何使用么?笔试时需不需要自己重新实现一个堆结构呢?这个问题怎么说,从底层实现是应该会的,也不难,但实际用的时候就不用自己重新造轮子了!C++标准库中有类似堆结构的东西——Priority_Queue!

lambda表达式()

段落来源转自简书–小白将

在开始今天的内容之前,我们先来说一说C++中的lambda表达式,大家学过Python的都知道lambda表达式的好处,可以省略大量代码而且使得阅读逻辑更加清晰,在C++中其表现结构一般为:

[ 俘获变量 ] ( 形参 ) { 函数体 }

lambda表达式最前面的方括号的意义何在?其实这是lambda表达式一个很要的功能,就是闭包。lambda表达式的大致原理:每当你定义一个lambda表达式后,编译器会自动生成一个匿名类(这个类当然重载了()运算符),我们称为闭包类型(closure type)。那么在运行时,这个lambda表达式就会返回一个匿名的闭包实例,其实一个右值。所以,我们上面的lambda表达式的结果就是一个个闭包。闭包的一个强大之处是其可以通过传值或者引用的方式捕捉其封装作用域内的变量,前面的方括号就是用来定义捕捉模式以及变量,我们又将其称为lambda捕捉块。
捕获的方式可以是引用也可以是复制,但是具体说来会有以下几种情况来捕获其所在作用域中的变量:

那么捕获域是怎么使用呢?我们可以看下面的例子:

int main(int argc, char** argv){
   
	int x =10;
	auto add_x = [x](int a){
   return a+x;};
	auto multipy_x = [&x](int a){
   return a*x;};
 
	cout<<"add "<<add_x(10)<<" "<<"multipy "<< multipy_x(10)<<endl;
}
  • []:默认不捕获任何变量;
  • [=]:默认以值捕获所有变量;
  • [&]:默认以引用捕获所有变量;
  • [x]:仅以值捕获x,其它变量不捕获;
  • [&x]:仅以引用捕获x,其它变量不捕获;
  • [=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
  • [&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
  • [this]:通过引用捕获当前对象(其实是复制指针);
  • [*this]:通过传值方式捕获当前对象;

一般我们通常使用前三种形式!!!

PriorityQueue(优先级队列)

C++标准库中的优先级队列其底层数据一般为vector形式,并以堆结构进行数据管理的,我们通过前面的知识也知道堆分为大根堆和小根堆,其中大根堆的根节点是最大值,而小根堆的根节点是最小值。因此,我们在定义PriorityQueue时候需要指定其比较器,特别是当存储类型为自定义对象时!

我们首先来看PriorityQueue的模板定义,其中less< value_type >是一个标准库中的函数对象,因此我们知道了 模板参数中的第三个位置是一个比较函数的函数对象。因此我们可以自己新建一个函数对象来进行传递!

template <class T, class Container = vector, class Compare =
less > class priority_queue;

下面例子介绍了几种构造优先级队列的方法:

  • 通过一个类重载()来构成函数对象,用于自定义比较器使用
  • 对于基础类型,可以使用标准库中的函数对象,如less和more
  • 使用lambda表达式,由于lambda表达式返回的是一个匿名对象,因此必须在实例化同时将其作为参数传递到priority_queue中去
  • 构建的比较器中<表示less(降序)表示小根堆,反之>表示大根堆
#include <queue>
#include <vector>
#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值