c++ - priority_queue使用和模拟实现

文章目录

    • 一、priority_queue接口使用
    • 二、 priority_queue模拟实现
    • 三、模拟代码总览


一、priority_queue接口使用

1、函数接口与作用

接口作用
priority_queue< T >构造一个空优先队列
priority_queue< T >(迭代区间)通过迭代区间构造一个优先队列
push(val)val入队
pop()出队
size()队列的元素个数
top()取出队头元素的引用
empty()判断栈是否为空

2、指定排序规则
在定义优先队列时指定,如果不指定就默认倒序(大堆)。
如何指定:

在这里插入图片描述

比较仿函数写法:

//比较仿函数
template <class T>
class cmp
{
public:
	//返回bool,两个参数
	bool operator()(T& x, T& y)
	{
		//比较........
		return x > y;
	}
};

3、使用

void priority_queue_test()
{
	//通过迭代器区间构造
	vector<int> v{ 1,2,5,3,8 };

	//默认大堆
	priority_queue<int> q(v.begin(),v.end());


	//判断是否为空
	while (!q.empty())
	{
		//取队头元素
		cout << q.top() << " ";
		//出队
		q.pop();
	}
	cout << endl;
}

在这里插入图片描述

二、 priority_queue模拟实现

1、 priority_queue是一个适配器,默认封装了vector容器,所以我们模拟时也使用vector容器。
在这里插入图片描述
2、priority_queue框架

//第一个是数据类型,第二个是容器类型(默认vector),第三个仿函数类的类型(默认大堆)
 template <class T,class Container = vector<T> , class Compare = less<T>>
 class priority_queue
 {
 public:
 void push(T x);
 //....
 private:
     Container c;
  }

3、比较仿函数类的实现
大堆:

template <class T>
class less
{
public:
    bool operator()(const T& a, const T& b)
    {
        return a < b;
    }
};

小堆:

template <class T>
class greater
{
public:
    bool operator()(const T& a, const T& b)
    {
        return a > b;
    }
};

4、插入、删除
(1)push
这里直接复用vector容器的push_back接口,但是我们需要将优先级最高的放到第一个位置,所以还需要使用一个堆的向上调整算法,该算法需要配合比较仿函数使用。

//向上调整算法
void Adjust_Up(size_t child)
{
    size_t father = (child - 1) / 2;
    T tmp = c[child];
    //仿函数类
    Compare cmp;

    while (child > 0)
    {
        //使用仿函数判断
        if(cmp(c[father], tmp))
        {
            c[child] = c[father];
            child = father;
            father = (child - 1) / 2;
        }
        else
            break;
    }

    c[child] = tmp;
}

 void push(const T& x)
 {
 //利用vector的接口
     c.push_back(x);
//使用向上调整算法
     Adjust_Up(size() - 1);
 }

(2)pop
我们需要将第一个位置的元素删掉,为了保证效率,需要将其与最后一个元素交换,再进行尾删(这样效率比直接删除第一个位置高),最后使用向下调整算法即可保持优先级最高的在第一个位置了。

//先下调整算法
 void Adjust_Down()
 {
     size_t father = 0;
     size_t child = father * 2 + 1;
     T tmp;
     //仿函数对象
     Compare cmp;
     if (size() > 0)
         tmp = c[0];
     else return;

     while (child < size())
     {
     //使用仿函数比较
         if (child + 1 < size() && cmp(c[child],c[child + 1]))
             child++;
     //使用仿函数比较
         if(cmp(tmp, c[child]))
         {
             c[father] = c[child];
             father = child;
             child = father * 2 + 1;
         }
         else
             break;
     }
      c[father] = tmp;
 }
 //删除
  void pop()
  {
  //先交换
      std::swap(c[0], c[size() - 1]);
  //再尾删
      c.pop_back();
  //最后向下调整
      Adjust_Down();
  }

5、其他接口
都是复用vector接口实现

//判断是否为空
 bool empty() const
 {
     return c.empty();
 }
//大小
 size_t size() const
 {
     return c.size();
 }
//取队头元素引用
 T& top() 
 {
     return c[0];
 }

6、构造函数

//默认构造
priority_queue()
 {};
//使用迭代器区间构造,直接复用push这个接口即可
 template <class InputIterator>
 priority_queue(InputIterator first, InputIterator last)
 {
     while (first != last)
     {
         push(*first);
         ++first;
     }
 }

三、模拟代码总览

namespace xu
{
   template <class T>
   class less
   {
   public:
       bool operator()(const T& a, const T& b)
       {
           return a < b;
       }
   };

   template <class T>
   class greater
   {
   public:
       bool operator()(const T& a, const T& b)
       {
           return a > b;
       }
   };


    template <class T,class Container = vector<T> , class Compare = less<T>>
    class priority_queue
    {
    public:
        
        priority_queue()
        {};

        template <class InputIterator>
        priority_queue(InputIterator first, InputIterator last)
        {
            while (first != last)
            {
                push(*first);
                ++first;
            }
        }

        void Adjust_Up(size_t child)
        {
            size_t father = (child - 1) / 2;
            T tmp = c[child];
            Compare cmp;

            while (child > 0)
            {
                //if (c[father] < tmp)
                if(cmp(c[father], tmp))
                {
                    c[child] = c[father];
                    child = father;
                    father = (child - 1) / 2;
                }
                else
                    break;
            }

            c[child] = tmp;
        }


        void Adjust_Down()
        {
            size_t father = 0;
            size_t child = father * 2 + 1;
            T tmp;
            Compare cmp;
            if (size() > 0)
                tmp = c[0];
            else return;

            while (child < size())
            {
                //if (child + 1 < size() && c[child] < c[child + 1])
                if (child + 1 < size() && cmp(c[child],c[child + 1]))
                    child++;

                //if (tmp < c[child])
                if(cmp(tmp, c[child]))
                {
                    c[father] = c[child];
                    father = child;
                    child = father * 2 + 1;
                }
                else
                    break;
            }

             c[father] = tmp;
        }

        bool empty() const
        {
            return c.empty();
        }

        size_t size() const
        {
            return c.size();
        }

        T& top() 
        {
            return c[0];
        }

        void push(const T& x)
        {
            c.push_back(x);

            Adjust_Up(size() - 1);
        }

        void pop()
        {
            std::swap(c[0], c[size() - 1]);
            c.pop_back();

            Adjust_Down();
        }

    private:
        Container c;
    };

};

测试:

void test01()
{
	//默认构造
	xu::priority_queue<int> q;
	//插入
	q.push(1);
	q.push(3);
	q.push(2);
	q.push(4);
	q.push(4);
	q.push(5);
	q.push(6);

	//判断
	while (!q.empty())
	{
		//队头元素
		cout << q.top() <<" ";
		//出队
		q.pop();
	}
	cout << endl;
}

void test02()
{
	vector<int> v{ 1,2,5,3,8 };
	//迭代器区间构造
	xu::priority_queue<int, vector<int>, xu::greater<int>> q(v.begin(),v.end());

	while (!q.empty())
	{
		cout << q.top() << " ";
		q.pop();
	}
	cout << endl;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉与模式识别实验2-1 角点检测算法(Harris,SUSAN,Moravec)

文章目录 &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1;Harris算法SUSAN算法Moravec算法 &#x1f9e1;&#x1f9e1;全部代码&#x1f9e1;&#x1f9e1; &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1; Harris算法 Harris算法实现步骤&…

数据容器的通用操作、字符串大小比较 总结完毕!

1.数据容器的通用操作 1&#xff09;五类数据容器是否都支持while循环/for循环 五类数据容器都支持for循环遍历 列表、元组、字符串都支持while循环&#xff0c;集合、字典不支持&#xff08;无法下标索引&#xff09; 尽管遍历的形式不同&#xff0c;但都支持遍历操作 2&a…

在电脑端实现多个微信同时登录[使用bat脚本登录]

在电脑端实现多个微信同时登录[使用bat脚本登录] 我认为工作和生活应该分开进行&#xff0c;但往往不尽人意。 第一步&#xff0c;找到微信启动程序地址。 第二步 创建txt文本&#xff0c;写入start 你的微信启动程序地址。 start D:\微信文件\WeChat\WeChat.exe start D:\微…

The First项目报告:一场由社区驱动的去中心化加密冒险—Turbo

2023年3月14日&#xff0c;由OpenAI公司开发自回归语言模型GPT-4发布上线&#xff0c;一时之间引发AI智能领域的轩然大波&#xff0c;同时受到影响的还有加密行业&#xff0c;一众AI代币纷纷出现大幅度拉升。与此同时&#xff0c;一款名为Turbo的Meme代币出现在市场中&#xff…

在美育浸润中成长 ——中山市光后中心小学张峻皓书画作品毕业汇报展成功举办

5 月 30 号下午 3 点&#xff0c;“在美育浸润中成长——广东省中山市光后中心小学张峻皓书画作品毕业汇报展”在中山市三乡镇光后中心小学成功举行&#xff0c;本次共展出张峻皓同学近期创作书法、国画及陶瓷作品共计78幅。 广东省中山市文联兼职副主席、中山市书法家协会主席…

【距离四六级只剩一个星期!】刘晓艳四级保命班课程笔记(1)(可分享治资料~)

大家好&#xff01;距离四级考试也就只剩下一个星期左右了&#x1f635;‍&#x1f4ab;。我也是时候好好补一补四级了&#xff0c;总不能还是不过吧&#x1f62d;&#xff08;已经考了两次了&#xff09;&#xff0c;这次我一定过过过过过过&#xff0c;大家也一定要过&#x…

若依前后端分离Spring Security新增手机号登录

备忘贴 转自&#xff1a;【若依RuoYi短信验证码登录】汇总_数据库_z_xiao_qiang-RuoYi 若依 配置Security: 按照Security的流程图可知&#xff0c;实现多种方式登录&#xff0c;只需要重写三个主要的组件&#xff0c;第一个用户认证处理过滤器&#xff0c;第二个用户认证tok…

Linux Shell脚本编写指南

大家好&#xff0c;在当今快节奏的科技时代&#xff0c;自动化和高效的工作流程对于个人和组织来说变得愈发重要。而Shell脚本编写作为一种强大且广泛应用的技能&#xff0c;成为了实现自动化任务和系统管理的利器。通过编写Shell脚本&#xff0c;我们可以将繁琐的重复任务自动…

【Matplotlib作图-4.Distribution】50 Matplotlib Visualizations, Python实现,源码可复现

目录 04 Distribution 4.0 Prerequisite 4.1 连续变量的直方图(Histogram for Continuous Variable) 4.2 分类变量的直方图(Histogram for Categorical Variable) 4.3 Density Plot 4.4 Density Curves with Histogram 4.5 Joy Plot 4.6 Distributed Dot Plot 4.7 Box P…

前端 video 实现全屏播放

只需要加上这句代码就行 controls <videoid"myVideo":src"detailDate.linkAddress":poster"detailDate.pictureUrl"enable-danmucontrolswebkit-playsinline"true"></video>

绘画参数配置及使用

绘画参数配置及使用 路径&#xff1a;站点后台-功能-AI绘画 进入参数配置 接口选择&#xff1a;多种接口自主选择&#xff08;需自己准备key&#xff09;&#xff0c;对应接口的key对话和绘画通用 存储空间&#xff1a; 位置在超管后台-存储空间 自主选择存储&#xff08;需…

【STL源码剖析】deque 的使用

别院深深夏席清&#xff0c;石榴开遍透帘明。 树阴满地日当午&#xff0c;梦觉流莺时一声。 目录 deque 的结构 deque 的迭代器剖析 deque 的使用 ​编辑 deque 的初始化 deque 的容量操作 deque 的访问操作 在 pos 位置插入另一个向量的 [forst&#xff0c;last] 间的数据​编…

JVMの堆、栈内存存储

1、JVM栈的数据存储 通过前面的学习&#xff0c;我们知道&#xff0c;将源代码编译成字节码文件后&#xff0c;JVM会对其中的字节码指令解释执行&#xff0c;在解释执行的过程中&#xff0c;又利用到了栈区的操作数栈和局部变量表两部分。 而局部变量表又分为一个个的槽位&…

web安全基础学习笔记

这里写目录标题 1.使用hackbar2.php漏洞基本分析 弱类型语言2.2 php漏洞找到隐藏的源代码之 index.php~2.3 php漏洞找到隐藏的源代码之 vim的临时文件 /.index.php.swp3.php漏洞基本分析 数组 3.php漏洞基本分析 extract4.php漏洞基本分析 strpos eregi函数漏洞4.php漏洞基本分…

Java web应用性能分析之【java进程问题分析定位】

Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 Java web应用性能分析之【java进程问题分析工具】-CSDN博客 Java web应用性能分析之【jvisualvm远程连接云服务器】-CSDN博客 由于篇幅限制、前面三篇讲了准备工作和分析小结&#xff0c;这里将详细操作java进程问题…

The First项目报告:去中心化知识产权治理协议MON Protocol如何革新链游产业?

2023年12月&#xff0c;RPG NFT 游戏 Pixelmon 首席执行官 GiulioX 在 X 平台表示&#xff0c;确认将推出代币 MON&#xff0c;代币生成&#xff08;TGE&#xff09;时间将取决于 MON 的路线图和主流 CEX 的启动板队列。12 月 11 日&#xff0c;RPG NFT 游戏 Pixelmon 首席执行…

防爆AGV叉车在现代物流行业的应用

AGV 随着机器人技术在中国的快速发展&#xff0c;国内企业开始推出区别于传统叉车的叉车AGV&#xff0c;旨在为企业降本增效&#xff0c;降低人工成本与对人的依赖&#xff1b;同时&#xff0c;也将人工从危险恶劣的环境中解放出来。随着技术的持续提升&#xff0c;叉车AGV已经…

API低代码平台介绍4-数据库记录插入功能

数据库记录插入功能 本篇文章我们将介绍如何使用ADI平台定义一个向目标数据库插入记录的接口&#xff0c;包括手工组装报文单表插入、手工组装报文多表插入、自动组装报文多表插入三种方式。无论是单表插入还是多表插入&#xff0c;任何一条记录写入失败&#xff0c;那么默认情…

kvm学习 - 迅速上手示例

目录 kvmtool kvmsample kvmtool GitHub - kvmtool/kvmtool: Stand-alone Native Linux KVM Tool repoStand-alone Native Linux KVM Tool repo. Contribute to kvmtool/kvmtool development by creating an account on GitHub.https://github.com/kvmtool/kvmtool.git cd …

17.Redis之主从复制

1.主从复制是怎么回事&#xff1f; 分布式系统, 涉及到一个非常关键的问题: 单点问题 单点问题&#xff1a;如果某个服务器程序, 只有一个节点(只搞一个物理服务器, 来部署这个服务器程序) 1.可用性问题,如果这个机器挂了,意味着服务就中断了~ 2.性能/支持的并发量也是比较有限…