Cola de prioridad [C++]

prioridad_cola

La cola de prioridad (priority_queue) también es un tipo de cola, y la interfaz de la cola de prioridad es la misma que la de la cola. Entonces, la sintaxis de uso de ambos es la misma. Veamos directamente el principio de implementación subyacente de la cola de prioridad (priority-queue).

Por defecto, la cola de prioridad es un gran montón.

usos de la cola de prioridad

//用vector作为底层容器,内部构造大堆结构。
priority_queue<int, vector<int>, less<int>> q1;
//用vector作为底层容器,内部构造小堆结构。
priority_queue<int, vector<int>, greater<int>> q2;
//不指定底层容器和内部需要构造的堆结构。
priority_queue<int> q3;
#include <iostream>
#include <functional>
#include <queue>
using namespace std;
int main()
{
    
    
	priority_queue<int> q;
	q.push(3);
	q.push(6);
	q.push(0);
	q.push(2);
	q.push(9);
	q.push(8);
	q.push(1);
	while (!q.empty())
	{
    
    
		cout << q.top() << " ";
		q.pop();
	}
	cout << endl; //9 8 6 3 2 1 0
	return 0;
}

Implementación analógica de priority_queue

La capa inferior de la cola de prioridad es en realidad un montón. Antes de simular la cola de prioridad, debe conocer los algoritmos de ajuste hacia abajo y hacia arriba. (Los siguientes dos algoritmos los usamos como ejemplo)

Ajustar algoritmo hacia arriba

La premisa del algoritmo de ajuste ascendente:
si desea ajustarlo a un montón pequeño, los subárboles izquierdo y derecho del nodo raíz deben ser montones pequeños.
 Si desea ajustarlo a un montón grande, los subárboles izquierdo y derecho del nodo raíz deben ser grandes montones

Para insertar datos en el montón, debe usar el algoritmo de ajuste ascendente
para insertar primero el elemento al final del montón, es decir, después del último elemento secundario, y compararlo con el nodo principal desde la posición del nodo insertado ( tomamos un montón grande como ejemplo), si el nodo de destino Si el valor es mayor que el valor del nodo principal, la posición del nodo de destino y su nodo principal se intercambiarán, y el nodo principal del nodo de destino original se considerará como el nuevo nodo de destino, y el ajuste continuará hasta que finalice el nodo raíz. En este momento, el árbol ya tiene mucho

En la figura, se toma como ejemplo un pequeño montón:
inserte la descripción de la imagen aquí

algoritmo de ajuste a la baja

La premisa del algoritmo de ajuste descendente:
si desea ajustarlo a un montón pequeño, los subárboles izquierdo y derecho del nodo raíz deben ser montones pequeños.
 Si desea ajustarlo a un montón grande, entonces los subárboles izquierdo y derecho del nodo raíz deben ser grandes montones

Comenzando desde el nodo raíz, seleccione el nodo con el valor mayor de los elementos secundarios izquierdo y derecho, y compare los valor del nodo con el valor mayor con el valor del nodo principal, si el nodo con un valor mayor es menor que el valor del nodo principal, intercambie las posiciones de los dos y use el nodo secundario con un valor mayor como el nodo principal, continúe ajustando hacia abajo y ajuste hasta el final del nodo hoja

En la figura, se toma como ejemplo un pequeño montón:
inserte la descripción de la imagen aquí

empujar

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

estallido

	void pop()
		{
    
    
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}

arriba

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

tamaño

bool size()
		{
    
    
			return _con.size();
		}	

vacío

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

funtor

using namespace std;
//仿函数 /函数对象
template <class T>
class Less
{
    
    
public:
	bool operator() (const T& x, const T& y)
	{
    
    
		return x < y;
	}
};

int main()
{
    
    
	Less<int>  lessfunc;
	bool result = lessfunc(6, 2);//仿函数
	//bool result = lessfunc.operator()(6, 2);
	cout <<boolalpha <<result << endl;
	return 0;
}

código completo

#pragma once 
#include<vector>
#include<functional>
using namespace std;

//仿函数 /函数对象
template <class T>
class Less
{
    
    
public:
	bool operator() (const T& x, const T& y)
	{
    
    
		return x < y;
	}
};
template <class T>
class Greater
{
    
    
public:
	bool operator() (const T& x, const T& y)
	{
    
    
		return x > y;
	}
};

namespace cxq
{
    
    
	template<class T, class Container = vector<T>, class Compare = Less<T> >
	class priority_queue
	{
    
    
	private:
		void AdjustDown(int parent)//从根节点开始
		{
    
    
			Compare com;//仿函数
			int child = parent * 2 + 1;
			while (child < _con.size())
			{
    
    
				//假设默认左孩子大于右孩子
			   // if (child + 1 < _con.size() && _con[child + 1] > _con[child])//右孩子要存在,防止越界
				if (child + 1 < _con.size() && com(_con[child + 1], _con[child]))
				{
    
    
					child++;
				}
				//if (_con[child] > _con[parent])
				if (com(_con[parent], _con[child]))
				{
    
    
					swap(_con[child], _con[parent]);
					int  parent = child;
					child = parent * 2 + 1;
				}
				else
				{
    
    
					break;
				}
			}

		}
		void AdjustUp(int child)
		{
    
    
			Compare com;//仿函数
			int parent = (child - 1) / 2;
			//大堆

			while (child > 0)
			{
    
    
				//if (_con[child] > _con[parent])
				if (com(_con[parent], _con[child]))
				{
    
    
					swap(_con[child], _con[parent]);
					int child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
    
    
					break;
				}
			}
		}
	public:
		//默认构造
		priority_queue()
		{
    
    }
		template<class InputIterator>
		//构造函数
		priority_queue(InputIterator first, InputIterator last)
		{
    
    
			while (first != last)
			{
    
    
				_con.push_back(*first);
				first++;
			}
			//建堆
			//最后一个非叶子节点
			for (size_t i = (_con.size() - 1 - 1) / 2; i >= 0; i++)
			{
    
    
				AdjustDown(i);
			}
		}
		void pop()
		{
    
    
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();
			AdjustDown(0);
		}
		void push(const T& x)
		{
    
    
			_con.push_back(x);
			AdjustUp(_con.size() - 1);
		}
		const T& top()
		{
    
    
			return _con[0];
		}
		bool empty()
		{
    
    
			return _con.empty();
		}
		bool size()
		{
    
    
			return _con.size();
		}
	private:
		Container _con;

	};
	void test_priority_queue1()
	{
    
    
		//默认是大堆--less
		//priority_queue<int> pq;
		priority_queue<int, vector<int>, Greater<int> > pq;//小堆
		pq.push(3);
		pq.push(5);
		pq.push(1);
		pq.push(4);
		while (!pq.empty())
		{
    
    
			cout << pq.top() << " ";
			pq.pop();
		}
		cout << endl;
	}
	class Date
	{
    
    
	public:
		Date(int year = 1900, int month = 1, int day = 1)
			: _year(year)
			, _month(month)
			, _day(day)
		{
    
    }

		bool operator<(const Date& d)const
		{
    
    
			return (_year < d._year) ||
				(_year == d._year && _month < d._month) ||
				(_year == d._year && _month == d._month && _day < d._day);
		}

		bool operator>(const Date& d)const
		{
    
    
			return (_year > d._year) ||
				(_year == d._year && _month > d._month) ||
				(_year == d._year && _month == d._month && _day > d._day);
		}

		friend ostream& operator<<(ostream& _cout, const Date& d);//声明
	private:
		int _year;
		int _month;
		int _day;
	};
	
	ostream& operator<<(ostream& _cout, const Date& d)
	{
    
    
		_cout << d._year << "-" << d._month << "-" << d._day;
		return _cout;
	}
	struct  LessPDate
	{
    
    
		//仿函数
		bool operator() ( const Date * p1 , const Date* p2)
		{
    
    
			return *p1 < *p2;
		}
	};
	void test_priority_queue2()
	{
    
    
		//priority_queue<Date> pq;
		//pq.push(Date(2023, 7, 20));
		//pq.push(Date(2023, 6, 20));
		//pq.push(Date(2023, 8, 20));
		//while (!pq.empty())
		//{
    
    
		//	cout << pq.top() << " ";
		//	pq.pop();
		//}
		//cout << endl;
		priority_queue<Date*, vector<Date*>, LessPDate> pq;
		pq.push(new Date(2023, 7, 20));
		pq.push(new Date(2023, 6, 20));
		pq.push(new Date(2023, 8, 20));
		while (!pq.empty())
		{
    
    
			cout << *pq.top() << " ";
			pq.pop();
		}
		cout << endl;
	}
	
}

Supongo que te gusta

Origin blog.csdn.net/qq_73478334/article/details/132332960
Recomendado
Clasificación