Adaptador de contenedor C ++ STL review (13)

STL proporciona tres tipos de adaptadores de contenedor, a saber, adaptador de pila de pila, adaptador de cola y adaptador de cola de prioridad priority_queue.
Inserte la descripción de la imagen aquí
En diferentes escenarios, debido a que diferentes contenedores secuenciales utilizan diferentes estructuras de datos en la parte inferior, la eficiencia de ejecución del adaptador de contenedor también es diferente.

1 pila

Un adaptador de pila es un contenedor con una apertura de un solo extremo. De hecho, el contenedor simula una estructura de almacenamiento de pila, es decir, si está almacenando datos o extrayendo datos de él, las operaciones solo se pueden implementar desde esta apertura.
Inserte la descripción de la imagen aquí
El comienzo del adaptador de pila se suele llamar la parte superior de la pila. Dado que el almacenamiento y la recuperación de datos solo se pueden realizar desde la parte superior de la pila, para acceder a los datos, el adaptador de pila tiene la característica de que solo se puede acceder al elemento superior en el adaptador cada vez, y solo al elemento en la parte superior de la pila Después de eso, se puede acceder a los elementos ubicados en la pila.
Los elementos almacenados en la pila cumplen con la regla de "último en entrar, primero en salir (LIFO)", y el adaptador de pila también sigue esta regla.

1 Creación de adaptador de contenedor de pila

Debido a que el adaptador de pila se encuentra en el archivo de encabezado en la forma de la clase de plantilla pila <T, Container = deque> (donde T es el tipo de elemento de almacenamiento y Container representa el tipo de contenedor subyacente), y se define en el espacio de nombres estándar. Por lo tanto, antes de crear el contenedor, el programa debe contener las siguientes 2 líneas de código:

#include <stack>
using namespace std;

1

Cree un adaptador de pila que no contenga ningún elemento y use el contenedor base deque predeterminado:

std::stack<int> values; 

La línea de código anterior crea con éxito un elemento de tipo int almacenable, y la capa inferior usa el adaptador de pila del contenedor base deque.

2

Como se mencionó anteriormente, la clase de plantilla stack <T, Container = deque> proporciona dos parámetros. Al especificar el segundo parámetro de tipo de plantilla, podemos usar otros contenedores secuenciales además del contenedor deque, siempre que el contenedor admita vacío (), el cinco funciones miembro de size (), back (), push_back (), pop_back () son suficientes.
Al introducir el adaptador, se mencionó que el contenedor serial contiene estas 5 funciones miembro al mismo tiempo, hay tres contenedores: vector, deque y list. Por tanto, el contenedor base del adaptador de pila puede ser cualquiera de ellos. Por ejemplo, a continuación se muestra cómo definir un adaptador de pila que usa el contenedor base de lista:

std::stack<std::string, std::list<int>> values;

3

Se puede usar un contenedor básico para inicializar el adaptador de pila, siempre que el tipo de contenedor sea el mismo que el contenedor básico usado en la parte inferior de la pila. P.ej:

std::list<int> values {
    
    1, 2, 3};
std::stack<int,std::list<int>> my_stack(values);

Tenga en cuenta que en el adaptador my_stack después de la inicialización, el elemento superior de la pila es 3, no 1. Además, en la segunda línea de código, el segundo parámetro de plantilla de la pila debe especificarse explícitamente como una lista (debe ser de tipo int, consistente con el tipo de almacenamiento); de lo contrario, la capa inferior de la pila utilizará el contenedor deque. de forma predeterminada, y no se puede utilizar el contenido del contenedor lsit Para inicializar el adaptador de pila.

4

También puede utilizar un adaptador de pila para inicializar otro adaptador de pila, siempre que el tipo de elemento que almacenan y el tipo de contenedor subyacente sean los mismos. P.ej:

std::list<int> values{
    
     1, 2, 3 };
std::stack<int, std::list<int>> my_stack1(values);
std::stack<int, std::list<int>> my_stack = my_stack1;
//std::stack<int, std::list<int>> my_stack(my_stack1);

Como puede ver, a diferencia de usar el contenedor básico, cuando se usa el adaptador de pila para inicializar otra pila, hay dos formas.

Funciones miembro admitidas por el adaptador de contenedor de pila

Inserte la descripción de la imagen aquí
Para la función miembro anterior, por ejemplo:

#include <iostream>
#include <stack>
#include <list>

using namespace std;

int main()
{
    
    
    //构建 stack 容器适配器
    list<int> values{
    
     1, 2, 3 };
    stack<string, list<int>> my_stack(values);
    //查看 my_stack 存储元素的个数
    cout << "size of my_stack: " << my_stack.size() << endl;
    //将 my_stack 中存储的元素依次弹栈,直到其为空
    while (!my_stack.empty())
    {
    
      
        cout << my_stack.top() << endl;
        //将栈顶元素弹栈
        my_stack.pop();
    }
    return 0;
}

Resultado de salida:

size of my_stack: 3
3
2
1

2 y

A diferencia del adaptador de contenedor de pila, el adaptador de contenedor de cola tiene 2 aberturas, una de las cuales está dedicada a los datos de entrada y la otra a los datos de salida.
Inserte la descripción de la imagen aquí
La característica más importante de esta estructura de almacenamiento es que el elemento que ingresa primero a la cola también puede ser el primero en salir de la cola. Es decir, el uso de este adaptador de contenedor para almacenar datos tiene las características de "primero en entrar, primero en salir (" FIFO ")", por lo que la cola también se denomina adaptador de cola.

1 Creación de un adaptador de contenedor de cola

El adaptador de contenedor de cola se encuentra en el archivo de encabezado en la forma de la clase de plantilla queue <T, Container = deque> (donde T es el tipo de elemento de almacenamiento y Container representa el tipo de contenedor subyacente) y se define en el espacio de nombres std. Por lo tanto, antes de crear el contenedor, el programa debe contener las siguientes 2 líneas de código:

#include <queue>
using namespace std;

1

Cree un adaptador de contenedor de cola vacío y seleccione el contenedor deque predeterminado para el contenedor base subyacente utilizado:

std::queue<int> values;

Con esta línea de código, puede crear con éxito un elemento de tipo int almacenable, y la capa inferior usa un adaptador de contenedor de cola del contenedor deque.

2

También puede especificar manualmente el tipo de contenedor subyacente que utiliza el adaptador de contenedor de cola.
Por ejemplo, lo siguiente crea un adaptador de contenedor de cola vacío que usa el contenedor de lista como contenedor base:

std::queue<int, std::list<int>> values;

Tenga en cuenta que al especificar manualmente el tipo de contenedor base, el tipo de datos almacenados debe ser coherente con el tipo de elementos almacenados por el adaptador de contenedor de cola.

3

El contenedor básico se puede utilizar para inicializar el adaptador de contenedor de cola, siempre que el tipo de contenedor sea el mismo que el tipo de contenedor básico utilizado en la parte inferior de la cola. P.ej:

std::deque<int> values{
    
    1,2,3};
std::queue<int> my_queue(values);

Dado que la capa inferior de my_queue usa un contenedor deque, que es consistente con el tipo de valores, y almacena todos los elementos de tipo int, los valores se pueden usar para inicializar my_queue.

4

También puede inicializar otro adaptador de contenedor de cola directamente a través del adaptador de contenedor de cola, siempre que el tipo de elemento que almacenan y el tipo de contenedor subyacente sean los mismos. P.ej:

std::deque<int> values{
    
    1,2,3};
std::queue<int> my_queue1(values);
std::queue<int> my_queue(my_queue1);
//或者使用
//std::queue<int> my_queue = my_queue1;

Funciones miembro admitidas por el adaptador de contenedor de cola

Inserte la descripción de la imagen aquí
Al igual que la pila, la cola no tiene iteradores, por lo que la única forma de acceder a los elementos es atravesar el contenedor y acceder al siguiente elemento eliminando continuamente el elemento visitado.

Último ejemplo:

#include <iostream>
#include <queue>
#include <list>

using namespace std;

int main()
{
    
    
    //构建 queue 容器适配器
    std::deque<int> values{
    
     1,2,3 };
    std::queue<int> my_queue(values);//{1,2,3}
    //查看 my_queue 存储元素的个数
    cout << "size of my_queue: " << my_queue.size() << endl;
    //访问 my_queue 中的元素
    while (!my_queue.empty())
    {
    
    
        cout << my_queue.front() << endl;
        //访问过的元素出队列
        my_queue.pop();
    }
    return 0;
}

Resultado de salida;

size of my_queue: 3
1
2
3

3 cola_prioridad

El adaptador de contenedor priority_queue también simula la estructura de almacenamiento de la cola, es decir, el uso de este adaptador de contenedor para almacenar elementos solo puede "entrar desde un extremo (llamado final de la cola) y salir desde el otro extremo (llamado cabeza de the queue) ", y solo se puede acceder a él cada vez que el elemento en la cabecera de la cola en priority_queue.
Sin embargo, el almacenamiento y la recuperación de elementos en el adaptador de contenedor priority_queue no sigue el principio "Primero en entrar, Primero en salir", pero el elemento con la prioridad más alta sale primero de la cola.

Entonces, ¿cómo se evalúa la prioridad de los elementos almacenados en el adaptador de contenedor priority_queue? Muy simple, cada adaptador de contenedor priority_queue se crea con una regla de clasificación. Según esta regla, los elementos almacenados en el adaptador de contenedor tienen niveles de prioridad.

Por ejemplo, suponga que actualmente hay un adaptador de contenedor priority_queue y sus reglas de clasificación se basan en el valor del elemento del mayor al menor. De acuerdo con esta regla, es natural que el elemento con el valor más grande en priority_queue tenga la prioridad más alta.

adaptador de contenedor priority_queue para asegurar que cada vez que se quita del encabezado de la cola sea el elemento de mayor prioridad actual, cada vez que ingrese un nuevo elemento, encontrará el elemento de mayor prioridad de acuerdo con las reglas de clasificación establecidas, y lo moverá a la cola El jefe del equipo; de manera similar, cuando priority_queue elimina un elemento del jefe del equipo, también encontrará el elemento con la prioridad actual más alta y lo moverá al jefe del equipo.

Según esta característica de priority_queue, el adaptador de contenedor se denomina cola de prioridad.
El adaptador de contenedor priority_queue se define de la siguiente manera:

template <typename T,
        typename Container=std::vector<T>,
        typename Compare=std::less<T> >
class priority_queue{
    
    
    //......
}

Como puede ver, la clase de plantilla de adaptador de contenedor priority_queue puede pasar hasta 3 parámetros, y sus respectivos significados son los siguientes:

  • typename T: especifique el tipo específico del elemento de almacenamiento;
  • Contenedor typename: especifique el contenedor básico usado en la parte inferior de priority_queue, el contenedor de vector se usa por defecto;
  • typename Compare: especifique las reglas de ordenación que se seguirán para evaluar la prioridad de los elementos en el contenedor. De forma predeterminada, std :: less se usa para ordenar los elementos de grandes a pequeños. También puede usar std :: mayores para ordenar los elementos de pequeño a grande, pero más En este caso, se utiliza una regla de clasificación personalizada.

1 Crear priority_queue

Dado que la plantilla del adaptador de contenedor priority_queue se encuentra en el archivo de encabezado y se define en el espacio de nombres estándar, antes de intentar crear este tipo de contenedor, el programa debe incluir las siguientes 2 líneas de código:

#include <queue>
using namespace std;

1

Cree un adaptador de contenedor priority_queue vacío, la capa inferior usa el contenedor de vector predeterminado y el método de clasificación también usa el método std :: less predeterminado:

std::priority_queue<int> values;

2

Puede inicializar el adaptador de contenedor priority_queue con datos en un rango especificado en una matriz normal u otro contenedor:

//使用普通数组
int values[]{
    
    4,1,3,2};
std::priority_queue<int> copy_values(values,values+4);//{4,3,2,1}
//使用序列式容器
std::array<int,4> values{
    
     4,1,3,2 };
std::priority_queue<int> copy_values(values.begin(),values.end());//{4,3,2,1}

Tenga en cuenta que los dos métodos anteriores deben garantizar que el tipo de elemento almacenado en la matriz o contenedor sea el mismo que el tipo de almacenamiento especificado por priority_queue. Además, no es necesario ordenar los datos en la matriz o el contenedor utilizado para la inicialización, priority_queue los clasificará automáticamente.

3

También puede especificar manualmente el contenedor subyacente y las reglas de clasificación utilizadas por priority_queue, como:

int values[]{
    
     4,1,2,3 };
std::priority_queue<int, std::deque<int>, std::greater<int>> copy_values(values, values+4);//{1,2,3,4}

Funciones miembro proporcionadas por priority_queue

Inserte la descripción de la imagen aquí
por ejemplo:

#include <iostream>
#include <queue>
#include <array>
#include <functional>

using namespace std;

int main()
{
    
    
    //创建一个空的priority_queue容器适配器
    std::priority_queue<int>values;
    //使用 push() 成员函数向适配器中添加元素
    values.push(3);//{3}
    values.push(1);//{3,1}
    values.push(4);//{4,3,1}
    values.push(2);//{4,3,2,1}
    //遍历整个容器适配器
    while (!values.empty())
    {
    
    
        //输出第一个元素并移除。
        std::cout << values.top()<<" ";
        values.pop();//移除队头元素的同时,将剩余元素中优先级最大的移至队头
    }
    return 0;
}

Resultado de salida:

4 3 2 1 %  

Supongo que te gusta

Origin blog.csdn.net/qq_24649627/article/details/108087991
Recomendado
Clasificación