运用比较器实现机制(函数对象和指针对象)实现最大堆和最小堆

C++高并发异步定时器:最小堆实现与性能优化实战 定时器是服务端编程中的核心基础组件,用于在指定时间点触发预设任务。其实现原理主要围绕高效管理大量定时任务并精确触发,关键在于数据结构选型与并发控制。从技术价值看,一个优秀的定时器能显著提升系统吞吐量、降低延迟,是构建高性能网络服务、游戏服务器及高频交易系统的基石。常见的应用场景包括连接超时管理、心跳检测、延迟任务调度等。本文聚焦于高并发场景,通过对比链表、时间轮、最小堆等数据结构,最终采用最小堆结合异步事件循环的方案,并深入探讨了线程安全、内存管理及性能优化等工程实践,例如通过惰性删除策略处理任务取消,以及 阅读详情

 

 

首先我们来了解一下最基本的函数对象的应用。

先来看STL源码:

 

//priority_queue模板源码:

template<class _Ty,

class _Container = vector<_Ty>,

class _Pr = less<typename _Container::value_type> >

class priority_queue

{    // priority queue implemented with a _Container

public: 

     explicit priority_queue(const _Pr& _Pred)

         : c(), comp(_Pred)

     {   

         //To use the comparator functor

         //bool b = comp(t1, t2);

     }

 

protected:

     _Container c; // the underlying container

     _Pr comp; // the comparator functor

};

可见_Pr为一种类型,可以为函数指针类型,也可以为类类型。

当为函数指针类型时,必须显式的传入对象,如:

typedef bool (*myfunc)(int , int);

     bool testFuncPointer(int i, int j)

     {

         if (i < j)

              return true;

         return false;

     }

     priority_queue<int, myfunc> q(testFuncPointer);

当为类对象时,不需要传入,因为_Pr comp会初始化一个对象出来,继而调用该函数对象的()操作符。

如:

priority_queue<int, greater<int>> q;

但有的人说了:我非要传进去一个函数对象进去不可,这样写。

priority_queue<int> q(less<int>());

priority_queue<int> q(less<int>);错

 

此种情况为类模板,但是泛型函数,内部书写方式如下:

比如sort:

 

template<class _RanIt,

class _Diff,

class _Pr> inline

     void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal, _Pr _Pred)

{

     //_Pred(t1, t2);

}

不再有如同上述模板类中的private成员的构造函数,所以_Pred必须传如对象

bool UDgreater ( int elem1, int elem2 )

     {

         return elem1 > elem2;

     }   

sort( v1.begin( ), v1.end( ), greater<int>( ) );

sort( v1.begin( ), v1.end( ), greater<int>);错

     sort( v1.begin( ), v1.end( ), UDgreater );

另外,更多的函数对象技术,比如否定器,绑定器之类的,去看源代码理解吧。

Tags:Pred一元谓词,BinPred二元谓词,Cmp比较操作,Op一元操作,BinOp二元操作,bind2nd是一个函数,binder2nd是一个类模板等等等等。

 

 

附:模仿STL源码自己实现堆,依据传入的cmp去指明是最大堆还是最小堆。

 

//less是最小堆,即top()返回最小的一个

template<typename T, typename cmp=less<T>>

class MyHeap

{

public:

     MyHeap(cmp _cmp = cmp());

     MyHeap(T arr[], int len, cmp _cmp = cmp());

 

     const T& top()const

     {

         assert(m_size > 0);

         return m_data[0];

     }

     T &top()

     {

         assert(m_size > 0);

         return m_data[0];

     }

    

     void pop();

     int size()const{return m_size;}

     void push(const T &val);

private:

     void make_heap();

     void fix_from_top(int root);

     void _swap(T &a, T &b){T tmp = a; a = b; b = tmp;}

     void fix_from_bottom(int child);

    

     cmp m_cmp;

     static const int MAXSIZE = 1024;

     T m_data[MAXSIZE];

     int m_size;

};

 

 

template<typename T, typename cmp>

MyHeap<T, cmp>::MyHeap(T arr[], int len, cmp _cmp)

:m_cmp(_cmp)

{

     assert(len <= MAXSIZE);

     memcpy(m_data, arr, sizeof(T)*len);

     m_size = len;

     make_heap();

}

 

template<typename T, typename cmp>

MyHeap<T, cmp>::MyHeap(cmp _cmp /* = less<T> */)

:m_size(0)

{

    

}

 

template<typename T, typename cmp>

void MyHeap<T, cmp>::make_heap()

{

     int end = m_size-1;

     for (int i = (end-1)/2; i >= 0; --i)

     {

         fix_from_top(i);

     }

}

 

template<typename T, typename cmp>

void MyHeap<T, cmp>::fix_from_top(int root)

{

     int range = m_size-1;

     T val = m_data[root];

     int father = root;

     int son = father*2+1;

 

     while (son <= range)

     {

         if(son + 1 <= range && !m_cmp(m_data[son], m_data[son+1]))

              ++ son;

 

         if (!m_cmp(m_data[father], m_data[son]))

         {

              _swap(m_data[father], m_data[son]);

              father = son;

              son = father*2+1;

         }

         else

              break;

     }

}

 

template<typename T, typename cmp>

void MyHeap<T, cmp>::pop()

{

     assert(m_size>0);

     -- m_size;

     m_data[0] = m_data[m_size];

 

     fix_from_top(0);

}

 

template<typename T, typename cmp>

void MyHeap<T, cmp>::push(const T &val)

{

     assert(m_size < MAXSIZE-1);

     m_data[m_size] = val;

     fix_from_bottom(m_size);

     ++ m_size;

}

 

template<typename T, typename cmp>

void MyHeap<T, cmp>::fix_from_bottom(int child)

{

     T val = m_data[child];

 

     int father = (child-1)/2;

     while (father >= 0)

     {

         if (!m_cmp(m_data[father], m_data[child]))

         {

              _swap(m_data[father], m_data[child]);

              child = father;

              if (child > 0)

                   father = (child-1)/2;

              else

                   father = -1;

         }

         else

              break;

     }

}

 

C++数组实现最大堆:原理、代码与性能优化全解析 堆是一种基于完全二叉树的重要数据结构,其核心性质是父节点值大于等于子节点值(最大堆)。这种结构通过巧妙的数组索引映射实现高效存储与访问,父子节点满足固定算术关系。堆的核心价值在于支持O(log n)时间复杂度的插入与删除最值操作,以及O(1)的峰值访问,使其成为实现优先队列的理想选择。在工程实践中,堆广泛应用于任务调度、实时排行榜、Top K问题及堆排序等场景。本文以C++为例,深入剖析数组实现最大堆的底层机制,详细讲解上浮与下沉两大核心操作,并探讨其与STL priority_queue的对比及常见调试技 阅读详情

相关推荐

QGIS效率提升神器:qgis_mcp插件+VSCode联合工作流配置全解析

本文详细解析了如何通过配置qgis_mcp插件与VSCode的联合工作流,实现语音控制和代码自动化来大幅提升QGIS操作效率。该方案将自然语言交互与现代编辑器生态结合,为地理信息专业人士构建了智能、高效的全新工作模式,彻底改变传统GIS操作方式。

weixin_29228203的博客 189

C++ 自定义大小顶堆的比较函数

当我们有自己的结构体时 struct Edge{ int v1,v2,cost; Edge(int tv1,int tv2,int c):v1(tv1),v2(tv2),cost(c){} bool operator <(const Edge& e)const{ return this-> cost > e.cost; } }; priority_queue<Node> A; //默认 大根堆 priority_qu

lcxyplucky的博客 3122

解密HDMI热插拔检测电路:从HPD引脚到EDID读取的全流程避坑

本文深入解析HDMI热插拔检测与EDID读取的全流程,从HPD引脚信号特性、DDC通道I2C协议到EDID数据结构,系统剖析了硬件电路设计、信号完整性和软件协议中的常见陷阱与解决方案,为消费电子设备开发者提供了一套完整的实战避坑指南。

weixin_29291069的博客 645

【C++】比较器

在C++中,可以使用函数比较器(comparator)来比较两个对象的大小或顺序。函数比较器是一个函数或函数对象,它接受两个参数并返回一个布尔值,用于指示两个对象的顺序。在C++中,可以通过编写比较器(comparator)函数或重载操作符来比较结构体对象的大小或顺序。

m0_68250740的博客 1219

Unity游戏开发:从零开始适配Nintendo Switch的完整指南

本文详细介绍了如何使用Unity进行Nintendo Switch游戏开发的完整流程,包括开发环境搭建、Unity工程适配、手柄与硬件特性开发、存储与性能优化等关键步骤。特别强调了Switch SDK的配置、输入系统改造和内存优化技巧,帮助开发者高效完成跨平台适配。

vodka的博客 1066

(一)ANSYS WORKBENCH实践入门

ANSYS-workbench 有限元分析应用基础教程 (张晔)学习笔记

qq_51767372的博客 1万+

有关栈、队列、堆的函数使用总结

C++版本: 栈: #include< stack > 定义:stack< int > s; s.empty(); //如果栈为空则返回true, 否则返回false; s.size(); //返回栈中元素的个数 s.top(); //返回栈顶元素, 但不删除该元素 ...

c_daofeng的博客 378

基于STM32F407VET6的智能巡检小车灰度循迹系统优化设计

本文详细介绍了基于STM32F407VET6主控芯片的智能巡检小车灰度循迹系统优化设计。通过将传感器输出从数字量升级为模拟量以获取更丰富的路面信息,并采用PD控制算法结合速度管理策略,有效提升了小车在复杂弯道上的循迹稳定性与适应性。文章分享了硬件电路抗干扰设计、软件滤波及实战调优经验,为嵌入式开发者提供了从“能跑”到“跑得稳”的系统性解决方案。

weixin_28273593的博客 442

C++中的模板template <typename T>

这个是C++中的模板..template<typename T> 这个是定义模板的固定格式,规定了的..模板应该可以理解到它的意思吧.. 比如你想求2个int float 或double型变量的值,只需要定义这么一个函数就可以了,假如不用模板的话,你就必须针对每种类型都定义一个sum函数..int sum(int, int);float sum(float, float);double sum(double, double); 1.因为T是一个模版实例化时才知道的类型,所以编译器更对T不

nihao_2014的博客 1539

Chromium实用技巧篇-如何下载指定版本的Chromium(一)

通过本指南,您已成功掌握如何在Windows系统上下载并安装最新版本的Chromium浏览器。我们详细介绍了从进入Chromium官网,到查找最新版本号,再到下载和安装的每一个步骤。通过这些步骤,您不仅能够体验到最新的浏览器功能,还可以参与开源项目的开发,享受高速、稳定、安全的浏览体验。

守城小轩的技术窝棚 1万+

revit二次开发环境搭建(2024版)(小白友好)

revit二次开发环境配置,SDK、addin manager和lookup新手友好安装教程

m0_56961251的博客 1419

C++ 泛型 Heap 实现

鉴于自己没写过Heap,很是羞愧~于是今晚写了一下~ 1. 学习了下嵌套template的使用~ 实现部分就是 template template 这种形式 2.使用函数对象传递函数,一开始忘了用实例化一个函数对象,语法老错,真汗~ 3. 想了下heap的push方法,只要在最后一个加上元素,然后从下往上“冒泡”就可以了~ 可以证明是保持heap有效的

New Day New Plan 1326

ABAP CDS 货币与计量单位换算全攻略:CURRENCY_CONVERSION、UNIT_CONVERSION 与 DECIMAL_SHIFT 的工程化实践

本文介绍了SAP ABAP CDS中三种单位/货币换算函数(UNIT_CONVERSION、CURRENCY_CONVERSION、DECIMAL_SHIFT)的实战应用。重点包括:各函数的职责边界与适用场景,参数配置与精度控制策略,以及基于标准表(T006、TCUR*等)的换算规则来源。文章提供可运行的CDS示例,涵盖单位换算(如MI转KM)、货币汇率转换(含小数位处理)及纯小数位调整等典型场景,并强调生产环境中需注意的精度差异与审计风险控制。适用于企业报表、成本核算等需要统一口径的业务场景。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1553

如何用priority_queue实现最大堆、最小堆及多字段优先级?一文讲透

掌握C++ STL priority_queue自定义优先级的实现方法,轻松构建最大堆、最小堆及多字段优先级队列。适用于算法竞赛与实际工程场景,提升数据处理效率。详解仿函数与模板参数技巧,值得收藏。

InstrWander的博客 463

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

揭秘C++ priority_queue仿函数机制:5分钟掌握自定义比较器的核心要点

掌握C++ priority_queue的仿函数用法,快速实现自定义排序逻辑。适用于堆优化、任务调度等场景,通过重载operator()灵活控制优先级,提升代码效率与可读性。揭秘核心机制与常见误区,值得收藏。

QuickSolve的博客 299

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

priority_queue仿函数对象深度揭秘:构建高效自定义堆的必备知识

掌握priority_queue的仿函数对象,轻松实现自定义堆排序逻辑。详解其在任务调度、数据优先级管理中的应用,解析operator()重载与STL适配技巧,提升代码效率与灵活性。深入用法值得收藏。

CodeWhim的博客 364

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

priority_queue自定义比较器全解析(从入门到精通仿函数对象)

掌握priority_queue的自定义排序,深入解析priority_queue的仿函数对象用法,涵盖运算符重载与函数对象设计,适用于堆排序、任务调度等场景,提升代码效率与灵活性,解决复杂优先级管理难题,值得收藏。

VarChat的博客 377

你真的懂priority_queue吗?探秘仿函数对象背后的底层机制

掌握priority_queue的高效使用秘诀,深入解析priority_queue的仿函数对象如何定制排序规则。涵盖STL底层实现机制、适用场景及自定义比较器的核心方法,提升代码灵活性与性能,值得收藏。

FastProceed的博客 423

揭秘priority_queue自定义比较器:如何轻松实现复杂数据类型的优先级排序

掌握C++ STL priority_queue自定义优先级技巧,轻松实现复杂数据类型排序。通过自定义比较器,灵活控制优先级规则,适用于任务调度、算法优化等场景。代码简洁高效,提升程序可读性与扩展性,值得收藏。

QuickTrans的博客 429

C++ priority_queue深度解析:从仿函数到自定义堆实现

在数据结构与算法中,堆(Heap)是一种基于完全二叉树的高效数据结构,常用于实现优先级队列。其核心原理是通过维护特定的堆序性质(如大顶堆或小顶堆),使得最大或最小元素始终位于堆顶,从而支持O(1)时间复杂度的极值访问,以及O(log N)的插入与删除操作。这一特性在任务调度、实时系统、游戏事件处理及Top K问题等场景中具有极高的技术价值,能够确保高优先级任务被及时处理。C++标准库中的priority_queue正是基于堆的容器适配器,其灵活性很大程度上源于仿函数(Functor)的运用。仿函数作为可调用

weixin_30268921的博客 337

priority_queue的仿函数对象完全解析(从小根堆到复杂类型排序)

掌握priority_queue的仿函数对象用法,轻松实现自定义排序。涵盖从小根堆构建到复杂类型排序的应用场景,详解operator()重载与STL适配技巧,提升代码灵活性与效率,值得收藏。

Algorhythm的博客 315

优先队列与堆实现详解:从原理到哈夫曼树实战

优先队列是一种基于优先级进行元素存取的数据结构,其核心在于能够高效地动态获取集合中的最大值或最小值。其底层通常采用堆(Heap)实现,特别是二叉堆,通过维护堆性质(父节点与子节点间的大小关系)和利用数组紧凑存储,使得插入与删除极值操作的时间复杂度均能保持在O(log n)。这一特性使其在需要频繁获取极值的场景中极具技术价值,例如在任务调度、实时数据流处理、以及高效排序算法中。一个经典的应用场景是哈夫曼编码,该算法在数据压缩领域(如ZIP、JPEG)至关重要,其构建过程需要反复从节点集合中取出两个最小权重的节

weixin_33976072的博客 397

从零实现堆数据结构:核心原理、C++代码与Top K应用

堆是一种基于完全二叉树实现的高效数据结构,其核心特性是能快速获取最大值或最小值。通过数组存储和巧妙的索引映射,堆实现了O(1)时间获取最值,以及O(log n)时间的插入与删除操作,这使其在动态数据场景下比有序数组更具优势。堆的核心操作依赖于上浮和下沉两种调整机制来维护堆序性质,这一原理支撑了其在优先级队列、堆排序等场景的广泛应用。特别是在处理海量数据的Top K问题时,通过维护一个最小堆,可以在O(N log K)时间内高效找出前K个最大元素,这是堆在工程实践中的典型价值体现。本文将以C++为例,手把手拆

weixin_30682415的博客 403

C++堆数据结构详解:从原理到STL应用与性能优化

堆是一种基于完全二叉树实现的高效优先级队列数据结构,其核心原理在于通过维护父节点与子节点间的特定大小关系(堆序性质),在O(log n)时间内完成元素的插入与最值提取。这种以局部有序换取全局最优解的设计思想,使其在需要动态管理优先级的场景中极具技术价值。堆的典型应用包括堆排序、Top K问题求解、流数据中位数查找以及任务调度系统。在C++工程实践中,STL提供了`std::priority_queue`及`<algorithm>`中的堆算法,开发者需掌握其使用模式与陷阱,例如通过自定义比较器实现最小堆,并理

weixin_34161064的博客 658

priority_queue仿函数对象实战精讲(涵盖函数对象、Lambda与类类型对比)

掌握priority_queue的仿函数对象用法,深入解析函数对象、Lambda与类类型在自定义排序中的应用。涵盖常见适用场景与性能对比,提升代码灵活性与效率,实战示例助你快速掌握核心技巧,值得收藏。

InitPulse的博客 432

为什么大厂面试总问priority_queue仿函数?揭开高薪程序员的秘密武器

掌握priority_queue的仿函数对象,轻松应对高频面试题。详解自定义排序规则在算法竞赛与大厂项目中的应用,解析STL底层机制与性能优化关键。学会灵活控制堆序,提升代码效率,值得收藏

PixelGlow的博客 254
上一篇: 我也来写KMP
MagicxiaoZ
博客等级 码龄19年 5粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值