Está en la página 1de 45

Contenedores

Biblioteca STL
Standard Template Library
Tema 3. Contenedores secuenciales

3.1. Uso de Iteradores


3.2. Vector
3.3. Cola de doble extremo (deque)
3.4. Lista doblemente enlazada (list)
3.5. Adaptadores de secuencia
3.5.1. Pila (stack)
3.5.2. Cola (queue)
3.5.3. Cola de prioridad
Contenedores e Iteradores
Un contenedor es un objeto cuya función es almacenar otros objetos, y provee
métodos para acceder a sus elementos.

 Secuenciales (acomodan los elementos en Vector


forma lineal. Permiten operaciones de
inserción y borrado en posiciones específicas) list

Asociativos Simples (los


Tipos

elementos almacenados set, multiset


 Asociativos (cuyas
operaciones sobre los son las mismas claves)
elementos están map,
basadas en claves) • Asociativos por Pares (se multimap
asocia una clave con otro
elemento)

 Cada tipo de contenedor tiene un tipo de iterador asociado.


Contenedores estándar
• Los contenedores estándar están disponibles a través de los siguientes
archivos de cabecera, cuyos nombres indican el tipo de contenedor
correspondiente.
#include <string> // strings
#include <vector> // arrays
#include <list> // cyclic doubly linked lists
#include <deque> // hybrid list/array
#include <queue> // queue
#include <stack> // stack
#include <bitset> // bit-vectors
#include <set> // general sets
#include <map> // associative arrays
STL: Standard Template Library
Contiene definiciones de clases: plantillas de datos
(contenedores) + algoritmos.

 Contenedores: vectores, listas, mapas, conjuntos,


colas.
 Algoritmos: ordenación, búsqueda, recorrido,
permutación, montículos, etc.
 Iteradores: sirven para hacer recorrido en los
contenedores.
Contenedores estándar – Iteradores: Interfaz general
TipoContenedor::iterator nombreIterador;
Por ejemplo:
Definición
set<int>::iterator it;
list<set<string> >::iterator it;

Avanzar iterador al siguiente elemento:


it++
Utilización Acceder al valor de un elemento:
*it
También es válido
it->atributo y it->método()
Contenedores estándar – Iteradores: Interfaz general
Inicializar iterador:
it = contenedor.begin();

Cosultar si un iterador llegó al final de la


secuencia:
Utilización
if (i != contenedor.end()) {
// El iterador referencia un elemento válido
} else {
// El iterador llegó al final
}
Contenedores estándar - Iteradores
• Los iteradores ofrecen una interfaz uniforme entre los contenedores y los
algoritmos en los contenedores. En el siguiente listado se muestra el idioma
estándar para recorrer un contenedor e imprimir sus elementos.
#include <iostream>
#include <string>
using namespace std;
int main(){ it es un iterador que sirve para
string A = "This is a string"; recorrer cada uno de los caracteres
string::iterator it;
//create iterator
de la cadena A
for (it = A.begin(); it != A.end(); ++it) {
cout << *it << endl;
}
}
Contenedores estándar - Iteradores
• Aquí it es un iterador para #include <iostream>
el contenedor A.
#include <string>
• Las funciones miembro using namespace std;
A.begin() regresa un
iterador apuntando al int main(){
primer elemento string A = "This is a string";
• A.end() regresa un iterador string::iterator it;
apuntando a "uno- //create iterator
después-del-final", for (it = A.begin(); it != A.end(); ++it)
significando una posición {
hipotética que podría ser cout << *it << endl;
ocupada por el último
elemento si se agregara al }
contenedor otro elemento }
Contenedores estándar - Algoritmos
• El núcleo de STL es #include <cstdlib>
su extensa #include <iostream>
colección de #include <stack> // STL pila
algoritmos. using namespace std;
• Debido a que los int main() {
iteradores forman stack<int> s; // pila de enteros
la interfaz entre s.push (45); // añade a la pila
los contenedores y s.push (110);
los algoritmos en s.push (51);
STL, los algoritmos while (!s.empty()){// mientras no esté vacía la pila hacer
son (en su mayor cout << s.top () << endl; // escribir valor de tope
parte) s.pop(); // borrar elemento de la pila
implantados como }
funciones libres return 0;
}
Contenedores estándar - Algoritmos
• Son un modo de almacenar datos en memoria. Proporcionan servicios tales como inserción, borrado,
búsqueda, ordenación, pruebas o comparación de un elemento con un miembro de la clase, y
similares.
• STL proporciona servicios para diez categorías básicas de contenedores:
• vector<T>: array (lista) secuencial.
• deque<T>: cola de doble entrada, secuencial, por ejemplo, LIFO.
• list<T>: lista doblemente enlazada.
• set<clave, comparar>: conjunto de elementos a los que se accede con la clave de búsqueda
asociativa.
• multiset<clave, comparar>: igual que set, pero puede contar múltiples copias del mismo
elemento.
• map<clave, T, comparar>: colección de correspondencias (mapas) de 1 : 1 entre clave y objeto.
• multimap<clave, T, comparar>: colección de 1:N correspondencias, con claves múltiples.
• stack<T, contenedor <T>>: adaptador para utilizar un contenedor como una pila.
• queue<T,Contenedor<T>>: cola; solo FIFO.
• priority_queue<contenedor<T>, comparar>: cola FIFO ordenada.
Contenedores estándar - Algoritmos
Contenedores estándar - Algoritmos
Contenedores estándar - Vector
Un vector es similar a un array inteligente que mantiene información
del tamaño y puede crecer para hacer espacio para almacenar más
datos. Los vectores proporcionan acceso aleatorio a sus datos a
través del operador de subíndice ([ ]).

Los elementos de un vector se almacenan físicamente de forma


contigua, por lo que las inserciones en el centro de un vector
originan que otros elementos se muevan y su tiempo de ejecución es
proporcional al número de elementos.

Si su programa hace muchas inserciones, se puede desear utilizar


una lista u otra estructura de datos eficiente en memoria.
Contenedores estándar - Vector

La declaración más común de un objeto de tipo vector se realiza de


la siguiente manera:

vector<tipo> objeto; o vector<tipo> objeto(numero);

Como por ejemplo:


vector<int> vecent1 // declara un vector de enteros vacío
vector<string> vstring1(10); // declara un vector de 10 string
vector<double> vdouble(100); // vector de 100 reales dobles
vector<double> vdouble(100,-10) // vector inicializado a -10
Contenedores estándar - Vector
Funciones miembro:
Contenedores estándar - Vector
Funciones miembro:
Contenedores estándar - Vector
VECTORES: Tamaño y capacidad

• Tamaño y capacidad son dos propiedades diferentes de un vector.

• En la imagen el tamaño es 3 (número de elementos que contiene


el vector) y la capacidad es 7 (tamaño del vector).
Contenedores estándar - Vector
#include <cstdlib>
#include <iostream> vec es un vector que almacenará
#include <vector> cadenas de texto (char* es una forma
using namespace std; de definir cadenas de texto
const int MaxStr = 4;
int main() {
vector <char*> vec; // crea un vector vacío
vec.insert(vec.end(), "Mazarambroz");
vec.insert(vec.end(), "Ajofrin");
vec.insert(vec.end(), "Sonseca");
vec.insert(vec.end(), "Toledo");
for (int i = 0; i < MaxStr; ++i) // recorre el vector y lo muestra
cout << " " << vec[i] << endl;
return 0;
}
Contenedores estándar – Vector – p1
Programa que crea un vector dinámico al que se le añaden datos siempre por el
final. En caso de que se termine la capacidad del vector, esta se duplica para
poder almacenar nuevos datos.

# include <iostream>
# include <vector>
using namespace std;
int main() {
vector<int> venteros(4);
int dato;
int contador = 0;
cout << "los datos que introduzca se añaden al final del vector\n";
Contenedores estándar – Vector – p2
do {
cout << " introduzca dato -1 fin ";
cin >> dato;
if (dato != -1) {
if (contador < venteros.size())
venteros[contador] = dato; // añade dato al final
else {
if (venteros.size() > = venteros.capacity())
// Se duplica el vector
venteros.reserve(2*venteros.capacity());
venteros.push_back(dato); // añade dato al final
}
contador++;
}
} while (dato != -1);
Contenedores estándar – Vector – p3

cout << "Vector: leido\n ";


//se visualiza el vector con un iterador constante de la clase vector
for (vector<int>::const_iterator cont = venteros.begin();
cont != venteros.end(); cont++)
cout << *cont << " ";
return 0;
}
Contenedores estándar - Vector
#include <iostream>
#include <vector> // Ahora con insert., Insertar al inicio
using namespace std; numeros.insert(numeros.begin(), 100);
int main() { // Insertar en la posición 1
vector<int> numeros; numeros.insert(numeros.begin() + 1, 500);
// Se agregan al final con push_back // Insertar en la penúltima posición
numeros.push_back(50); numeros.insert(numeros.end() - 1, 1000);
// Imprimirlos para ver contenido
numeros.push_back(70); cout << "Imprimiendo" << std::endl;
numeros.push_back(80); for (size_t i = 0; i < numeros.size(); i++) {
// Imprimirlos para ver contenido cout<<numeros[i]<<endl;
cout << "Imprimiendo" << endl; }
for (size_t i = 0; i < numeros.size(); i++) { }
cout<<numeros[i]<<endl;
}
Contenedores estándar - List
La clase list (lista) es una lista doblemente enlazada que proporciona una
estructura de datos eficiente para insertar y quitar elementos de cualquier parte
de la lista.

Se proporcionan iteradores para acceder a sus elementos, pero los iteradores de


list son bidireccionales. Su principal ventaja es la eficiencia de las operaciones de
inserción y borrado, independientemente de la posición de la lista en la que se
realicen.
#include <list>
...
Declaración list<int> Lista1; //crea lista vacía de enteros
de listas list<int> Lista2(100); //crea lista para 100 enteros
list<double> Li3(50, 2.7); //lista de 50 double inicializados con 2.7
Contenedores estándar - List

Funciones miembro
Contenedores estándar - List

Funciones miembro
Contenedores estándar - List
// visualización de la lista
#include <cstdlib>
for (i = l.begin(); i != l.end(); i++)
#include <iostream>
cout << *i << " ";
#include <list> // clase lista
cout << endl;
using namespace std;
// nueva visualización de la lista
int main(int argc, char *argv[]) {
cout << "Valores de la lista:" << endl;
list <int> l; // lista de enteros
while (l.size() > 0)
list<int>::const_iterator i; // iterador
// mientras haya elementos en la lista
int valor;
{
// Añadir valores al final de la lista
valor = l.front();
l.push_back(2); l.push_back(4);
// Obtener el valor del inicio de la lista
l.push_back(5); l.push_back(1);
cout << valor << " ";
l.push_back(20);
l.pop_front(); // Eliminar el elemento
for (int j = 10; j < 15; j++)
}
l.insert(l.end(), j); // añade j al final de la lista.
return 0;
cout << " datos almacenados en la lista " << endl;
}
Contenedores estándar - List
#include <iostream>
#include <list> // Mostrar el contenido de la lista
using namespace std; // Se usa un iterador
int main (int argc, char * argv[]) { list<int>::iterator it = lista.begin();
// Instanciación de lista de enteros while (it != lista.end()) {
list<int> lista; cout << *it << " ";
int n; // Se muestra el contenido del
cout<<"Dar numero (0 terminar): "; // elemento referenciado
cin >> n; it++; // Avanzar el iterador
while (n > 0) { }
lista.push_back(n); // Agregar al final return 0;
cout<<"Dar numero (0 terminar): "; }
cin >> n;
}
Contenedores estándar - deque
Los deques o colas de doble terminación ("Double-ended queue") son un tipo
de estructura de datos que comparte las características de las colas
("Queues") y las pilas ("Stacks").

Como en las colas , los elementos pueden ser empujados por un extremo al
interior del contenedor, y el primer elemento introducido puede ser extraído
por el extremo opuesto.

Al mismo tiempo, el último elemento introducido por el principio puede ser


extraído en ese mismo extremo como si fuese una pila.

Las características de los deques implementados en la STL pueden resumirse


en: Acceso aleatorio; mecanismo eficiente de inserción al principio o al final.
Contenedores estándar - <deque>
Son similares a los vectores pero más eficientes para la inserción y eliminación
de elementos. A diferencia de los vectores, la asignación contigua de
almacenamiento puede no estar garantizada.
Contenedores estándar - <deque>
Algunas funciones: Asumir como ejemplo dos deque DA y DB
DA:
DB:

DA.size(): Retorna un entero que indica el tamaño del deque DA (4).

DA.swap(DB): Intercambia el contenido de DA con lo de DB. Para el ejemplo, el


resultado será:

DA:
DB:
Contenedores estándar - <deque>
Algunas funciones: Asumir como ejemplo dos deque DA y DB
DA:

DA.push_back(x): Inserta el elemento x al final del deque DA. Por ejemplo, el


resultado de DA.push_back(6) será:

DA:

DA.push_front(x): Inserta el elemento x al frente del deque DA. Por ejemplo, el


resultado de DA.push_front(6) será:
DA:
Contenedores estándar - <deque>
Algunas funciones: Asumir como ejemplo dos deque DA y DB
DA:

DA.pop_back(x): Remueve el elemento x al final del deque DA. Por ejemplo, el


resultado de DA.pop_back(6) será:

DA:

DA.pop_front(x): Inserta el elemento x al frente del deque DA. Por ejemplo, el


resultado de DA.pop_front(6) será:
DA:
Contenedores
#include <iostream>
estándar – deque – ej1
#include <deque>
using namespace std;
void display(deque <int> x);
main(){
deque<int> a;
a.push_back(10); a.push_front(20);
a.push_back(30); a.push_front(15);
cout << "The deque a is : "; display(a);
cout << "\na.size(): " << a.size(); //función display
cout << "\na.front(): " << a.front(); void display(deque <int> x) {
cout << "\na.back(): " << a.back(); deque <int> :: iterator it;
cout << "\na.pop_front(): "; for (it = x.begin(); it != x.end(); ++it)
a.pop_front(); display(a); cout << ' ' << *it;
cout << "\na.pop_back() : "; cout << '\n';
a.pop_back(); display(a); }
}
Contenedores estándar – deque – ej2
#include <iostream>
#include <deque>
using namespace std;
main(){
deque<string> animales;
animales.push_back("Perro");
animales.push_back("Gato");
animales.push_back("Cerdo");
animales.push_back("Mapache");
animales[2] = "Gusano";
for (int i=0; i<animales.size(); i++) {
cout<<animales.at(i)<<endl;
}
}
Contenedores estándar - Stack
Contenedor de elementos tipo pila LIFO que permite inserciones y eliminaciones
solo en la parte superior.

Operaciones principales: empty, size, top, push, pop


Contenedores estándar - Stack
#include <iostream>
#include <stack>
using namespace std;
main(){
stack<int> st1;
st1.push(21); st1.push(31);
int j = st1.top(); int j = st1.top();
cout<<j<<“ “; stack <int>::size_type i;
st1.push(9); i = st1.size();
j = st1.top(); cout<<“El largo de la pila es: “<<i<<endl;
cout<<j<<“ “; st1.pop();
st1.push(12); cout<<“El elemento arriba de la pila es: “<<i<<endl;
j = st1.top(); cout<<“Tamano de la pila es: “<<i<<endl;
cout<<j<<“ “; }
Contenedores estándar - Queue
Contenedor de elementos tipo cola FIFO (First In First Out), en la que la inserción
de un elemento es por un extremo y la eliminación por el otro.

Eliminación
- Salida de
elemento

Inserción-
Entrada de
elemento

Operaciones principales: empty, size, front, back, Push, Pop


Contenedores estándar - Queue
#include <iostream>
#include <queue>
using namespace std;
main() {
queue<char> s;
for (int i='A'; i <= 'T'; i++)
s.push(i);
while (! s.empty() ) {
cout << s.front() << " " ;
s.pop();
}
cout << endl;
system("PAUSE");
}
Contenedores estándar - priority_queue
Colas de prioridad: Son parecidas a las colas, con la diferencia de que en estas
los elementos se ordenan mediante algún predicado.

Es una estructura de datos en la que los elementos se atienden en el orden


indicado por una prioridad asociada a cada uno. Si varios elementos tienen la
misma prioridad,se atenderán de modo convencional según la posición que
ocupen.

Este tipo especial de colas tienen las mismas operaciones que las colas , pero
con la condición de que los elementos se atienden en orden de prioridad.

Ejemplos de la vida diaria serían la sala de urgencias de un hospital, ya que los


enfermos se van atendiendo en función de la gravedad de su enfermedad.
Contenedores estándar - priority_queue
main(){
priority_queue<int> p;
#include <cstdlib>
p.push(100);
#include <iostream> p.push(35);
p.push(12);
#include <queue>
p.push(200);
using namespace std;
// mostrar elementos
while (! p.empty() ) {
cout << p.top() << endl;
p.pop();
}
system("PAUSE");
}
Contenedores estándar - priority_queue

El resultado del programa anterior, obtiene los valores de mayor


a menor y se debe al hecho de que por defecto la función o
predicado que compara los elementos de la priority_queue es
menor (less).

El predicado puede ser cambiado para que la comparación se


mayor (greater) y para lograrlo se debe de usar una plantilla
basada en la clase vector o en la clase deque.
Contenedores estándar - priority_queue
#include <iostream>
#include <queue>
using namespace std;
main() {
priority_queue< int, deque<int>, greater<int> > p;
p.push(100);
p.push(35);
p.push(12);
p.push(200);
while (! p.empty() ){
cout << p.top() << endl;
p.pop();
}
}
Contenedores estándar - priority_queue
una priority_queue permite usar un constructor para obtener una copia
ordenada de un contenedor ( vector, deque ).
#include <iostream>
#include <queue>
#include <vector>
using namespace std; vector<string>::iterator it = v.begin();
// declaración de tipo cout<<"Contenido del vector"<<endl;
typedef priority_queue<string, vector<string>, while (it != v.end() )
greater<string> > STRPQUE; cout << "\t" << *it++ << endl;
main(){ STRPQUE p( v.begin(), v.end() );
vector<string> v; cout<<"\nContenido de priority_queue"<<endl;
v.push_back("pera"); while (! p.empty() ){
v.push_back("uva"); cout<<"\t"<<p.top()<<endl;
v.push_back("manzana"); p.pop();
v.push_back("banana"); }
v.push_back("coco"); }
Contenedores estándar - priority_queue
#include <iostream>
#include <queue>
using namespace std;
main() {
priority_queue< int, deque<int>, greater<int> > p;
p.push(100);
p.push(35);
p.push(12);
p.push(200);
while (! p.empty() ){
cout << p.top() << endl;
p.pop();
}
}

También podría gustarte