standard template library paulo marques departamento de eng. informática universidade de coimbra...
TRANSCRIPT
![Page 1: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/1.jpg)
Standard TemplateLibrary
Paulo MarquesDepartamento de Eng. InformáticaUniversidade de [email protected] O
ut/2
005
Uma Introdução
![Page 2: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/2.jpg)
2
Sobre o que é que vamos falar?
Primeira parte (expositiva): Programação baseada em genéricos (templates) Apresentação da STL Colecções simples: “vector”, “list”, “deque”, “stack” Colecções associativas: “map” e “multimap” Colecções associativas múltiplas: “set” e “multiset” Brevemente: Extensões: “hash_set” e “hash_map” Brevemente: Algoritmos da STL
Segunda parte (prática): Alguns exercícios Caso de estudo
![Page 3: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/3.jpg)
3
Qual é o problema da seguinte rotina?
Apenas funciona para inteiros. Se necessitarmos de trocar quaisquer outros tipos de dados, temos de definir várias versões da mesma rotina... void swap(double& a, double& b) void swap(unsigned&a, unsigned& b) void swap(string&a, string& b) ...
// Rotina que troca o valor de duas variáveisvoid swap(int& a, int& b){ int tmp = a; a = b; b = tmp;}
![Page 4: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/4.jpg)
4
Programação utilizando genéricos (templates)
Permite criar uma família de funções, parametrizadas por um tipo de dados abstracto. Meta-programação Existe há anos em C++: a STL é baseada neles Adição recente em Java (J2SE 5.0) e .NET (2.0) Semântica de programação potencialmente complicada
(... e também de implementação das linguagens!)
// Rotina que troca o valor de duas variáveis quaisquertemplate<class T>void myswap(T& a, T& b){ T tmp = a; a = b; b = tmp;}
int a = 10;int b = 20;
myswap<int>(a, b);
![Page 5: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/5.jpg)
5
Problemática das tabelas de tamanho fixo
Uma grande parte das linguagens actuais fornece ao programador tabelas de tamanho fixo (e.g. C, C++, Java, .NET) Uma vez criadas, o seu tamanho não pode ser redefinido No entanto, em muitas circunstâncias, o programador não
sabe quantos elementos é que a sua tabela terá de armazenar!
// Número máximo de pessoasconst unsigned MAX_SIZE = 10;
// Tabela onde armazenar a altura das pessoasdouble heights[MAX_SIZE];unsigned totalPeople = 0;
// Armazena sucessivamente pessoasdouble height;while (cin >> height) heights[totalPeople++] = height;
Ao chegarmos à décima primeira pessoa... BANG!
![Page 6: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/6.jpg)
6
Tabela Dinâmica Genérica
A solução passa por criar uma classe “Tabela Dinâmica”, genérica, capaz de armazenar qualquer tipo de dadosint main()
{ // Tabela dinâmica para armazenar alturas DynamicArray<double> heights;
// Lê a altura das pessoas double altura; while (cin >> altura) heights.push_back(altura); // Calcula e mostra a média das alturas double averageHeight = 0.0; for (unsigned i=0; i<heights.size(); i++) averageHeight+= heights[i]; averageHeight/= heights.size();
cout << averageHeight << endl;
return 0;}
![Page 7: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/7.jpg)
7
O resultado da execução...
![Page 8: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/8.jpg)
8
Interface de DynamicArray
template<class T>class DynamicArray{private: const static int _DEFAULT_CAPACITY = 1;
unsigned int _size; unsigned int _capacity; T* _myArray;
public: DynamicArray(unsigned int size = 0); virtual ~DynamicArray(void);
void push_back(T& element); unsigned int size() const;
T& operator[](unsigned int index) const;};
![Page 9: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/9.jpg)
9
Construtor, Destrutor e size() de DynamicArray
// Construtor, leva como parâmetro o tamanho inicial da tabelatemplate<class T>DynamicArray<T>::DynamicArray(unsigned int size) : _size(size), _capacity(_DEFAULT_CAPACITY){ if (_size > 0) _capacity = _size; _myArray = new T[_capacity];}
// Destructortemplate<class T>DynamicArray<T>::~DynamicArray(void){ delete[] _myArray;}
// Retorna o número de elementos na tabelatemplate<class T>unsigned int DynamicArray<T>::size() const{ return _size;}
![Page 10: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/10.jpg)
10
Principais operações: push_back() e acesso []
// Acrescenta um elemento à tabela, fazendo uma cópia do mesmotemplate<class T>void DynamicArray<T>::push_back(T& element){ if (_size == _capacity) { _capacity = _capacity * 2; T* newArray = new T[_capacity]; for (unsigned i=0; i<_size; i++) newArray[i] = _myArray[i]; delete[] _myArray; _myArray = newArray; } _myArray[_size] = element; _size++;}
// Retorna uma referência para um elemento da tabela template<class T>T& DynamicArray<T>::operator[](unsigned int index) const{ return _myArray[index];}
![Page 11: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/11.jpg)
11
Aviso...
A forma como os compiladores utilizam templates varia radicalmente: é compiler specific: consultar a documentação
Uma possível abordagem relativamente segura e genérica: Incluir o ficheiro .h (i.e. “dynamic_array.h”) Dependentemente do tipo de compilador, definir a macro
TEMPLATE_INCLUSIVE_MODEL na Makefile (ou projecto) Dependentemente do compilador, incluir na compilação a
implementação do template .cpp (i.e. “dynamic_array.cpp”)
#ifndef _DYNAMIC_ARRAY_H_#define _DYNAMIC_ARRAY_H_
template<class T>class DynamicArray{ ...};
#ifdef TEMPLATE_INCLUSIVE_MODEL#include "dynamic_array.cpp"#endif
#endif
#include "dynamic_array.h"
...
#include "dynamic_array.h"
...
dynamic_array.h
dynamic_array.cpp
my_program.cpp
![Page 12: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/12.jpg)
12
STL
STL = Standard Template Library Biblioteca contendo algoritmos e estruturas de dados
genéricas para uso em C++
Baseada nas ideias sobre “programação genérica” de Alexander Stepanov. Enquanto trabalhava nos Bell Labs e mais tarde na HP,
implementou o core de uma biblioteca de programação genérica em C++
(1993) É convidado a apresentar as suas ideias sobre programação genérica ao comité de ANSI/ISO do C++. A resposta é entusiástica. Em 1994 a sua proposta para inclusão da biblioteca no standard do C++ é aprovada.
(1994) A HP publica livremente na internet a implementação da STL. Esta implementação, mais tarde modificada pela SGI, constitui a base na maior parte das implementações actualmente disponíveis.
![Page 13: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/13.jpg)
13
HP / SGI
Microsoft’s Visual Studio <vector>
GNU’s G++ <vector.tcc>
![Page 14: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/14.jpg)
14A nossa área de foco
STL – Modelo Plug-and-Play
Container Classes
Iterators GenericAlgorithms
Vector
list
istream
ostream
inserterase
inserterase
sort
find
merge
istream_iterator
ostream_iterator
less
equal
greater
FunctionObjects
![Page 15: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/15.jpg)
15
Componentes
Containers Armazenam colecções de objectos
Algoritmos Genéricos Realizam operações sobre containers
Iteradores Permitem percorrer um determinado container
Function Objects Realizam cálculos ou combinam dados
Adaptadores Modificam a interface de um componente
(e.g. Stack, PriorityQueue) Allocators
Permitem ao programador controlar explicitamente o uso de memória [perigoso mas poderoso!]
![Page 16: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/16.jpg)
16
Colecções Lineares
vector<T>:Corresponde a uma tabela dinâmica, aumentando automaticamente de tamanho sempre que é necessário. Acesso aleatório aos seus elementos muito rápido: O(1) Inserir e apagar elementos do final é eficiente. Tipicamente O(1) Relativamente lento a eliminar elementos do início e do meio.
deque<T>:Semelhante a vector<T> mas permite inserir e apagar elementos de forma muito eficiente do início e fim: O(1).
list<T>:Corresponde a uma lista duplamente ligada. Inserir/apagar elementos é rápido desde que se esteja no local
correcto: O(1). Mas, tal como o acesso, em geral, é O(n). Não suporta acesso aleatórios aos elementos. No entanto
também não desperdiça espaço.
![Page 17: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/17.jpg)
17
Exemplo utilizando vector<T>
#include <vector>using namespace std;
void ex_vector(){ // Tabela dinâmica para armazenar alturas vector<double> heights;
// Lê a altura das pessoas double altura; while (cin >> altura) heights.push_back(altura); // Calcula e mostra a média das alturas double averageHeight = 0.0; for (unsigned i=0; i<heights.size(); i++) averageHeight+= heights[i];
averageHeight/= heights.size(); cout << averageHeight << endl;}
![Page 18: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/18.jpg)
18
Iteradores
Um iterador permite percorrer uma colecção seguindo uma determinada ordem
Um iterador é uma inner class de cada colecção particular, tendo por nome “iterator”. Para declarar um é necessário utilizar o operador de abrangência ::
vector<int>::iterator it = ...
Para avançar/recuar um iterador utilizam-se os operadores ++ e -- it++ avança o iterador para o próximo elemento, it-- recua-o É ainda possível avançar mais do que um elemento: it+= 2
Para aceder ao elemento apontado utiliza-se o operador * *it retorna o valor actualmente apontado
begin() retorna um iterador para o início de uma colecção end() retorna um iterador para além do final da colecção
(sentinela)
![Page 19: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/19.jpg)
19
Exemplo utilizando iteradores
#include <vector>#include <string>#include <iostream>using namespace std;
void ex_iterator(){ // Tabela para armazenar palavras vector<string> words;
// Lê as palavras do stdin para o vector string word; while (cin >> word) words.push_back(word);
// Imprime as palavras lidas vector<string>::iterator it = words.begin(); while (it != words.end()) { cout << *it << endl; ++it; }}
![Page 20: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/20.jpg)
20
Exemplo utilizando iteradores reversos
void ex_reverse_iterator(){ // Tabela para armazenar palavras vector<string> words;
// (...)
// Imprime as palavras pela ordem inserida cout << "Palavras pela ordem de insercao:" << endl;
vector<string>::iterator it = words.begin(); for (; it != words.end(); it++) cout << "\t" << *it << endl;
// Imprime as palavras pela ordem inversa cout << endl << "Palavras pela ordem inversa:" << endl;
vector<string>::reverse_iterator rit = words.rbegin(); for (; rit != words.rend(); rit++) cout << "\t" << *rit << endl;}
![Page 21: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/21.jpg)
21
Resultado da execução...
![Page 22: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/22.jpg)
22
Alguns métodos importantes de vector<T>
vector()Construtor por omissão: o vector fica vazio
vector(size_type n)Construtor que cria um vector com n objectos, com o seu valor por omissão (uso do construtor default)
size_type size() constRetorna o número de elementos no vector
size_type capacity() constRetorna a capacidade actual do vector
bool empty() const Retorna se o vector está vazio
T& operator[](size_type n)Retorna uma referência para o elemento n
T& front()Retorna referência para o primeiro elemento
T& back()Retorna referência para o último elemento
![Page 23: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/23.jpg)
23
Alguns métodos importantes de vector<T> (2)
void push_back(const T&) Adiciona um elemento ao final do vector
void pop_back()Remove o último elemento
void clear() Apaga todos os elementos do vector
vector<T>::iterator begin()Retorna um iterador para o início do vector
vector<T>::iterator end()Retorna um iterador para um elemento após o final do vector (sentinela)
vector<T>::reverse_iterator rbegin()Retorna um iterador reverso que começa no último elemento do vector
vector<T>::reverse_iterator rend()Retorna um iterador reverso que aponta para antes do início do vector
void insert(iterator pos, const T& x) Insere um elemento antes de uma posição apontada por um iterador
iterator erase(iterator pos)Apaga um elemento apontado por um iterador
Nota: Para todos os métodos que retornam elementos ou iteradores, existem versões que retornam os correspondentes constantes. E.g. const T& vector<T>::front() const
![Page 24: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/24.jpg)
24
Outros aspectos...
Os vectores armazenam cópias dos elementos, não referências
Muitas vezes, é mais sensato armazenar referências (ponteiros) para os objectos do que armazenar os objectos em si. Semântica do Java e .NET Importante se os objectos necessitam de ser utilizados em
diversos locais! Sempre que o vector aumenta de tamanho, é invocado o
construtor por omissão para todos os elementos da nova tabela interna; todos os elementos são copiados; é invocado o destrutor de cada um dos objectos antigos PESADO!
Se à priori se souber que vão ocorrer um certo número de inserções, é sensato reservar o espaço.
![Page 25: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/25.jpg)
25
deque<T>
Semelhante a vector<T> mas permite inserir e apagar elementos de forma muito eficiente do início e do final da colecção. Óptimo para implementar sistemas tipo
produtor/consumidor
void deque<T>::push_front(const T& x) Adiciona um elemento ao início
void deque<T>::push_back(const T& x)Adiciona um elemento ao final
T& deque<T>::front() Obtem o primeiro elemento
T& deque<T>::back()Obtem o último elemento
void deque<T>::pop_front()Remove o primeiro elemento
void deque<T>::pop_back()Remove o último elemento
![Page 26: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/26.jpg)
26
Exemplo deque<T>
// Simula uma repartição pública (processamento por ordem)class Reparticao{private: deque<string> _pedidos;
public: // Adiciona um pedido ao fim da lista de trabalho a processar void adicionaPedido(const string& pedido) { _pedidos.push_back(pedido); }
// Caso existam pedidos, retorna o primeiro que deu entrada bool retiraPedido(string& pedido) { if (_pedidos.empty()) return false; pedido = _pedidos.front(); _pedidos.pop_front(); return true; }};
![Page 27: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/27.jpg)
27
Exemplo deque<T> (2)
void ex_deque(){ Reparticao financas;
financas.adicionaPedido("Impostos_1"); financas.adicionaPedido("Impostos_2"); financas.adicionaPedido("Impostos_3");
string pedido; while (financas.retiraPedido(pedido)) { cout << "PEDIDO: " << pedido << endl; }}
![Page 28: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/28.jpg)
28
list<T>
Implementa uma lista duplamente ligada Suporta iteradores para a frente e para trás Ao contrário de vector<T> e deque<T>, não suporta
acesso aleatório (operador []), apenas acesso via iteradores. Tirando isso, o interface é semelhante a deque<T>: push_front(), push_back(), pop_front(), pop_back(), e iteradores.
Inserir um elemento não invalida os iteradores existentes
![Page 29: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/29.jpg)
29
Exemplo de list<T> (algo “retorcido”...)
#include <list>#include <iostream>using namespace std;
void ex_list() { // Cria uma lista para conter os números de Fibonacci list<int> fibonacci; fibonacci.push_back(1); fibonacci.push_back(1);
// Dada novo número é a soma de ambos os anteriores! list<int>::iterator current = fibonacci.begin(); for (int i=0; i<10; i++) { int newValue = *current++; newValue+= *current; fibonacci.push_back(newValue); }
// Imprime a lista resultante current = fibonacci.begin(); while (current != fibonacci.end()) cout << *current++ << endl;}
![Page 30: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/30.jpg)
30
Resultado da execução...
![Page 31: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/31.jpg)
31
Que estrutura utilizar?
Estrutura Condições
vector - Acesso aleatório aos elementos- Baixa necessidade de eliminar elementos do início/meio, ou caso esta exista, apenas em colecções “pequenas”- Estrutura base de armazenamento para apoio a outras
deque - Condições de vector mas em que é necessário introduzir e eliminar eficientemente elementos no início e fim da colecção
list - Elevada necessidade de eliminar elementos do início ou meio da colecção, especialmente em colecções “grandes”- Baixa necessidade de utilização de elementos intermédios- Colecções “grandes” em que é necessário armazenar efectivamente os elementos (não referências). Caso se necessite armazenar referências, considerar seriamente o uso de vector
![Page 32: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/32.jpg)
32
Colecções Associativas – Motivação I
Suponhamos que necessitamos de armazenar 100.000 pessoas em memória. Essas pessoas serão pesquisadas por Bilhete de Identidade. A pesquisa de cada pessoa demora 50us
JOANA FRANCISCA 10896534 R. Fernão Lop
Qual é o problema se quisermos encontrar a pessoacom o BI Nº 10896534?
Esquecendo as caches, se usarmos uma estrutura linear (e.g. vector)Tempo de acesso a uma pessoa = 50usEm média temos de percorrer ½ tabela = 50.000 entradas50000 entradas X 50us = 2500000us = 2.5s!!!
![Page 33: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/33.jpg)
33
Colecções Associativas – Motivação I (2)
Se as pessoas forem armazenadas numa árvore binária equilibrada...
log2(100.000) 16
Tempo de acesso a uma pessoa = 50usEm média temos de percorrer ½ árvore = 16/2 entradas = 8 entradas
8 entradas X 50us = 400us = 0.0004s!!!
![Page 34: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/34.jpg)
34
Colecções Associativas – Motivação II
É muito simpático poder escrever...
#include <iostream>#include <string>#include <map>using namespace std;
void ex_map() { map<int,string> baseDeDados;
baseDeDados[10609100] = "Carlos Manuel"; baseDeDados[10432546] = "Joaquim Antonio"; baseDeDados[34545442] = "Silvino Costa"; int numeroBI; while (cin >> numeroBI) { if (baseDeDados.count(numeroBI) == 0) cout << "Pessoa nao encontrada" << endl; else cout << “Nome da pessoa: " << baseDeDados[numeroBI] << endl; }}
![Page 35: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/35.jpg)
35
Colecções Associativas
map<TKey,TValue> e multimap<TKey,TValue>:Corresponde a uma árvore binária equilibrada (tipicamente, uma árvore red-black), permitindo armazenar elementos que são pesquisáveis por uma chave. Acesso aos seus elementos muito eficiente O(logN) Os elementos são mantidos ordenados por chave multimap permite manter vários elementos por chave
set<T> e multiset<T>:Permite armazenar um conjunto elementos em que o seus próprios valores constituem as chaves de procura. Ou seja... permite verificar se um elemento se encontra presente
ou não multiset permite armazenar vários elementos idênticos
hash_map<TKey, TValue> e hash_set<T>:Semelhantes aos acima mencionados mas baseados em tabelas de dispersão (hashtables) Inserir, apagar e pesquisar elementos é muito rápido: O(1) Os elementos não são mantidos ordenados Infelizmente, (ainda) não faz parte do ANSI/ISO standard
![Page 36: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/36.jpg)
36
Utilização de map<TKey,TValue>
tabelaAssociativa.count(key) conta o número de ocorrências do objecto identificado por key na colecção
tabelaAssociativa[key] = obj; coloca na tabela associativa o objecto obj identificando-o por key
obj = tabelaAssociativa[key]; retira da tabela associativa o objecto representado por key
map<TKey,TValue> tabelaAssociativa;
Chave depesquisa
Objecto aguardar
Se o objecto não existir na tabela, é automaticamente colocado na tabela um novo objecto com essa chave, sendo utilizado o construtor por omissão de TValue!
![Page 37: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/37.jpg)
37
Acesso aos elementos...
(...)
if (baseDeDados.count(numeroBI) == 0) cout << "Pessoa não encontrada." << endl;else cout << "Pessoa: " << baseDeDados[numeroBI] << endl;
(...)
Duas pesquisas na árvore!
(...)
map<int,string>::iterator result = baseDeDados.find(numeroBI); if (result == baseDeDados.end()) cout << "Pessoa não encontrada." << endl;else cout << "O nome da pessoa é: " << result->second << endl;
(...)
Uma única pesquisa na árvore!
![Page 38: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/38.jpg)
38
A operação map<TKey,TValue>::find()
O método find retorna um iterador que refere uma estrutura pair<TKey,TValue> O primeiro elemento do pair é a chave do objecto O segundo elemento é o valor do objecto
Um pair é algo semelhante a:
template <class T, class Q>struct pair { T first; Q second;}
![Page 39: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/39.jpg)
39
Uso de typedefs
É vulgar utilizarem-se typedef’s para simplificar o código
// Definição da Base-de-dadosmap<int,string> baseDeDados;
typedef pair<int,string> pessoa;typedef map<int,string>::iterator bd_iterator;
// Coloca pessoas na BD// (...)
// Localiza a pessoa com o BI 10609129bd_iterator it = baseDeDados.find(10609129);if (it != baseDeDados.end()){ pessoa bi_nome = *it++; cout << "BI: " << bi_nome.first << endl; cout << "Nome: " << bi_nome.second << endl;}
![Page 40: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/40.jpg)
40
Uso de typedefs (2)
Vejamos o conteúdo da base-de-dados...#include <iostream>#include <string>#include <map>using namespace std;
typedef map<int,string> BaseDeDados;typedef pair<int,string> pessoa;typedef map<int,string>::iterator BD_iterator;
void ex_map3() { BaseDeDados bd;
bd[10324] = "Joana Sampaio"; bd[34434] = "Patricio Domingues"; bd[12667] = "Bruno Cabral"; bd[76768] = "Catarina Reis";
BD_iterator it = bd.begin(); while (it != bd.end()) { pessoa bi_nome = *it++; cout << "BI: " << bi_nome.first << endl; cout << "Nome: " << bi_nome.second << endl << endl; }}
![Page 41: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/41.jpg)
41
Resultado da execução...
Note-se que os elementos são mantidos ordenados no map!
![Page 42: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/42.jpg)
42
Alguns aspectos importantes de map<TKey,TValue>
Os elementos são mantidos ordenados no map Tal é intrínseco à árvore red-black associada. A classe TKey tem de suportar a noção de ordem
(i.e. o operador “<“ tem de ser válido – definido!)
Caso se coloque na tabela um elemento que já esteja na mesma (i.e. que tenha a mesma chave), o que lá se encontra é substituído A classe multimap permite armazenar vários elementos
para a mesma chave
Os iteradores de map apontam sempre para tipos pair<TKey,TValue>
![Page 43: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/43.jpg)
43
Alguns métodos importantes de map<TKey,TValue>
map()Construtor por omissão: o map fica vazio
map<TKey,TValue>::iterator begin()Retorna um iterador para o primeiro elemento
map<TKey,TValue>::iterator end() Retorna um iterador para além do último elemento
size_type size() constRetorna o número de elementos no map
bool empty() constRetorna se a tabela está vazia
map<TKey,TValue>::iterator find(const TKey& key)Encontra o elemento de chave key
size_type erase(const TKey& key)Elimina o elemento de chave key
size_type erase(map<TKey,TValue>::iterator it)Elimina o elemento apontado por it
size_type count(const TKey& key) Conta o número de elementos presentes com a chave key
TValue& operator[](const Tkey& key) Retorna uma referência para o elemento de chave key; caso necessário, acrescentando um novo à tabela
![Page 44: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/44.jpg)
44
mutimap<TKey,TValue>
Bastante semelhante a map mas permite ter vários valores para a mesma chave.typedef multimap<string,int> AgendaTelefonica;typedef multimap<string,int>::iterator agenda_iterator;typedef pair<string,int> entrada_agenda;
void ex_multimap() { AgendaTelefonica telefones;
telefones.insert(entrada_agenda("Paulo Marques", 914144687)); telefones.insert(entrada_agenda("Paulo Marques", 964324546)); telefones.insert(entrada_agenda("Rita Queiroz", 933409876)); telefones.insert(entrada_agenda("Bruno Cabral", 918788755)); telefones.insert(entrada_agenda("Bruno Cabral", 930012232));
string pessoa("Paulo Marques"); cout << pessoa << ":" << endl;
agenda_iterator it = telefones.find(pessoa); for (unsigned i=0; i<telefones.count(pessoa); i++, it++) { cout << "\t" << it->second << endl; }}
![Page 45: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/45.jpg)
45
Notas sobre mutimap<TKey,TValue>
Os elementos têm de ser inseridos usando insert(), com um pair<TKey,TValue>. Não existe operador de acesso [].
find() retorna um iterador para o primeiro elemento encontrado O iterador não é para percorrer todos os elementos
correspondentes à pesquisa. É apenas uma referência para o primeiro.
Dado que multimap está garantidamente ordenado, os seguintes podem ser acedidos avançando o iterador até um número de vezes igual a count()
Tal como em map, o iterador refere-se a uma estrutura pair. O primeiro elemento contém a chave, o segundo o valor
![Page 46: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/46.jpg)
46
set<T>
Semelhante a map mas os elementos são a própria chave. A principal utilidade é testar de um elemento se encontra presente
ou não; secundariamente, armazenar elementos (se bem que vector ou list poderão ser melhor alternativas)
Os elementos são mantidos ordenados (necessidade da existência do operador “<“)
void ex_set() { // Pessoas que se encontram num edifício set<string> edificio;
// Pessoas as entrarem e a saírem do edifício edificio.insert("Carlos"); edificio.insert("Miguel"); edificio.erase("Carlos"); edificio.insert(“Maria");
// Verifica se "Miguel" está presente if (edificio.find("Miguel") != edificio.end()) cout << “Miguel presente no edifício!" << endl; else cout << “Miguel fora do edifício." << endl;}
![Page 47: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/47.jpg)
47
multiset<T>
Semelhante a set<T>, mas os elementos podem aparecer mais do que uma vez.
void ex_multiset() { multiset<unsigned> notasExame;
// Gera aleatoriamente um conjunto de notas (0-20) for (unsigned i=0; i<200; i++) { int nota = rand()%11 + rand()%11; notasExame.insert(nota); }
// Gera um histograma dos resultados cout << setw(6) << "Nota" << " | " << setw(6) << "Vezes |" << endl; for (unsigned nota=0; nota<=20; nota++) { cout << setw(6) << nota << " | " << setw(6) << notasExame.count(nota) << "|"; for (unsigned j=0; j<notasExame.count(nota); j++) cout << "#"; cout << endl; }}
![Page 48: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/48.jpg)
48
O resultado da execução...
![Page 49: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/49.jpg)
49
Porque é que o seguinte código não é válido?
struct Pessoa{ int BI; string nome;
// ######################################
Pessoa(int o_BI, const string& o_nome) : BI(o_BI), nome(o_nome) { }};
void ex_set3(){ set<Pessoa> filaDoMercado;
filaDoMercado.insert( Pessoa(432532, "Jorge Manuel") );}
O operador “<“ nãose encontra definido!!
Não sabemos comoinserir na árvoresubjacente...
![Page 50: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/50.jpg)
50
Não esquecer...
Se vão ser utilizados tipos definidos pelo programador como chaves em map<TKey,TValue> e set<T>, é necessário, no mínimo, que o operador de ordem (“<“) esteja definido.
bool operator<(const Pessoa& other) const { return BI < other.BI; }
struct Pessoa{ int BI; string nome; // ---------------- Pessoa(int o_BI, const string& o_nome) : BI(o_BI), nome(o_nome) { }
};
![Page 51: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/51.jpg)
51
hash_map<TKey,TValue>, hash_set<T>
Ambas as classes têm o mesmo interface do que map e set no entanto, a implementação subjacente é uma tabela de dispersão (hashtable) Inserir, remover e pesquisar elementos é muito rápido
insert("Paulo Marques", 30)
hash(“Paulo Marques”) = 32748
0
1
2
3
4
5
6
32748%7 = 230
find("Paulo Marques")
hash(“Paulo Marques”) = 32748
32748%7 = 2
Hashtable
![Page 52: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/52.jpg)
52
hash_map<TKey,TValue>, hash_set<T> (2)
Actualmente não fazem parte do standard É muito provável que venham a fazer A maior parte dos compiladores inclui-as, embora variando
o espaço de nomes onde se encontram (e.g. std::, stdext::)
Os elementos não se encontram ordenados Apenas o operador de igualdade é necessário (==)
O sistema tem de saber calcular um código de dispersão (hashcode) sobre os objectos usados como chave
Também existem os análogos de multimap e multiset: hash_multimap e hash_multiset
![Page 53: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/53.jpg)
53
Um teste de performance...
![Page 54: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/54.jpg)
54
Que estrutura utilizar?
Estrutura Condições
map /multimap
- Necessidade de armazenar elementos em que os mesmos têm de ser rapidamente pesquisados por uma chave de procura- Necessidade de armazenar elementos (automaticamente) ordenados de acordo com um certo critério- Caso só possa existir um elemento armazenado por chave de procura utiliza-se o map, caso contrário, o multimap
set / multiset
- Nas condições de map/multimap mas em que a chave de procura é o próprio elemento
hash_map / hash_set
- Não existe necessidade de obedecer ao standard ANSI C++- Necessidade de uma maior velocidade de inserção, pesquisa e apagamento do que em map/multimap- Não é necessário (ou não faz sentido) existir um ordenamento por chave
![Page 55: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/55.jpg)
55
Adaptadores
Para além dos Containers básicos, existe um conjunto de classes que mascaram essas colecções e implementam um conjunto de estruturas de dados bastante úteis.
stack<T>:Armazena um conjunto de elementos permitindo inserir e retirar elementos segundo uma política FIRST-IN-LAST-OUT
Tipicamente utiliza um deque<T> como estrutura subjacente push(), pop(), top()
queue<T>:Armazena um conjunto de elementos permitindo inserir e retirar elementos segundo uma política FIRST-IN-FIRST-OUT
Tipicamente utiliza um deque<T> como estrutura subjacente push(), pop(), front(), back()
priority_queue<T>:Armazena um conjunto de elementos mantendo-os automaticamente ordenados
Tipicamente utiliza um vector<T> como estrutura subjacente (!! Cuidado !!)
push(), pop(), top()
![Page 56: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/56.jpg)
56
Algoritmos
A STL possui um largo conjunto de algoritmos que actuam sobre colecções
Os algoritmos dividem-se em categorias: Não Modificantes: for_each(), find(), find_if(),
adjacent_find(), find_first_of(), count(), count-if(), mismatch(), equal(), search(), search_n(), find_end(), ...
Modificantes: copy(), copy_n(), copy_backwards(), swap(), replace(), replace_if(), replace_copy(), replace_copy_if(), fill(), fill_n(), remove(), unique(), ...
Ordenamento: sort(), binary_sort(), includes(), set_union(), set_intersection(), min(), max(), ...
Numéricos: accumulate(), inner_product(), partial_sum(), power(), ...
Fortemente baseados no uso de iteradores
![Page 57: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/57.jpg)
57
Ordenar um vector
#include <vector>#include <iostream>#include <algorithm>using namespace std;
void print(vector<int>& v) { for (unsigned i=0; i<v.size(); i++) cout << v[i] << "\t"; cout << endl;}
void ex_algorithms() { // Um vector não ordenado vector<int> v;
// Acrescenta 10 números aleatórios ao vector for (unsigned i=0; i<10; i++) v.push_back(rand()%100);
// Mostra o vector antes e depois de ordenado print(v); sort(v.begin(), v.end()); print(v);}
![Page 58: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/58.jpg)
58
O resultado da execução...
![Page 59: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/59.jpg)
59
Mas, podemos re-escrever o código...
int random_number() { return rand() % 100;}
void ex_algorithms2(){ // v irá conter 10 valores aleatórios vector<int> v(10); generate(v.begin(), v.end(), random_number);
// Imprime a tabela for_each(v.begin(), v.end(), print_element<int>()); cout << endl;
// Ordena a tabela sort(v.begin(), v.end());
// Imprime a tabela for_each(v.begin(), v.end(), print_element<int>()); cout << endl;}
![Page 60: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/60.jpg)
60
print_element<int>
Trata-se de uma “função unária” definida por nós... A STL define outros tipos de funções (e.g. binárias... )
#include <functional>
template <class T>struct print_element : public unary_function<T,void>{ void operator()(T& toPrint) { cout << setw(5) << toPrint; }};
![Page 61: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/61.jpg)
61
print_element<int>
Trata-se de uma “função unária” definida por nós... A STL define outros tipos (e.g. binária... )
#include <functional>
template <class T>struct print_element : public unary_function<T,void>{ void operator()(T& toPrint) { cout << setw(5) << toPrint; }};
Método invocado na função
Tipo que devolve
Tipo do parâmetro de entrada
![Page 62: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/62.jpg)
62
E o resultado é...
![Page 63: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/63.jpg)
63
Um último exemplo do uso de algoritmos...
#define N_ELEMENTS(table,type) ( sizeof(table) / sizeof(type) )
void ex_set2() { // Cria duas tabelas estáticas int tabelaA[] = { 1, 2, 3, 4 }; int tabelaB[] = { 3, 4, 5, 6 };
// Calcula um conjunto resultante contendo a intercepção entre elas set<int> result; insert_iterator< set<int> > addToResult_it(result, result.begin());
set_intersection(tabelaA, tabelaA + N_ELEMENTS(tabelaA,int), tabelaB, tabelaB + N_ELEMENTS(tabelaB,int), addToResult_it);
// Imprime o resultado ostream_iterator<int> output(cout, " ");
cout << endl << "Conjunto A: \t"; copy(tabelaA, tabelaA + N_ELEMENTS(tabelaA,int), output);
cout << endl << "Conjunto B: \t"; copy(tabelaB, tabelaB + N_ELEMENTS(tabelaB,int), output);
cout << endl << "INTER(A,B): \t"; copy(result.begin(), result.end(), output);}
![Page 64: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/64.jpg)
64
Iteradores
No exemplo anterior vimos que é possível construir um iterador para inserções: insert_iterator
Vimos também que é possível criar um iterador que envia os dados para uma stream de output: ostream_iterator
Toda a STL é baseada em iteradores, dos quais existem os seguintes tipos: Input Iterators: Referem um objecto e podem ser
incrementados (apontados) para o próximo. Output Iterators: Permitem escrever objectos e ser
incrementados Forward Iterator: Permitem ler e escrever, sendo apenas
incrementáveis para o próximo. Bidirectional Iterators: Similar aos forward iterators mas
permitem avançar ou recuar. Random Access Iterators: Permitem acessos aleatórios à
colecção subjacente (inc. aritmética de ponteiros)
![Page 65: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/65.jpg)
65
Iteradores (2)
Usandos estes conceitos de iteradores, os tipos concretos são... istream_iterator ostream_iterator reverse_iterator reverse_bidirectional_iterator insert_iterator front_insert_iterator back_insert_iterator input_iterator output_iterator forward_iterator bidirectional_iterator random_access_iterator
Felizmente, em geralnão é necessário preocuparmo-nos comestes detalhes...
![Page 66: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/66.jpg)
66
Onde estamos nós?
OK!Container Classes
Iterators GenericAlgorithms
Vector
list
istream
ostream
inserterase
inserterase
sort
find
merge
istream_iterator
ostream_iterator
less
equal
greater
FunctionObjects
Pouco aprofundado
![Page 67: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/67.jpg)
67
Uma questão importante...
Um aspecto extremamente importante quando se usa a STL (e, na verdade, C++), é não fazer cópias desnecessárias de objectos
Regra geral, os objectos devem ser guardados num local. Caso estes sejam necessários noutras classes/métodos, devem de se utilizar referências Evita a chamada a copy-constructors e assigment operators Cada referência ocupa apenas 4 bytes (máquinas de 32bits)
Data
IndexA IndexB IndexC
1
*
1
*
1
*
«references» «references» «references»
![Page 68: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/68.jpg)
68
Pequeno exemplo
Pretende-se desenhar uma classe EMPREGADOS que permite armazenar PESSOAs Cada pessoa tem um
“nome”, uma “morada” e um “BI”
Vamos assumir que não existem duplicados (pessoas a viverem no mesmo local, com o mesmo nome ou com o mesmo BI)
A classe tem de suportar pesquisas de forma eficiente por “nome”, “morada” e “bilhete de identidade” As pesquisas devolvem uma
cópia da ficha (Pessoa). [Porquê uma cópia?]
+adicionaPessoa()+procuraPorNome()+procuraPorMorada()+procuraPorBI()
-_nomeIndex-_moradaIndex-_BIIndex
Empregados
1 *+_nome+_morada+_bi
Pessoa
NomeIndex : map<string,Pessoa*>
MoradaIndex : map<nome,Pessoa*>
BIIndex : map<int,Pessoa*>
1
*
1
*
1
*
Estes três objectoscorrespondemàs instâncias em"Empregados"
![Page 69: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/69.jpg)
69
Classe Empregados
class Empregados{private: map<string,Pessoa*> _nomeIndex; map<string,Pessoa*> _moradaIndex; map<int,Pessoa*> _BIIndex;
public: Empregados(); virtual ~Empregados();
void adicionaPessoa(const Pessoa& pessoa);
bool procuraPorNome(const string& nome, Pessoa& result); bool procuraPorMorada(const string& morada, Pessoa& result); bool procuraPorBI(int bi, Pessoa& result);};
![Page 70: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/70.jpg)
70
Estrutura Pessoa
struct Pessoa{ string nome; string morada; int bi;
Pessoa() {}
Pessoa(const string& o_nome, const string& a_morada, int o_bi) : nome(o_nome), morada(a_morada), bi(o_bi) {}
void print() { cout << "\t [ " << nome << " / " << morada << " / " << bi << "]" << endl; }};
![Page 71: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/71.jpg)
71
Implementação de Empregados
Empregados::Empregados(){}
void Empregados::adicionaPessoa(const Pessoa& pessoa){ Pessoa* p = new Pessoa(pessoa); _nomeIndex[pessoa.nome] = p; _moradaIndex[pessoa.morada] = p; _BIIndex[pessoa.bi] = p;}
Empregados::~Empregados(){ map<int,Pessoa*>::iterator it = _BIIndex.begin(); while (it != _BIIndex.end()) { Pessoa* p = it->second; ++it; delete p; }}
![Page 72: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/72.jpg)
72
Implementação de Empregados (2)
bool Empregados::procuraPorNome(const string& nome, Pessoa& result) { map<string,Pessoa*>::iterator it = _nomeIndex.find(nome); if (it == _nomeIndex.end()) return false; else { result = *(it->second); return true; }}
bool Empregados::procuraPorMorada(const string& nome, Pessoa& result) { // Similar ao método acima }
bool Empregados::procuraPorBI(int bi, Pessoa& result) { map<int,Pessoa*>::iterator it = _BIIndex.find(bi); if (it == _BIIndex.end()) return false; else { result = *(it->second); return true; }}
![Page 73: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/73.jpg)
73
Test Drive
Empregados loja;loja.adicionaPessoa(Pessoa("Maria", "Coimbra, 2", 234345));loja.adicionaPessoa(Pessoa("Sofia", "Lisboa, 3", 565655));loja.adicionaPessoa(Pessoa("Tania", "Porto, 5", 435675));
// ##########################################const int N = 4;const string nomes[N] = { "Maria", "Carlos", "Antonio", "Tania" };
Pessoa resultado;for (unsigned i=0; i<N; i++){ cout << "A pesquisar nome: " << nomes[i] << endl; if (loja.procuraPorNome(nomes[i], resultado)) resultado.print(); else cout << "\t Nao encontrado" << endl;}
(...)
![Page 74: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/74.jpg)
74
Resultado da Execução...
![Page 75: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/75.jpg)
75
Para aprender mais...
Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library, by Scott MeyersAddison-Wesley, June 2001
The C++ Standard Library : A Tutorial and Reference, by Nicolai M. JosuttisAddison-Wesley Professional, August 1999
C++ Primer, 4th Editionby Stanley B. Lippman et. al.Addison-Wesley Professional, Feb. 2005 “A bíblia laica do C++”, com cobertura
adequada da STL
Standard Template Library Programmer's Guide SGI Online Reference: http://www.sgi.com/tech/stl/
![Page 76: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/76.jpg)
76
IMPORTANT NOTICE
YOU ARE FREE TO USE THIS MATERIAL FOR YOUR PERSONAL LERNING OR REFERENCE, DISTRIBUTE IT AMONG COLLEGUES OR EVEN USE IT FOR TEACHING CLASSES. YOU MAY EVEN MODIFY IT, INCLUDING MORE INFORMATION OR CORRECTING STANDING ERRORS.
THIS RIGHT IS GIVEN TO YOU AS LONG AS YOU KEEP THIS NOTICE AND GIVE PROPER CREDIT TO THE AUTHOR. YOU CANNOT REMOVE THE REFERENCES TO THE AUTHOR OR TO THE INFORMATICS ENGINEERING DEPARTMENT OF THE UNIVERSITY OF COIMBRA.
(c) 2005 – Paulo Marques, [email protected]
![Page 77: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/77.jpg)
Standard TemplateLibrary
Paulo MarquesDepartamento de Eng. InformáticaUniversidade de [email protected] O
ut/2
005
Sessão Prática
![Page 78: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/78.jpg)
78
Problema 1 – Conta Palavras
Implemente um programa que dado um ficheiro de texto, conte o número de ocorrências de cada palavra nesse ficheiro. Assuma que o ficheiro pode ser de gigantesco (1 ou 2GB) Assuma que o número de palavras diferentes pode ser
bastante elevado Como resultado da execução deve ser enviado
para o ecrã o número de ocorrências de cada palavra (par palavra/nº vezes). Numa primeira fase apresente o resultado por ordem
alfabética de palavras Numa segunda fase, apresente o resultado por ordem de
ocorrência de palavras (na mais frequente para a menos)
Não é necessário preocupar-se com a leitura do ficheiro: pode lê-lo do standard input:
$ ./ocorrencias <romance.txt
![Page 79: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/79.jpg)
79
Problema 2 – Anagramas
Dado um dicionário de palavras de uma língua, encontrar todos os anagramas existentes. Por exemplo: “barragem”, “embargar” são anagramas pois
escrevem-se exactamente com as mesmas letras.
O ficheiro “english.txt” contém um dicionário de inglês que poderá utilizar nos seus testes. Se desejar, poderá ser-lhe fornecido um dicionário de
Português, mas nesse caso terá de ser preocupar com os acentos...
O ficheiro também contém palavras que começam por maiúscula
Qual é o maior número de anagramas existentes? Numa primeira fase mostre apenas os existentes Numa segunda, mostre do maior número de anagramas para o
menor.
![Page 80: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/80.jpg)
80
Problema 3 – Árvore Mínima Abrangente
1
1
1
A
B
C
D
E
F
G
H
I
J
K
1
1
10
5
2
343
5
Árvore Mínima Abrangente: Uma árvore que passa por todos os nodos em que o custo total é mínimo.(Nota: isto não é uma árvore que minimiza o caminho/tempo que os pacotes têm de percorrer!)
![Page 81: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/81.jpg)
81
Árvore Mínima Abrangente
1
1
1
A
B
C
D
E
F
G
H
I
J
K
1
1
10
5
2
343
5
![Page 82: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/82.jpg)
82
“Algoritmo de Prim”
Começa-se com uma aresta de peso mínimo
Até que não seja possível adicionar arestas (altura em que formaria um ciclo) Encontrar a aresta de menor peso ligado a um nodo
existente na árvore mínima actual e que não forme um ciclo se for adicionado
Adiciona-se essa aresta à árvore mínima actual
![Page 83: Standard Template Library Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Out/2005 Uma Introdução](https://reader035.vdocuments.site/reader035/viewer/2022062318/552fc101497959413d8bda1f/html5/thumbnails/83.jpg)
83
Funcionalidades do Programa
Dada a descrição de uma rede: Permite modelar essa
rede Calcula a árvore mínima
abrangente Imprime a árvore
mínima abrangente Simula o envio de um
pacote de um nodo para outro
int main(){ Network net;
net.addConnection("A", "D", 1); net.addConnection("B", "D", 1); net.addConnection("D", "E", 3); net.addConnection("C", "E", 1); net.addConnection("D", "F", 2); net.addConnection("E", "F", 4); net.addConnection("F", "G", 3); net.addConnection("G", "I", 1); net.addConnection("F", "J", 1); net.addConnection("F", "H", 5); net.addConnection("H", "K", 10);
net.calculateMinimumSpanningTree(); net.printMinimumSpanningTree(); net.sendPacket("C", "K");
return 0;}