Post on 17-Apr-2015
1 2008 LCG/UFRJ. All rights reserved.
Standard Template LibraryStandard Template Library STL STL
Claudio EsperançaPaulo Roma Cavalcanti
2 2008 LCG/UFRJ. All rights reserved.
O que é a STL?O que é a STL?
• STL é uma biblioteca padrão com as estruturas de dados mais usadas em Computação. ▪Foi criada para evitar a implementação e
teste das mesmas estruturas de dados eternamente.
▪Por isso, economiza muito tempo e evita “dor de cabeça” desnecessária.
• Por que templates?▪Elas lhe poupam da tarefa de
reimplementar o código para cada novo tipo de dado da sua aplicação.
3 2008 LCG/UFRJ. All rights reserved.
STLSTL
• Quando usadas apropriadamente, as templates são bastante eficazes.▪ No entanto, as mensagens de erro costumam
ser pouco elucidativas.• Uma boa fonte sobre a STL é o guia de
programação da SGI.▪ Ou então a nossa implementação de um
subconjunto da STL.• Na nossa implementação, cada classe tem o
prefixo “utl” (não havia namespace ainda).▪ Se a variável de compilação USE_STL estiver
definida, o prefixo será suprimido, “cgcUtil::” será substituído por “std::”, e o compilador usará a STL nativa então.
4 2008 LCG/UFRJ. All rights reserved.
Estrutura da STLEstrutura da STL
• A STL oferece:▪Containers (recipientes).▪ Iterators (iteradores).▪Algorithms (algoritmos).
• Recipientes servem para armazenar dados e podem ser classificados como:▪Seqüências de dados ▪Recipientes associativos para pares de
objetos (chave, dado).▪Adaptadores que provêem um
subconjunto da funcionalidade de um recipiente.◦Pilhas, filas, filas de prioridade.
5 2008 LCG/UFRJ. All rights reserved.
IteradoresIteradores
• Iteradores foram criados para permitir uma maneira unificada de percorrer ou recuperar dados de recipientes.▪Escondem os detalhes de implementação,
principalmente ponteiros, das aplicações.▪Portanto, geralmente é possível trocar o
tipo de recipiente e ainda assim usar o mesmo código.
• A STL adota a filosofia de manter os algoritmos fora das classes dos recipientes.▪A razão é permitir que o mesmo algoritmo
possa agir sobre recipientes diferentes.
6 2008 LCG/UFRJ. All rights reserved.
ExemploExemplo
• Geralmente os algoritmos são implementados usando iteradores apenas.▪Ordenação, busca, contagem,
substituição, etc...▪Iteradores tem operadores de
incremento “++” definidos. ▪Ponteiros podem ser usados como
iteradores.
7
2008 LCG/UFRJ. All rights reserved.
Imprimindo Imprimindo elementos de elementos de
um vetorum vetor
#include <vector>#include <iostream>using namespace std; /** função objeto. * Insere T em um stream de saída. * Substitui “passar ponteiro para função” de C. */template <class T> struct print : public unary_function <T, void> {
print(ostream& out) : os(out), count(0) {} void operator() (T x) { os << x << ' '; ++count; } ostream& os; int count; }; int main() { int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int);
print<int> P = for_each(A, A + N, print<int>(cout)); cout << endl << P.count << " objects printed." << endl;
return 1; }
1 4 2 8 5 76 objects printed.
Calcula o tamanho
de A Dois iteradore
s
Redefine operador
( )
Construtor
Guarda número
de elemento
s impresso
s
Chama print() para
cada elemento de
A
8 2008 LCG/UFRJ. All rights reserved.
VectorVector
• vector é o recipiente mais simples da STL.▪É uma seqüência que suporta acesso
aleatório aos seus elementos.▪ Inserção e remoção de elementos no final
em O(1).▪ Inserção e remoção de elementos no meio
em O(n).▪Busca em O(n).▪Gerenciamento automático de memória.▪ Iteradores estão invalidados após
realocação de memória, inserção e remoção no meio.
▪Descrição e implementação.
9
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe vectorvector..
#include <vector>#include <iostream>#include <iterator>#include <ext/algorithm>using namespace std;using __gnu_cxx::is_sorted;
int main(){ vector<int> V; V.push_back(20); V.push_back(30); V.push_back(-1); V.push_back(-1); V.push_back(-1); cout << "V: \n"; copy(V.begin(), V.end(), ostream_iterator<int>(cout, " ")); stable_sort (V.begin(), V.end()); cout << "\nV: sorted\n"; copy(V.begin(), V.end(), ostream_iterator<int>(cout, " ")); cout << "\nV: is sorted? "; cout << is_sorted ( V.begin(), V.end() ) << "\n";}
V: 20 30 -1 -1 -1 V: sorted-1 -1 -1 20 30 V: is sorted? 1
Insere no final de
V.Insere V
no stream
de saída
Ordena V com
merge sort. Verifica
se V está ordenado
.
10
2008 LCG/UFRJ. All rights reserved.
FunçãoFunção copy copy..
/** copies elements from a container to another. * * Copies elements from the range [first, last) to the * range [result, result + (last - first)). * That is, it performs the assignments * *result = *first, *(result + 1) = *(first + 1), and so on. * Generally, for every integer n from 0 to last - first, * copy() performs the assignment *(result + n) = *(first + n). * Assignments are performed in forward order, i.e. in order of * increasing n. * * The return value is result + (last - first) * * @param first where to start copying. * @param last where to end copying. * @param result where to copy. * @return result + (last-first). */template<class InputIterator, class OutputIterator> inline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { for( InputIterator itr = first; itr != last; ++itr, ++result ) {
*result = *itr; } return result;}
Apenas percorre o
recipiente de entrada.
E atribui ao
recipiente da
saída.
Derivados da mesma
classe base.
11 2008 LCG/UFRJ. All rights reserved.
DequeDeque
• deque (Double Ended Queue) é como um vetor com inserção eficiente na frente também.▪ É uma seqüência que suporta acesso aleatório
aos seus elementos.▪ Inserção e remoção de elementos no meio em
O(n).▪ Busca em O(n).▪ Inserção e remoção de elementos na frente e no
final em O(1).▪ Gerenciamento automático de memória.▪ Iteradores estão invalidados após realocação de
memória, inserção e remoção no meio.▪ Descrição e implementação.
12
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe ddequeeque..
#include <deque>#include <iostream>#include <iterator>
using namespace std;
int main() {
deque<int> Q;Q.push_back(3);Q.push_front(1);Q.insert(Q.begin() + 1, 2);Q[2] = 0;copy(Q.begin(), Q.end(), ostream_iterator<int>(cout, " "));cout << "\n";// The values that are printed are 1 2 0Q.insert(Q.begin() + 1, (size_t)3, 5);Q.push_front(7);Q.push_front(8);Q.push_front(9);
Insere 5 três vezes
após a primeira posição.
13
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe dequedeque..
copy(Q.begin(), Q.end(), ostream_iterator<int>(cout, " "));cout << "\n";deque<int> P = Q;copy(Q.begin(), Q.end(), ostream_iterator<int>(cout, " "));cout << "\n";P.resize ( 18, 88 );P.push_front ( 99 );P.push_front ( 98 );copy(P.begin(), P.end(), ostream_iterator<int>(cout, " "));P.erase ( P.begin(), P.begin()+2 );cout << "\n";cout << P.back();cout << "\n";cout << P.front();cout << "\n";cout << *P.begin();cout << "\n";}
1 2 09 8 7 1 5 5 5 2 09 8 7 1 5 5 5 2 098 99 9 8 7 1 5 5 5 2 0 88 88 88 88 88 88 88 88 88889
9
Redimensiona P
completando com 88 no
final.Remove os
dois primeiros elementos
de P.Último
elemento de P
Primeiro elemento
de P
14 2008 LCG/UFRJ. All rights reserved.
ListList
• list é de fato uma lista duplamente encadeada. ▪É uma seqüência que suporta percurso
para frente e para trás. ▪Busca em O(n).▪Inserção e remoção de elementos na
frente, no meio e no final em O(1).▪Iteradores ainda estão válidos após
inserção, splicing ou remoção.▪Descrição, Implementação.
15
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe listlist..
#include <list>#include <iostream>#include <iterator>
using namespace std;
int main(){ list<int> L; L.push_back(0); L.push_front(1); L.insert(++L.begin(), 2); copy(L.begin(), L.end(), ostream_iterator<int>(cout, " ")); cout << "\n"; list<int> M ( L ); L.splice ( ++++L.begin(), M ); copy(L.begin(), L.end(), ostream_iterator<int>(cout, " ")); cout << “\n”; copy(M.begin(), M.end(), ostream_iterator<int>(cout, " "));}
1 2 01 2 1 2 0 0
Insere 0 no final
de LInsere 1 no início
de L.
Insere 2 após a
primeira posição.Move
elementos de M para
L.
M está vazia.
16 2008 LCG/UFRJ. All rights reserved.
StringString
• string toma o lugar de um “array of char”.▪Não é mais necessário se preocupar
com o tamanho do arranjo. ▪Oferece todas as funções de C
pertinentes a strings como membros da classe.
▪Evita erros relacionados com ponteiros, na chamada de funções que recebem ou retornam strings.
▪Descrição, Implementação.
17
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe stringstring..
#include <string>#include <iostream>using namespace std;
int main () { //test constructors string str0; cout << "empty constructor: " << str0 << endl; cout << "str0 size = " << str0.size() << endl; string str1("hellow world!"); // 0123456789012 cout << "const char constructor: " << str1 << endl; cout << "data = " << str1.data() << endl; cout << "size = " << str1.size() << endl; cout << "length = " << str1.length() << endl; cout << "capacity = " << str1.capacity() << endl; cout << "max_size = " << str1.max_size() << endl; // empty cout << "str0 empty = " << str0.empty() << endl; cout << "str1 empty = " << str1.empty() << endl;
empty constructor: str0 size = 0const char constructor: hellow world!data = hellow world!size = 13length = 13capacity = 13max_size = 13str0 empty = 1str1 empty = 0
Capacidade da string
sem ter de realocar.
Tamanho máximo que uma string pode ter.
Comprimento atual da
string
O mesmo que length.
18
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe stringstring..
string str2(str1); cout << “copy constructor: " << str2 << endl; string str3(str1, 4, 6); cout << "string&, pos, npos, str3 constructor: " << str3 << endl; string str4("hellow word!", 6); cout << "char[], npos, str4 constructor: " << str4 << endl; string str5(12, 'h'); cout << “n, char str5 constructor: " << str5 << endl; cout << "str5 size = " << str5.size() << endl; // swap str5.swap(str1); cout << "swap str1 and str5" << endl; cout << "str1 = " << str1 << endl; cout << "str5 = " << str5 << endl;}
copy constructor: hellow world!string&, pos, npos, str3 constructor: ow worchar[], npos, str4 constructor: hellown, char str5 constructor: hhhhhhhhhhhhstr5 size = 12swap str1 and str5str1 = hhhhhhhhhhhhstr5 = hellow world!
Troca o conteúdo
de str5 por str1.
19 2008 LCG/UFRJ. All rights reserved.
SetSet
• set é uma coleção ordenada de objetos do tipo “key” sem duplicatas.▪Operações de conjunto como interseção,
união e diferença são eficientes.▪ Implementado por uma árvore
balanceada de busca (Red Black, Splay).▪Busca em O(log n).▪Descrição, Implementação.
• multiset é a versão que permite duplicatas.▪Descrição, Implementação.
20
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe setset..
#include <set>#include <iostream>using namespace std;
/// função objeto. Compara duas seqüências de caracteres.struct ltstr{ bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }};
int main(){ const int N = 6; const char* a[N] = {"isomer", "ephemeral", "prosaic", "nugatory", "artichoke", "serif"}; const char* b[N] = {"flat", "this", "artichoke", "frigate", "prosaic", "isomer"};
set<const char*,ltstr> A(a, a + N); set<const char*,ltstr> B(b, b + N); set<const char*,ltstr> C;
Retorna se s1 é lexicograficam
ente menor que s2
Construtor a partir de dois
iteradores
21
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe setset..
cout << "Set A: "; copy(A.begin(), A.end(), ostream_iterator <const char*>(cout, " ")); cout << endl; cout << "Set B: "; copy(B.begin(), B.end(), ostream_iterator <const char*>(cout, " ")); cout << endl;
cout << "Union: "; set_union(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator<const char*>(cout, " "), ltstr()); cout << endl;
cout << "Intersection: "; set_intersection(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator<const char*>(cout, " "), ltstr()); cout << endl;
set_difference(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()), ltstr()); cout << "Set C (difference of A and B): "; copy(C.begin(), C.end(), ostream_iterator <const char*>(cout, " ")); cout << endl;}
Set A: artichoke ephemeral isomer nugatory prosaic serif Set B: artichoke flat frigate isomer prosaic this Union: artichoke ephemeral flat frigate isomer nugatory prosaic serif this Intersection: artichoke isomer prosaic
Set C (difference of A and B): ephemeral nugatory serif
A ∪ B.
A ∩ B.
A – B.
Insere o resultado
em C.
22 2008 LCG/UFRJ. All rights reserved.
MapMap
• map associa objetos do tipo “key” a objetos do tipo “data”.▪Nenhum par de elementos possui a mesma
chave.▪Percurso é ordenado.▪ Indicada para implementação de dicionários.▪ Implementada por uma árvore balanceada
de busca (Red Black, Splay).▪Busca em O(log n).▪Descrição, Implementação.
• multimap é a versão que permite duplicatas.▪Descrição, Implementação.
23
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe mapmap..
#include <map>#include <string>#include <iostream>
using namespace std;
typedef map < long, string > mapType;typedef mapType::value_type ValuePair;
int main() {
mapType Map;
Map[836361136] = "Andrew"; Map[274635328] = "Berni"; Map[974635328] = "Ulisses"; Map[277735328] = "Paulo"; Map[277825328] = "Pedro"; Map[266735328] = "Peter"; Map[275734328] = "Paula"; Map[275839328] = "Paulos"; Map.insert(ValuePair(260736622, "John")); Map.insert(ValuePair(720002287, "Karen")); Map.insert(ValuePair(138373498, "Thomas")); Map.insert(ValuePair(135353630, "William")); // insertion of Xaviera is not executed, because // the key already exists. Map.insert(ValuePair(720002287, "Xaviera"));
mapType Map2 ( Map.begin(), Map.end() ); cout << "equality operator " << (Map2 == Map) << endl;
Duas formas de inserção
Chave e dado.
Cria um par
(chave,dado).
equality operator 1Output:974635328:Ulisses836361136:Andrew720002287:Karen277825328:Pedro277735328:Paulo275839328:Paulos275734328:Paula
Ordem decresce
nte.
24
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe mapmap..
cout << "Output:\n";
Map.erase ( 720002287 ); Map2.swap ( Map ); mapType::const_reverse_iterator iter = Map.rbegin(); while( iter != (mapType::const_reverse_iterator)Map.rend() ) { cout << (*iter).first << ':' << (*iter).second << endl; ++iter; }
cout << "Output of the name after entering the number\n" << "Number: "; long Number;
cin >> Number; mapType::const_iterator it = Map.find(Number);
if(it != Map.end()) { cout << (*it).second << ' ' // O(1)
<< endl; } else cout << "Not found!" << endl;}
Se encontra
do.
Busca é O(log n).
Iterador reverso.
Cast para
iterador constant
e.
274635328:Berni266735328:Peter260736622:John138373498:Thomas135353630:WilliamOutput of the name after entering the numberNumber: 275734328Paula
25 2008 LCG/UFRJ. All rights reserved.
Hash MapHash Map
• hash_map associa objetos do tipo “key” a objetos do tipo “data”.▪ Nenhum par de elementos possui a mesma
chave.▪ Não há ordem de percurso.▪ Implementada por uma hash table.
◦ Há uma função de hash que gera endereços a partir de chaves.
▪ Busca em O(1).▪ Descrição, Implementação.
• hash_multimap é a versão que permite duplicatas.▪ Descrição, Implementação.
26
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe hash_maphash_map..
#include <ext/hash_map>#include <string>#include <iostream>
using namespace std;using __gnu_cxx::hash_map;using __gun_cxx::hash;
// initial hash table size#define table_size 11
// define your own hash functiontemplate <class T> class my_hash: public hash<T> {public:
my_hash() {}
size_t operator()(const string& p) const { hash<const char*> h; return h(p.c_str()); }}; typedef hash_map<string, string, my_hash<string> > mapType;typedef mapType::value_type ValuePair;
int main() {
mapType Map ( table_size, my_hash <string>() );
Map["ANDREW"]="Andrew"; Map["BERNI"]="Berni"; Map["JOHN"]="John"; Map.insert(ValuePair("KAREN", "Karen")); Map.insert(ValuePair("THOMAS", "Thomas")); Map["WILLIAM"]="William"; // insertion of Xaviera is not executed, because // the key already exists. Map.insert(ValuePair("BERNI", "Xaviera"));
Recebe string e passa char*.
27
2008 LCG/UFRJ. All rights reserved.
Uso da classe Uso da classe hash_maphash_map..
cout << "Output:\n";
mapType::iterator iter = Map.begin(); while(iter != Map.end()) { cout << (*iter).first << ':' << (*iter).second << endl; ++iter; }
cout << "Output of the name after entering the key\n" << "Key: "; char buf[256]; buf[0] = '\0'; fgets ( buf, 256, stdin ); if ( buf[strlen(buf)-1]=='\n' ) buf[strlen(buf)-1] = '\0'; string key ( buf );
iter = Map.find(key);
if(iter != Map.end()) { cout << (*iter).second << ' '
<< Map[key] << endl;
} else cout << "Not found!" << endl;
}
Elimina \n do final de buf.
Busca é O(1)
Output:JOHN:JohnBERNI:BerniKAREN:KarenANDREW:AndrewTHOMAS:ThomasWILLIAN:WillianOutput of the name after entering the keyKey: KARENKaren Karen
Não há ordem.