Tabla de contenido
1.2 La estructura subyacente de pila y cola en la biblioteca estándar STL
1.3.1 Introducción al principio deque (comprensión)
1.3.2 Ventajas y desventajas de deque
1.3.3 ¿Por qué elegir deque como el contenedor predeterminado subyacente de pila y cola?
2. Introducción y uso de la pila
2.3 implementación de simulación de pila
3. Introducción y uso de la cola
3.3 implementación de la simulación de colas
4.1 Introducción a la cola de prioridad
4.2 Uso de la cola de prioridad
4.3 implementación de simulación de cola de prioridad
1. Adaptador de contenedor
1.1 ¿Qué es un adaptador?
1.2 La estructura subyacente de pila y cola en la biblioteca estándar STL
1.3 y
1.3.1 Introducción al principio deque (comprensión)
¿Cómo mantiene deque su estructura continua hipotética con la ayuda de su iterador?
1.3.2 Ventajas y desventajas de deque
deque: 1. El cálculo del operador [ ] es un poco complicado, se usa en grandes cantidades y el rendimiento cae (en comparación con el vector)
2. La eficiencia de inserción y eliminación en el medio no es alta
3. Los iteradores angulares subyacentes pueden ser complejos
1.3.3 ¿Por qué elegir deque como el contenedor predeterminado subyacente de pila y cola?
1. La inserción y la eliminación de la cabeza a la cola son muy adecuadas. En comparación con el vector y la lista, es muy adecuado para el contenedor de adaptación predeterminado de pila y cola.
2. Inserte y elimine la lista de usos múltiples en el medio
3. Vector multipropósito de acceso aleatorio
2. Introducción y uso de la pila
Introducción a la pila 2.1
- stack es un adaptador de contenedor, que se usa especialmente en el entorno de contexto con la operación de último en entrar, primero en salir, y su eliminación solo puede insertar y extraer elementos de un extremo del contenedor .
- La pila se implementa como un adaptador de contenedor, que encapsula una clase específica como su contenedor subyacente y proporciona un conjunto de funciones de miembro específicas para acceder a sus elementos, utilizando una clase específica como su cola de contenedor específica de elemento subyacente (es decir, la parte superior de la pila) se empuja y se abre.
- El contenedor subyacente de la pila puede ser cualquier plantilla de clase de contenedor estándar o alguna otra clase de contenedor específica, y estas clases de contenedor deben admitir las siguientes operaciones:
vacío: juicio vacío operación
tamaño: devuelve el número de elementos válidos en la pila
back: Obtener la operación del elemento de cola
push_back: operación de elemento de inserción de cola
pop_back: operación de elemento de eliminación de cola
- Los contenedores estándar vector, deque y list cumplen todos estos requisitos. De manera predeterminada, si no se especifica ningún contenedor subyacente específico para la pila, se usa deque de manera predeterminada.
2.2 uso de pila
función descriptiva |
Descripción de la interfaz
|
pila() | construir una pila vacía |
vacío() | Comprobar si la pila está vacía |
tamaño() | Devuelve el número de elementos en la pila. |
arriba() | Devuelve una referencia al elemento superior de la pila. |
empujar() | Empuje el elemento val en la pila |
estallido() | Pop el elemento al final de la pila |
2.3 implementación de simulación de pila
template<class T,class Container=deque<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
T& top()
{
return _con.back();
}
const T& top() const
{
return _con.back();
}
bool empty() const
{
return _con.empty();
}
size_t size() const
{
return _con.size();
}
private:
Container _con;
};
3. Introducción y uso de la cola
3.1 Introducción a la cola
- Una cola es un adaptador de contenedor diseñado para operar en un contexto FIFO (primero en entrar, primero en salir), donde los elementos se insertan desde un extremo del contenedor y se extraen desde el otro.
- Una cola se implementa como un adaptador de contenedor, que encapsula una clase de contenedor específica como su clase de contenedor subyacente, y la cola proporciona un conjunto específico de funciones miembro para acceder a sus elementos. Los elementos ingresan a la cola desde la cola y salen de la cola desde la cabeza.
- El contenedor subyacente puede ser una de las plantillas de clase de contenedor estándar u otra clase de contenedor especialmente diseñada. El contenedor subyacente soportará al menos las siguientes operaciones:
vacío: comprobar si la cola está vacíatamaño: devuelve el número de elementos válidos en la colafront: Devuelve una referencia al elemento frontal de la colaatrás: devuelve una referencia al elemento al final de la colapush_back: ingrese a la cola al final de la colapop_front: fuera de la cola al principio de la cola
- Las clases de contenedor estándar deque y list cumplen estos requisitos. De forma predeterminada, si no se especifica ninguna clase de contenedor para la creación de instancias de cola, se utiliza el deque de contenedor estándar.
3.2 Uso de colas
declaración de función | Descripción de la interfaz |
cola() | construir una cola vacía |
vacío() | Compruebe si la cola está vacía, devuelva verdadero, de lo contrario, devuelva falso |
tamaño() | Devuelve el número de elementos válidos en la cola |
frente() | Devuelve una referencia al elemento al principio de la cola. |
atrás() | Devuelve una referencia al elemento al final de la cola. |
empujar() | Poner en cola el elemento val al final de la cola |
estallido() | Desencolar el elemento al principio de la cola |
3.3 implementación de la simulación de colas
template<class T,class Container=deque<int>>
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
T& back()
{
return _con.back();
}
T& front()
{
return _con.front();
}
const T& back() const
{
return _con.back();
}
const T& front() const
{
return _con.front();
}
bool empty() const
{
return _con.empty();
}
size_t size() const
{
return _con.size();
}
private:
Container _con;
};
4. prioridad_cola
4.1 Introducción a la cola de prioridad
Un funtor , también conocido como objeto de función (Objeto de función), es una clase que puede realizar funciones de función.
La sintaxis del funtor es casi la misma que nuestra llamada de función ordinaria, pero como una clase del funtor, el operador operator() debe estar sobrecargado . Porque llamar al funtor es en realidad llamar al operador operator() sobrecargado a través del objeto de clase.
- Una cola de prioridad es un adaptador de contenedor cuyo primer elemento es siempre el más grande de los elementos contenidos de acuerdo con estrictos criterios de ordenamiento débil.
- Este contexto es similar a un montón, donde los elementos se pueden insertar en cualquier momento y solo se puede recuperar el elemento de montón más grande (el que está en la parte superior de la cola de prioridad).
- La cola de prioridad se implementa como un adaptador de contenedor, que encapsula una clase de contenedor específica como su clase de contenedor subyacente, y la cola proporciona un conjunto de funciones miembro específicas para acceder a sus elementos. Los elementos se extraen de la "cola" de un contenedor en particular, que se denomina la parte superior de la cola de prioridad.
- El contenedor subyacente puede ser cualquier plantilla de clase de contenedor estándar o cualquier otra clase de contenedor de un diseño específico. Los contenedores deben ser accesibles a través de iteradores de acceso aleatorio y admitir las siguientes operaciones:
vacío (): comprueba si el contenedor está vacíosize(): Devuelve el número de elementos válidos en el contenedorfront(): devuelve una referencia al primer elemento del contenedorpush_back(): inserta elementos al final del contenedorpop_back(): elimina el elemento de cola del contenedor
- Las clases de contenedor estándar vector y deque satisfacen estas necesidades. De forma predeterminada, se utiliza vector si no se especifica ninguna clase de contenedor para una instancia de clase de prioridad_cola en particular.
- Los iteradores de acceso aleatorio deben admitirse para que la estructura del montón siempre se mantenga internamente. El adaptador de contenedor hace esto automáticamente llamando automáticamente a las funciones algorítmicas make_heap, push_heap y pop_heap cuando es necesario.
4.2 Uso de la cola de prioridad
declaración de función | Descripción de la interfaz |
prioridad_cola() cola_prioridad(primero,último) |
Construir una cola de prioridad vacía |
vacío() | Detecta si la cola de prioridad está vacía, devuelve verdadero, de lo contrario, devuelve falso |
arriba() | Devuelve el elemento más grande (más pequeño) en la cola de prioridad, es decir, el elemento superior |
empujar() | Insertar elemento val en la cola de prioridad |
estallido() | Elimine el elemento más grande (más pequeño) en la cola de prioridad, es decir, el elemento superior del montón |
//构造一个空的优先队列(此优先队列默认为大顶堆)
priority_queue<int> big_heap;
//另一种构建大顶堆的方法
priority_queue<int,vector<int>,less<int> > big_heap2;
pequeño montón superior (orden ascendente)
//构造一个空的优先队列,此优先队列是一个小顶堆
priority_queue<int,vector<int>,greater<int> > small_heap;
Aviso:
Si usa menos y más, se requieren archivos de encabezado:
#include <functional>
Si coloca datos de tipo personalizado en la cola de prioridad, los usuarios deben proporcionar > o < sobrecarga en el tipo personalizado .
4.3 implementación de simulación de cola de prioridad
template<class T, class Container = vector<T>,class Compare=std::less<T>>
class priority_queue
{
public:
priority_queue()
{}
template<class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
_con.push_back(*first);
++first;
}
//建堆,(_con.size()-1-1)/2为末尾节点的父节点所在位置
for (int i = ((_con.size() - 1 - 1) / 2); i >= 0; i--)
{
//向下建堆logN
adjust_down(i);
}
}
//向上建堆
void adjust_up(size_t child)
{
/*size_t parent = (child - 1) / 2;
while (child > 0)
{
//建大堆
if (_con[parent] < _con[child])
{
std::swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}*/
Compare com;//仿函数,类对象像函数一样使用,重载operator()
size_t parent = (child - 1) / 2;
while (child > 0)
{
//建大堆
if (com(_con[parent],_con[child]))
{
std::swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
//先vector插入,再向上调整
_con.push_back(x);
adjust_up(_con.size() - 1);
}
//向下建堆
void adjust_down(size_t parent)
{
/*size_t child = parent * 2 + 1;
while (child < _con.size())
{
//选出左右孩子大的那一个
if (child + 1 < _con.size() && _con[child] < _con[child + 1])
{
++child;
}
//建大堆
if (_con[parent] < _con[child])
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}*/
Compare com;//仿函数,类对象像函数一样使用,重载operator()
size_t child = parent * 2 + 1;
while (child < _con.size())
{
//选出左右孩子大的那一个
if (child + 1 < _con.size() && com(_con[child] , _con[child + 1]))
{
++child;
}
//建大堆
if (com(_con[parent] , _con[child]))
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
//根与最右下边的孩子交换,vector尾删,再下调整
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top() const
{
return _con[0];
}
bool empty() const
{
return _con.empty();
}
size_t size() const
{
return _con.size();
}
private:
Container _con;
};
No entraré en detalles sobre el proceso de creación de montones aquí, y puede buscar el contenido de la estructura de datos para revisarlo usted mismo.