C++中priority_queue模拟实现的代码示例

 更新时间:2021年08月29日 10:35:50   作者:可乐不解渴  
在c++语言中数据结构中的堆结构可以通过STL库中的priority_queue 优先队列来实现,这样做极大地简化了我们的工作量,这篇文章主要给大家介绍了关于C++中priority_queue模拟实现的相关资料,需要的朋友可以参考下

priority_queue概述

priority_queue定义

  • 优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。

priority_queue特点

  • 优先队列是一种容器适配器,首先要包含头文件 #include<queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。
  • 优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
  • 注意:默认情况下priority_queue是大根堆。如果想让其生成小根堆,需要使用到仿函数或者Lambda表达式。

构造函数

由于priority_queue是一种容器适配器,适配的是vector,我们在vector中已经写过它的构造函数了。故priority_queue在此不需要多余的其他构造函数。

// 创造空的优先级队列
priority_queue():m_priority_queue()
{

}

template<class Iterator>
priority_queue(Iterator first, Iterator last)
	: m_priority_queue(first, last)
{
	// 将m_priority_queue中的元素调整成堆的结构
	int count = m_priority_queue.size();
	int root = ((count - 2) >> 1);
	for (; root >= 0; root--)
	AdjustDown(root);
}

修改相关函数

push

功能:push函数用来往堆中(尾部)插入一个元素,并向上调整成新的堆。

//向上调整
void AdjustUp(int child)
{
	int parent = (child-1)>>1;
	
	while (child > 0)
	{
		//其中c是一个对象,用该对象去调用仿函数来进行比较
		if (c(m_priority_queue[parent], m_priority_queue[child]))
		{
			std::swap(m_priority_queue[parent], m_priority_queue[child]);
			child = parent;
			parent = (child - 1) >> 1;
		}
		else
		{
			break;
		}
	}

}

void push(const T& val)
{
	m_priority_queue.push_back(val);
	AdjustUp(m_priority_queue.size()-1);
}

pop

功能:pop函数弹出堆顶元素。具体步骤是:堆顶元素与最后一个数字进行交换位置。之后在进行尾删来删除堆顶。再重新向下调堆。

//向下调堆
void AdjustDown(int parent)
{
	int child = (parent << 1) + 1;
	int size = static_cast<int>(m_priority_queue.size());

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

		if (c(m_priority_queue[parent], m_priority_queue[child]))
		{
			std::swap(m_priority_queue[parent], m_priority_queue[child]);
			parent = child;
			child = (parent << 1) + 1;
		}
		else
		{
			break;
		}
	}
}

void pop()
{
	assert(!m_priority_queue.empty());

	std::swap(m_priority_queue[0], m_priority_queue[m_priority_queue.size()- 1]);
	m_priority_queue.pop_back();
	AdjustDown(0);
}

容量相关函数

size

功能:用来获取堆中的元素个数。

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

empty

功能:用来判断堆中是否为空。

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

元素访问相关函数

top

功能:用来获取堆顶的元素。

T& top()
{
	return m_priority_queue.front();
}

const T& top()	const
{
	return m_priority_queue.front();
}

代码实现

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<assert.h>
namespace ZJ
{
	template<class T>
	class less
	{
	public:
		bool operator() (const T& x, const T& y) const
		{
			return x < y;
		}
	};

	template<class T>
	class greater
	{
	public:
		bool operator() (const T& x, const T& y) const
		{
			return x > y;
		}
	};
	template<class T,class Container=std::vector<T>, class Compare = ZJ::less<T>>
	class priority_queue
	{
	public:
		// 创造空的优先级队列
		priority_queue():m_priority_queue()
		{

		}

		template<class Iterator>
		priority_queue(Iterator first, Iterator last)
			: m_priority_queue(first, last)
		{
			// 将m_priority_queue中的元素调整成堆的结构
			int count = m_priority_queue.size();
			int root = ((count - 2) >> 1);
			for (; root >= 0; root--)
			AdjustDown(root);
		}
	public:

		//向上调整
		void AdjustUp(int child)
		{
			int parent = (child-1)>>1;
			
			while (child > 0)
			{
				if (c(m_priority_queue[parent], m_priority_queue[child]))
				{
					std::swap(m_priority_queue[parent], m_priority_queue[child]);
					child = parent;
					parent = (child - 1) >> 1;
				}
				else
				{
					break;
				}
			}

		}
		void push(const T& val)
		{
			m_priority_queue.push_back(val);
			AdjustUp(m_priority_queue.size()-1);
		}

		void AdjustDown(int parent)
		{
			int child = (parent << 1) + 1;
			int size = static_cast<int>(m_priority_queue.size());

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

				if (c(m_priority_queue[parent], m_priority_queue[child]))
				{
					std::swap(m_priority_queue[parent], m_priority_queue[child]);
					parent = child;
					child = (parent << 1) + 1;
				}
				else
				{
					break;
				}
			}
		}

		void pop()
		{
			assert(!m_priority_queue.empty());

			std::swap(m_priority_queue[0], m_priority_queue[m_priority_queue.size()- 1]);
			m_priority_queue.pop_back();
			AdjustDown(0);
		}

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

		T& top()
		{
			return m_priority_queue.front();
		}

		const T& top()	const
		{
			return m_priority_queue.front();
		}

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

	private:
		Container m_priority_queue;
		Compare c;
	};
}

总结

到此这篇关于C++中priority_queue模拟实现的文章就介绍到这了,更多相关C++ priority_queue模拟实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++ map 根据value找key的实现

    C++ map 根据value找key的实现

    今天小编就为大家分享一篇C++ map 根据value找key的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • opencv3/C++ 实现SURF特征检测

    opencv3/C++ 实现SURF特征检测

    今天小编就为大家分享一篇opencv3/C++ 实现SURF特征检测,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • 基于C++实现俄罗斯方块游戏的示例代码

    基于C++实现俄罗斯方块游戏的示例代码

    俄罗斯方块(Tetris)是一款风靡全球的经典益智游戏,自1984年首次发布以来,便吸引了无数玩家,在这篇博文中,我们将深入探讨如何用 C++ 编写一个简单的俄罗斯方块游戏,我们将从游戏的基本概念和设计入手,逐步实现游戏的各个功能模块,感兴趣小伙伴快来看看吧
    2024-11-11
  • c语言求余数的实例讲解

    c语言求余数的实例讲解

    在本篇文章里小编给大家整理的是关于c语言如何求余数的相关知识点内容,有需要的朋友们可以学习下。
    2020-02-02
  • C++用Dijkstra(迪杰斯特拉)算法求最短路径

    C++用Dijkstra(迪杰斯特拉)算法求最短路径

    Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。下面这篇文章就给大家介绍关于C++用Dijkstra算法(迪杰斯特拉算法)求最短路径的方法,下面来一起看看吧。
    2016-12-12
  • 使用Qt/C++实现WGS84,高德GCJ-02与百度BD-09坐标系间相互转化

    使用Qt/C++实现WGS84,高德GCJ-02与百度BD-09坐标系间相互转化

    这篇文章主要为大家详细介绍了如何使用Qt实现WGS84、高德GCJ-02与百度BD-09坐标系间相互转化,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-07-07
  • C++如何获取本机的IP地址

    C++如何获取本机的IP地址

    这篇文章主要为大家详细介绍了C++如何获取本机IP地址小程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C语言的动态内存管理的深入了解

    C语言的动态内存管理的深入了解

    这篇文章主要为大家详细介绍了语言C的动态内存管理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • EasyC++模板显式具体化

    EasyC++模板显式具体化

    这篇文章主要介绍了C++模板显式具体化,在C++中,可以提供一个具体化函数定义称为具体显式化(explict specialization)。其中包含所需的代码,当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不再寻找模板,下面我们来看看文章具体介绍吧
    2021-12-12
  • C语言学习之关键字的示例详解

    C语言学习之关键字的示例详解

    关键字,这名字一听,就很关键。而有些关键字,你可能不是很了解,更别谈使用。所以,这篇文章将带你见识常见的关键字,一起领略它们的风采吧
    2022-10-10

最新评论