[C++] STL usa funtores para controlar la cola de prioridad Priority_queue



prefacio

Este artículo explica el adaptador de contenedor STL de C++: la implementación de priority_queue e implementa el functor para controlar la capa inferior de priority_queue.


1. La implementación subyacente de priority_queue

Priority_queue se denomina cola de prioridad y su estructura subyacente es un montón. En la biblioteca, se genera un gran montón de forma predeterminada.
inserte la descripción de la imagen aquí
En la implementación de la biblioteca, el vector se utiliza como contenedor de adaptación de la cola de prioridad.

Como Priority_queue también es un adaptador, sus funciones de interfaz también se pueden usar para encapsular funciones de otros contenedores.

inserte la descripción de la imagen aquí
Simulemos la implementación de priority_queue.


#pragma once

//优先级队列底层是堆,heap
namespace bit
{
    
    
	//仿函数
	template<class T>
	class Less
	{
    
    
	public:
		bool operator()(const T& t1, const T& t2)
		{
    
    
			return t1 < t2;
		}

	};

	template<class T>
	class Greater
	{
    
    
	public:
		bool operator()(const T& t1, const T& t2)
		{
    
    
			return t1 > t2;
		}

	};

	//类名不是类型
	template<class T, class Container = vector<T>, class Compare = Less<T> >
	//默认大堆
	class PriorityQueue
	{
    
    
		//com是一个仿函数
		Compare com;
		void AdjustDown(int parent)
		{
    
    
			int child = parent * 2 + 1;
			while (child > 0)
			{
    
    
				//可能右孩子存在且大于左孩子
				if (child + 1 < _con.size() && com(_con[child],_con[child + 1]))
				{
    
    
					++child;
				}
				//如果孩子存在且孩子大于父亲,交换
				if (child < _con.size() && com(_con[parent],_con[child]))
				{
    
    
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
    
    
					break;
				}
			}
		}

		void AdjustUp(int child)
		{
    
    
			Compare com;
			//类名实例化类对象,该类型是一个仿函数,实例化的com可以调用仿函数的比较方法
			//记录父亲的下标
			int parent = (child - 1) / 2;

			while (child > 0)
			{
    
    	
				if (com(_con[parent], _con[child]))
				{
    
    
					swap(_con[child], _con[parent]);
				}
				child = parent;
				parent = (child - 1) / 2;
			}
		}

	public:

		PriorityQueue()
		{
    
    }

		//默认建大堆
		template<class InputIterator>
		PriorityQueue(InputIterator first, InputIterator end)
		{
    
    
			//插入数据
			while (first != end)
			{
    
    
				_con.push_back(*first);
				++first;
			}
			//向下调整建堆
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
			{
    
    
				AdjustDown(i);
			}
		}

		void push(const T& val)
		{
    
    
			//插入元素
			_con.push_back(val);
			//然后向上调整
			AdjustUp(_con.size() - 1);
		}

		void pop()
		{
    
    
			//1.堆顶和堆尾交换
			swap(_con[0], _con[_con.size() - 1]);

			//2.删除堆尾
			_con.pop_back();

			//3.向下调整,恢复堆
			AdjustDown(0);
		}

		T& top() 
		{
    
    
			 return _con[0];
		}
		
		size_t size() const
		{
    
    
			return _con.size();
		}

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

	private:
		Container _con;

anotación:

  • 1. Al construir, usamos intervalos iterativos para la construcción
    • (1) Insertar datos en el espacio
    • (2) Ajuste el montón hacia abajo, cree N datos, comience a construir el montón desde el primer nodo que no sea hoja y ajuste hacia abajo cada vez, la complejidad del tiempo es O (N).

La implementación de la función push:
inserte un elemento al final del montón. El elemento insertado puede cambiar la estructura del montón, por lo que debemos ajustar el elemento hacia arriba para mantener las características del montón.

Implementación de la función pop:
para eliminar el elemento superior del montón, primero intercambie el elemento superior con el último elemento del montón y luego realice la eliminación final. Después de la eliminación, el elemento al final del montón ahora está en la parte superior del montón, y debemos ajustarlo hacia abajo para mantener el estado del montón.

función vacía:
simplemente juzgue si el montón está vacío.

función de tamaño:
calcula el número de elementos en el montón.

función superior:
toma el elemento superior del montón, es decir, toma el primer elemento.

La función del contenedor Priority_queue: el contenedor se puede usar donde sea necesario usar el montón.

2. Usa el funtor para controlar la capa inferior de la cola de prioridad

¿Qué es un funtor?
Functor: Una función falsa que no es una función real. Puede sobrecargar operator(), implementar el método que desea internamente y luego crear una instancia de un objeto de método, llamar al objeto como un parámetro, luego puede llamar al método operator() implementado dentro del objeto de clase de método.

Dado que la estructura subyacente de la cola de prioridad en la biblioteca es un montón, y el valor predeterminado es un montón grande, cuando simulamos la implementación y el uso, si nos encontramos con un escenario en el que se requiere un montón pequeño, hay muchas cosas que deben cambiarse, como el método de comparación entre el algoritmo de ajuste ascendente y el algoritmo de ajuste descendente.
Ahora necesitamos especificar un método, que podamos controlar, para lograr el tamaño del montón.

funtor:

//仿函数
template<class T>
class Less
{
    
    
public:
	bool operator()(const T& t1, const T& t2)
	{
    
    
		return t1 < t2;
	}

};

template<class T>
class Greater
{
    
    
public:
	bool operator()(const T& t1, const T& t2)
	{
    
    
		return t1 > t2;
	}

};

Aquí se implementan dos clases y se sobrecarga un método de comparación.
En la implementación de la plantilla priority_queue, podemos pasar un parámetro de plantilla más: class Compare, es decir, pasar un método de comparación más. Luego escribimos un método de comparación y lo pasamos, y luego creamos una instancia de un objeto de método en la implementación de priority_queue para controlar la generación del montón.


Resumir

Este artículo explica el proceso de control del functor de la implementación subyacente del contenedor de la cola de prioridad y la implementación subyacente de la cola de prioridad.

El contenedor de prioridad_cola se puede utilizar dondequiera que haya un montón.

Supongo que te gusta

Origin blog.csdn.net/w2915w/article/details/131872310
Recomendado
Clasificación