C++priority_queue模拟实现

Posted 可乐不解渴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++priority_queue模拟实现相关的知识,希望对你有一定的参考价值。

做一个干净洒脱的人,往事不记,后事不提。

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++priority_queue模拟实现

C++priority_queue模拟实现与仿函数讲解

C++priority_queue模拟实现与仿函数讲解

C++stack和queue及适配器的学习使用

STL详解—— priority_queue的使用与模拟实现