• Nenhum resultado encontrado

algoritmosgentericosum

N/A
N/A
Protected

Academic year: 2021

Share "algoritmosgentericosum"

Copied!
56
0
0

Texto

(1)

Programa¸c˜

ao Gen´erica - Algoritmos Gen´ericos

Andr´e Duarte Bueno, Dr. Eng.

(2)

Conte´udo

ê Introdu¸c˜ao `a programa¸c˜ao gen´erica, aos algoritmos gen´ericos

ê Classifica¸c˜ao dos algoritmos gen´ericos

ê Fun¸c˜oes gen´ericas

• Preenchimento

• Compara¸c˜ao

• Remo¸c˜ao, Trocas

• Misturar/Mesclar/Inverter

• Pesquisar, Ordena¸c˜ao, Classifica¸c˜ao

• Transforma¸c˜ao

• Matem´aticos, Opera¸c˜oes com conjuntos, Ordena¸cao de pilhas

Nota: uma descri¸c˜ao detalhadas das fun¸c˜oes gen´ericas pode ser obtida em http://www. cplusplus.com/reference/algorithm/.

(3)

Introdu¸c˜ao `a programa¸c˜ao gen´erica

Embora o conceito de programa¸c˜ao gen´erica seja antigo (cerca de 30 anos), seu uso se intensificou com a inclus˜ao na STL de um conjunto de fun¸c˜oes gen´ericas. Ou seja, a STL fornece, al´em de uma biblioteca de classes containers, um vasto conjunto de fun¸c˜oes para pesquisa, ordena¸c˜ao, mistura, troca e transforma¸c˜oes em um container.

ê Cada fun¸c˜ao pode ser aplicada a um conjunto espec´ıfico de containers.

ê Algumas fun¸c˜oes gen´ericas exigem que a classe container j´a tenha sido ordenada.

ê De uma maneira geral, as fun¸c˜oes gen´ericas utilizam iteradores para acessar e

ma-nipular os containers.

ê As fun¸c˜oes gen´ericas foram constru´ıdas de forma a necessitar de um n´umero reduzido de servi¸cos dos iteradores.

ê O uso de gabaritos (templates) e de fun¸c˜oes gen´ericas permite a implementa¸c˜ao de algoritmos independentes do tipo de dados a ser utilizado.

(4)

Classifica¸c˜ao das fun¸c˜oes gen´ericas

Veja a seguir uma classifica¸c˜ao das fun¸c˜oes gen´ericas quanto `a mudan¸ca do container, quanto ao iterador necess´ario e quanto ao tipo das opera¸c˜oes.

(5)

Classifica¸c˜ao quanto `a modifica¸c˜ao do container

ê Fun¸c˜oes que n˜ao mudam o container:

accumulate, find, max, adjacent find, find if, max element, binary search, min, count, find first of, for each, min element, count if, includes, mismatch, equal, le-xicographical compare, nth element, equal range, lower bound, mismatch, search, search n,

find end, upper bound.

ê Fun¸c˜oes que mudam o container:

copy, remove if, copy backward, replace, fill, replace copy, fill n, replace copy if, ge-nerate, replace if, generate n, reverse, inplace merge, reverse copy, iter swap, rotate swap, make heap, rotate copy, merge, set difference, nth element, next permutation, set intersection, set symmetric difference, partial sort, set union, partial sort copy, sort, partition, sort heap, prev permutation, stable partition, push heap, stable sort, pop heap, swap, random shuffle, swap ranges, remove, transform, unique, unique copy, remove copy, remove copy if.

(6)

Classifica¸c˜ao quanto `a categoria dos iteradores

ê Algoritmos que n˜ao usam iterador:

max, min, swap.

ê Requer somente InputIterator:

accumulate, find, mismatch, count, find if, count if, includes, equal, inner product, for each, lexicographical compare.

ê Requer somente OutputIterator:

fill n, generate n.

ê Lˆe de um InputIterator e escreve para um OutputIterator:

adjacent difference, replace copy, transform, copy, replace copy if, unique copy, merge, set difference, partial sum, set intersedtion, remove copy, set symmetric difference, remove copy if, set union.

ê Requer um ForwardIterator:

(7)

unique, min element, swap ranges, fill, remove, find first of, remove if, upper bound, generate, replace, iter swap, replace if.

ê Lˆe de um ForwardIterator e escreve para um OutputIterator:

rotate copy.

ê Requer um BidirectionalIterator:

copy backward, partition, inplace merge,

prev permutation, next permutation, reverse, stable permutation.

ê Lˆe de um BidirectionalIterator e escreve em um OutputIterator:

reverse copy.

ê Requer um iterator randˆomico, RandomAccessIterator:

make heap, pop heap, sort, nth element, push heap, sort heap, partial sort, random shuffle, stable sort.

ê Lˆe de um InputIterator e escreve para um RandomAccessIterator:

(8)

Classifica¸c˜ao quanto `as opera¸c˜oes realizadas

ê Opera¸c˜oes de preenchimento:

fill, fill n, copy, copy backward

ê Opera¸c˜oes de compara¸c˜ao:

equal, mismatch, lexicographical compare, includes

ê Opera¸c˜oes de remo¸c˜ao:

remove, remove if, remove copy, remove copy if

ê Opera¸c˜oes de troca (swap):

swap, swap ranges, iter swap, replace, replace copy, replace copy if, replace if

ê Opera¸c˜oes de mistura:

inplace merge, merge, reverse, reverse copy, random shuffle, rotate, rotate copy

ê Opera¸c˜oes de pesquisa:

find, adjacent find, find if, find first of, count if, search, find, binary search, se-arch n, lower bound, equal range, upper bound

(9)

ê Opera¸c˜oes de ordena¸c˜ao:

sort, partial sort, stable sort, partial sort copy, nth element

ê Opera¸c˜oes de classifica¸c˜ao:

unique copy, unique

ê Opera¸c˜oes de transforma¸c˜ao:

generate n, generate, for each, transform, partition, stable partition

ê Opera¸c˜oes matem´aticas:

max, min, max element, min element, count, count if, accumulate

ê Opera¸c˜oes de set (conjuntos):

set symmetric difference, set difference, set union, set intersection

ê Opera¸c˜oes de pilha:

(10)

Fun¸c˜oes gen´ericas

Veremos a seguir uma breve descri¸c˜ao de cada fun¸c˜ao gen´erica oferecida pela STL. Se o leitor n˜ao compreender determinada fun¸c˜ao, a dica ´e ver os exemplos apresentados no final deste cap´ıtulo. Observe que apresentamos a forma de uso e n˜ao o prot´otipo; o prot´otipo das fun¸c˜oes gen´ericas ´e encontrado no arquivo de cabe¸calho <algorithm> ou no site http://www.sgi.com/tech/stl/.

(11)

Preenchimento

As fun¸c˜oes fill() e copy() s˜ao utilizadas para preencher o container.

fill (d.begin(), d.end(), valor);

Utiliza fill para preencher o container de begin() a end() com o valor. Veja listagem 1.

fill n (d.begin(), n, valor);

A partir da posi¸c˜ao begin(), preencher n elementos do container com o valor.

copy (orig.begin(), orig.end(), out);

Copia de first a last para out. Utilize copy() para gerar uma sa´ıda do container ou para gerar um novo container. A fun¸c˜ao copy() ´e usada para copiar blocos de dados de um container para outro. Veja listagens 2 e 3.

copy backward (orig.begin(), orig.end(), dest.end());

Copia os elementos de orig para dest; orig[0] ´e colocado no fim de dest, e assim sucessivamente.

(12)

Compara¸c˜ao

Os algoritmos a seguir s˜ao utilizados para comparar containers ou elementos de con-tainers. Para comparar elementos de containers do mesmo tipo use == ou <.

equal (v1.begin(), v1.end(), v2.begin());

Compara a igualdade de cada elemento dos containers v1 e v2. Retorna true se for tudo igual.

mismatch (v1.begin(), v1.end(), v2.begin());

Retorna um par de iteradores que apontam para objetos de v1 e v2 que s˜ao diferentes. Se v1 == v2, os iteradores apontam para end().

lexicographical compare (v1.begin(), v1.end(), v2.begin(), v2.end());

Retorna a posi¸c˜ao onde os containers v1 e v2 s˜ao diferentes.

includes (a, a+size, b, b+size);

Compara os containers ordenados a e b; se qualquer elemento de b estiver presente em a, retorna true. Veja listagem ??.

(13)

Remo¸c˜ao

Os algoritmos a seguir s˜ao utilizados para remover elementos do container. Observe que os elementos n˜ao s˜ao de fato removidos, apenas movidos para o fim do container (no intervalo de valores entre size() e capacity()).

remove (v.begin(), v.end(), valor);

Percorre todo o container (de begin() a end()) e remove os objetos que tˆem seu conte´udo igual a valor.

remove if (v.begin(), v.end(), Fun¸c˜aoPredicado);

Remove de begin() a end() se a fun¸c˜ao predicado retornar true.

remove copy (orig.begin(), orig.end(), d.begin(), valor);

Remove de begin() a end() o valor e copia para d. Se o container d for pequeno, haver´a estouro de pilha.

remove copy if (o.begin(), o.end(), d.begin(), fpred);

(14)

Troca

Os algoritmos a seguir s˜ao utilizados para trocar elementos de containers.

replace (v.begin(), v.end(), valor, novoValor);

Troca de begin() a end() valor por novoValor.

replace if (v.begin(), v.end(), Fun¸c˜aoPredicado, novoValor);

Se a fun¸c˜ao predicado retornar true, troca pelo novoValor.

replace copy (orig.begin(), orig.end(), d.begin(), valor, novoValor);

Troca de begin() a end() valor por novoValor e copia para d.

replace copy if (orig.begin(), orig.end(), d.begin(), Fun¸c˜aoPredicado, novo-Valor);

Se a fun¸c˜ao predicado retornar true, troca por novoValor no destino d.

swap (v[0], v[1]);

(15)

iter swap (it1, it2);

Troca os objetos apontados por it1 e it2.

swap range (v, v+3, v+4);

Troca os objetos no intervalo especificado. O primeiro intervalo vai de v a v+3 (excluindo v+3). O segundo intervalo inicia-se em v+4.

(16)

Misturar/Mesclar/Inverter

Os algoritmos a seguir s˜ao utilizados para misturar, mesclar ou inverter elementos de diferentes containers.

merge (orig1.begin(), orig1.end(), orig2.begin(), orig2.end(), dest.begin())

Pega os containers orig1 e orig2, que devem estar ordenados, e cria um container v3 com todos os elementos de orig1 e orig2. A seguir, copia os elementos de v3 para dest.

merge (orig1.begin(), orig1.end(), orig2.begin(), orig2.end(), back inserter(d))

Pega os containers orig1 e orig2, que devem estar ordenados, e cria um contai-ner v3 com todos os elementos de orig1 e orig2. Depois copia v3 para d usando push_back().

inplace merge (v.begin(), v.begin()+n, v.end())

Mistura dois conjuntos de dados do mesmo container. Ir´a misturar os valores de be-gin() a bebe-gin()+n com os valores a partir de bebe-gin()+n (sem ultrapassar v.end()).

(17)

reverse (v.begin(), v.end());

Muda a ordem; o primeiro passa a ser o ´ultimo. Veja listagem ??.

reverse copy (orig.begin(), orig.end(), back inserter(dest));

Inverte os elementos de orig e copia para dest. A fun¸c˜ao back_inserter() chama a fun¸c˜ao push_back() de dest para inserir os elementos em dest.

rotate (v.begin(), v.end(), v.begin());

Rotaciona ciclicamente. Veja listagem ??.

random shufle (v.begin(), v.end());

(18)

Pesquisa

Os algoritmos a seguir s˜ao utilizados para pesquisar/localizar determinado valor ou condi¸c˜ao. Para fazer pesquisa de tr´as para frente use um reverse_iterator.

find (v.begin(), v.end(), valor);

O find() procura por valor no intervalo especificado. Veja listagens 1 e 4.

find if (v.begin(), v.end(), Fun¸c˜aoPredicado);

O find_if() procura no intervalo [first-last) o objeto que satisfa¸ca `a fun¸c˜ao predi-cado. Veja listagem 1.

find first of (v1.begin(), v1.end(), v2.begin(), v2.end());

Retorna iterador para elemento de v1 que existe em v2.

find end(v1.begin(), v1.end(), v2.begin(), v2.end());

Procura a ´ultima ocorrˆencia de uma subsequˆencia em um intervalo. Procura no intervalo [v1.begin(), v1.end()) por uma sub-sequˆencia de valores iguais no inter-valo [v2.begin(), v2.end()) e retorna um iterador para primeiro elemento na sub-sequˆencia.

(19)

adjacent find (v.begin(), v.end());

Procura pelo primeiro par de valores iguais e adjacentes; retorna iterador para o primeiro elemento.

binary search (v.begin(), v.end(), valor);

Retorna true se o valor estiver presente no container. O container deve estar orde-nado.

lower bound (v.begin(), v.end(), valor);

Retorna um iterador para o primeiro elemento igual ao valor. Para manter o contai-ner ordenado, inserir valor utilizando o iterador retornado. No exemplo a seguir, se o vetor v tem os elementos 3,4,6,12,34,34,34,50 e valor=34, lower_bound() retorna iterador para o primeiro 34.

Exemplo:

vector<int>::iterator lower;

lower = lower_bound(v.begin(),v.end(),valor); upper bound (v.begin(), v.end(), valor);

(20)

Retorna um iterador para o primeiro elemento maior que valor. Se tiver 3,4,6,12,34,34,50 e valor=34, retorna iterador para 50.

Exemplo :

vector<int>::iterator uper = uper_bound(v.begin(),v.end(),valor); equal range (v.begin(), v.end(), valor);

Retorna um pair para aplica¸c˜ao de first=lower_bound() e second=uper_bound(). Exemplo:

pair<vector<int>::iterator, vector<int>::iterator> p; p = equal_range(v.begin(),v.end(),valor);

search (v.1begin(), v1.end(), v2.begin(), v2.end());

Procura uma seq¨uˆencia de v1.begin() a v1.end() que exista em v2.begin() a v2.end(). Ou seja, a seq¨uˆencia do container v1 existe no container v2? Retorna iterador para primeiro objeto no container v1.

(21)

Procura de v.begin() a v.end() os elementos do container que satisfa¸cam `a fun¸c˜ao predicado. Retorna iterador para primeira ocorrˆencia.

search n (v.begin(), v.end(), n, valor)

Procura seq¨uˆencia com n combina¸c˜oes de valor. Retorna iterador para primeiro elemento encontrado.

(22)

Ordena¸c˜ao

Os algoritmos a seguir s˜ao utilizados para ordenar um container.

sort (v.begin(), v.end());

Ordena o container v, de v.begin(), at´e v.end(). O m´etodo sort() n˜ao ´e dispo-n´ıvel para <list>; utilize o sort() do pr´oprio container <list>. A fun¸c˜ao sort() usa um algoritmo do tipo ”quicksort” e tem um custo computacional proporcional a O(N.log(N)). Veja listagens 1, 2, 3, ??.

Exemplo:

sort(v.begin(), v.end(), std::greater<int>); partial sort (in´ıcio, meio, fim);

(23)

Classifica¸c˜ao

Os algoritmos a seguir s˜ao utilizados para classificar um container.

unique copy (orig.begin(), orig.end(), back inserter(dest));

Obt´em uma c´opia de orig, sem elementos repetidos, e copia para dest.

unique (v.begin(), v.end());

Elimina os elementos duplicados, movendo-os para o fim do container. Observe que retorna iterador para ´ultimo elemento n˜ao duplicado. Nota: antes de chamar unique(), chame sort().

(24)

Apresenta-se no exemplo a seguir uma fun¸c˜ao gen´erica que realmente elimina os ele-mentos duplicados. Exemplo: template<typename C> void unique2(C& c) { // Ordena o container sort(c.begin(),c.end());

// Move para tr´as elementos duplicados

typename C::iterator p = unique(c.begin(),c.end()); // Deleta elementos duplicados

c.erase(p,c.end()); }

(25)

Transforma¸c˜ao

Os algoritmos a seguir s˜ao utilizados para aplicar transforma¸c˜oes aos elementos de um container. Os elementos transformados podem ser enviados para o pr´oprio container destino ou um iterador (como ostream_iterator).

generate (v.begin(), v.end(), fun¸c˜ao);

generate() ´e usada para gerar novos valores para o container. De v.begin() a v.end() executa a fun¸c˜ao que n˜ao recebe nenhum parˆametro mas retorna um novo elemento para o container. Veja listagem ??.

generate n (v.begin(), n, fun¸c˜ao);

De begin() a n executa a fun¸c˜ao que n˜ao recebe nada mas retorna um novo elemento para o container. Ou seja, preenche o container de v.begin() at´e v.begin()+n. Note que v.begin() ´e um iterador, logo, a fun¸c˜ao pode ser usada n vezes e a sa´ıda enviada para o iterador.

for each (v.begin(), v.end(), fun¸c˜ao);

(26)

a fun¸c˜ao, utilizada para aplicar uma dada fun¸c˜ao a cada um dos elementos do container. Observe que for_each() n˜ao modifica os elementos do container.

transform (orig.begin(), orig.end(), dest.begin(), fun¸c˜ao);

De orig.begin() a orig.end() executa a fun¸c˜ao e armazena o resultado em dest. Observe que a fun¸c˜ao deve receber um objeto do container (como const) e deve retornar um objeto transformado. Por exemplo, para somar o n´umero 75 a todos os elementos do container v. Veja outros exemplos nas listagens ??, ??. No exemplo a seguir o destino ´e o pr´oprio vetor v.

Exemplo:

transform(v.begin(), v.end(), d.begin(), rand);

transform(v.begin(), v.end(), v.begin(), bin2nd(plus<int>(),75); transform (orig1.begin(), orig1.end(), orig2.begin(), d.begin(), fun¸c˜ao);

De orig1.begin() a orig1.end() executa a fun¸c˜ao, usando os dados de orig1 e orig2, e armazena o resultado em d. Observe que a fun¸c˜ao deve receber um objeto do container orig1 (como const) e um objeto do container orig2 (como const) e deve retornar um objeto transformado.

(27)

partition (v.begin(), v.end(), Fun¸c˜aoPredicado);

Uma parti¸c˜ao ordena o container de acordo com a fun¸c˜ao predicado. V˜ao para o in´ıcio do container os objetos que satisfazem ao predicado (retornam true). Veja listagem ??.

Exemplo:

partition(in´ıcio,fim,predicado);

Dica: os algoritmos que mudam o container, como tranform(), retornam um iterador para destino.end().

(28)

Matem´aticos

Os algoritmos a seguir s˜ao utilizados para realizar opera¸c˜oes matem´aticas, como exem-plo obter o maior valor de um container. Veja o arquivo <numerics>.

max (a, b);

Retorna a, se a > b, ou b, se b > a. Retorna o maior valor.

min (a, b);

Retorna a, se a < b, ou b, se b < a. Retorna o menor valor.

max element (v.begin(), v.end());

Retorna o maior elemento.

min element (v.begin(), v.end());

Retorna o menor elemento.

count (v.begin(), v.end(),valor);

Determina o n´umero de elementos igual a valor. Exemplo:

(29)

int total = count(v.begin(),v.end(),0); count if (v.begin(), v.end(), Fun¸c˜aoPredicado);

Determina o n´umero de elementos que obedecem `a fun¸c˜ao predicado.

accumulate (v.begin(), v.end(), valorInicial);

Retorna a soma de todos os elementos. Observe que podemos passar o valor inicial do somat´orio. Veja listagem ??.

Exemplo:

(30)

Opera¸c˜oes matem´aticas com conjuntos

set difference (a, a+size, b, b+size, diferen¸ca);

Todos os valores do vetor a que n˜ao estiverem no vetor b ser˜ao copiados para o vetor diferen¸ca. Veja listagem ??.

Exemplo:

int diferenca[size];

set_difference ( a, a + size , b , b + size , diferenca ); set intersection (a, a+size, b, b+size, interse¸c˜ao);

Todos os valores do vetor a que estiverem no vetor b ser˜ao copiados para o vetor interse¸c˜ao. Veja listagem ??.

Exemplo:

int intersecao[size];

set_intersection (a,a+size,b,b+size,intersecao); set union (a, a+size, b, b+size, uni˜ao);

(31)

Exemplo:

int uniao[size];

set_union (a,a+size,b,b+size,uniao);

set symmetric difference (a, a+size, b, b+size, sym dif );

Determina o conjunto de valores de a que n˜ao est˜ao em b e os valores de b que n˜ao est˜ao em a, e copia para o vetor sym_dif(). Veja listagem ??.

Exemplo:

int sym_dif[size];

(32)

Ordena¸c˜ao de pilhas - heapsort

Um heap armazena os elementos de uma maneira semi-ordenada, de forma que a procura pelo maior elemento tenha um custo constante. A remo¸c˜ao do maior elemento e adi¸c˜ao de novos elementos tem tempo de processamento logar´ıtmico.

make heap (v.begin(), v.end());

Marca a pilha. O primeiro elemento de v ´e o maior.

sort heap (v.begin(), v.end());

Ordena toda a pilha.

push heap (v.begin(), v.end());

Adiciona elemento no container.

pop heap (v.begin(), v.end());

(33)

Exemplos de uso das fun¸c˜oes gen´ericas

Veremos a seguir exemplos de uso das fun¸c˜oes gen´ericas.

(34)

Listing 1: Usando sort(), find(), find_if(), fill(). 1 # i n c l u d e < ios tre am > 2 # i n c l u d e < fstream > 3 # i n c l u d e < iomanip > 4 # i n c l u d e < string > 5 # i n c l u d e < vector > // C l a s s e de v e t o r e s 6 # i n c l u d e < a l g o r i t h m > // A l g o r i t m o s g e n ´e r i c o s 7 u s i n g n a m e s p a c e std ; // D e f i n e o uso do e s p a ¸c o de n o m e s std 8 9 // D e c l a r a ¸c ~a o de s o b r e c a r g a de << pa ra o s t r e a m e v e c t o r 10 o s t r e a m & o p e r a t o r < < ( o s t r e a m & os , c o n s t v e c t o r < int >& v ) 11 {

12 for ( int i = 0; i < v . s ize () ; i ++)

13 os < < " v [" << set w (3) < < i < < "]= " << se tw (5) < < v [ i ] < < ’ ’; 14 r e t u r n os ;

15 } 16

17 // D e c l a r a ¸c ~a o de s o b r e c a r g a de << pa ra o f s t r e a m e v e c t o r 18 o f s t r e a m & ope rat or < < ( o f s t r e a m & os , c o n s t v e c t o r < int >& v ) 19 {

20 for ( int i = 0; i < v . s ize () ; i ++) 21 os < < set w (10 ) << v [ i ] << en dl ; 22 r e t u r n os ;

(35)

24 25 // D e c l a r a ¸c ~a o e d e f i n i ¸c ~a o de f u n ¸c ~a o p r e d i c a d o 26 // R e c e b e um o b j e t o do t ipo a r m a z e n a d o no c o n t a i n e r 27 // r e t o r n a v e r d a d e i r o ou f a l s o . 28 bo ol m a i o r Q u e 5 ( int v a l o r ) 29 { 30 r e t u r n v a l o r > 5; 31 } 32 33 int ma in () 34 { 35 s t r i n g l i n h a =" - - - -\ n "; 36 vector < int > v ; 37 int da ta ; 38 do 39 {

40 co ut << "\ n E n t r e com o d ado (" << set w (3) < < v . s ize () << ") :"; 41 cin >> da ta ; 42 cin . get () ; 43 if ( cin . go od () ) 44 v . p u s h _ b a c k ( d ata ) ; 45 } w h i l e ( cin . g ood () ) ; 46 cin . get () ;

47 cin . c l e a r () ; // R e s e t a o b j e t o cin par a e s t a d o ok 48 {

(36)

49 o f s t r e a m f out (" v e c t o r . dat ") ; 50 if (! f out ) 51 r e t u r n 0; 52 fo ut << v << e ndl ; 53 fo ut . c l o s e () ; 54 } 55 co ut << "\ n " < < l i n h a << v << en dl ; 56 57 int n u m e r o ; 58 co ut << "\ n E n t r e com o n ´u m e r o a ser l o c a l i z a d o :"; 59 cin > > n u m e r o ; 60 cin . get () ; 61 62 // P o n t e i r o pa ra a p o s i ¸c ~a o l o c a l i z a d a

63 v e c t o r < int >:: i t e r a t o r it = f ind ( v . b e g i n () , v . end () , n u m e r o ) ;

64 co ut < < "\ n N ´u m e r o l o c a l i z a d o na p o s i ¸c ~a o :" < < ( it - v . b e g i n () ) << end l ; 65 66 // L o c a l i z a p r i m e i r o e l e m e n t o que s a t i s f a z a c o n d i ¸c ~a o 67 // d ada p ela f u n ¸c ~a o m a i o r Q u e 5 68 it = f i n d _ i f ( v . b e g i n () , v . end () , m a i o r Q u e 5 ) ; 69 co ut < < "\ n N ´u m e r o m a i o r que 5 l o c a l i z a d o na p o s i ¸c ~a o :" 70 << ( it - v . b e g i n () ) << end l ;; 71 72 // O r d e n a o c o n t a i n e r 73 so rt ( v . b e g i n () , v . end () ) ;

(37)

74 co ut < < "\ n V e t o r a p´os o r d e n a ¸c ~a o com so rt ( v . b e g i n () , v . end () ) \ n " 75 << l i n h a << v << en dl ; 76 77 // P r e e n c h e com o v a l o r 45 78 fi ll ( v . b e g i n () , v . end () , 45) ; 79 co ut < < "\ n V e t o r a p´os f ill ( v . b e g i n () , v . end () , 45) ;\ n " 80 << l i n h a << v << en dl ; 81 82 // R e t o r n a d i m e n s ~a o e c a p a c i d a d e 83 co ut < < " v . siz e () =" < < v . siz e () 84 << "\ nv . c a p a c i t y () =" << v . c a p a c i t y () << e ndl ; 85 86 // R e d i m e n s i o n a o c o n t a i n e r 87 v . r e s i z e (10 ) ; 88 co ut < < "\ n V e t o r a p´os r e s i z e (10 ) :\ n " 89 << l i n h a << v 90 << "\ nv . s ize () =" << v . si ze () 91 << "\ nv . c a p a c i t y () =" << v . c a p a c i t y () << "\ n " 92 << l i n h a << en dl ; 93 cin . get () ; 94 r e t u r n 0; 95 }

(38)

[ b u e n o @ l d s c 0 5 Parte - III ] $ ./ a . out E n t r e com o d ado ( 0) :45 E n t r e com o d ado ( 1) :15 E n t r e com o d ado ( 2) :91 E n t r e com o d ado ( 3) :13 E n t r e com o d ado ( 4) :26 E n t r e com o d ado ( 5) : -v [ 0]= 45 v [ 1]= 15 v [ 2]= 91 v [ 3]= 13 v [ 4]= 26 E n t r e com o n ´u m e r o a ser l o c a l i z a d o :91 N ´u m e r o l o c a l i z a d o na p o s i ¸c ~a o :2 N ´u m e r o m a i o r que 5 l o c a l i z a d o na p o s i ¸c ~a o :0

V e t o r ap ´os o r d e n a ¸c ~a o com sor t ( v . b e g i n () , v . end () )

-v [ 0]= 13 v [ 1]= 15 v [ 2]= 26 v [ 3]= 45 v [ 4]= 91 V e t o r ap ´os fi ll ( v . b e g i n () , v . end () , 45) ; -v [ 0]= 45 v [ 1]= 45 v [ 2]= 45 v [ 3]= 45 v [ 4]= 45 v . s ize () =5 v . c a p a c i t y () =8 V e t o r ap ´os r e s i z e ( 10) :

(39)

-v [ 0]= 45 v [ 1]= 45 v [ 2]= 45 v [ 3]= 45 v [ 4]= 45 v [ 5]= 0 v [ 6]= 0 v [ 7]= 0 v [ 8]= 0 v [ 9]= 0 v . s ize () =10

v . c a p a c i t y () =10

-No exemplo da listagem 2 mostramos o uso de sort() e copy(). O programa ordena as linhas de texto digitadas pelo usu´ario ou as linhas de um arquivo de disco usando a fun¸c˜ao global OrdenaLinhasArquivo().

(40)

Listing 2: Usando sort() e copy() para ordenar linhas de texto. # i n c l u d e < fstream > # i n c l u d e < ios tre am > # i n c l u d e < string > # i n c l u d e < vector > # i n c l u d e < ite rat or > # i n c l u d e < a l g o r i t h m >

vo id O r d e n a L i n h a s A r q u i v o ( std :: i s t r e a m & in , std :: o s t r e a m & out ) { std :: s t r i n g l i n h a ; std :: vector < std :: string > v ; w h i l e ( std :: g e t l i n e ( in , l i n h a ) ) v . p u s h _ b a c k ( l i n h a ) ; std :: s ort ( v . b e g i n () , v . end () ) ; std :: c out < < std :: end l ;

std :: c opy ( v . b e g i n () , v . end () , std :: o s t r e a m _ i t e r a t o r < std :: string >( out ,"\ n " ) ) ; in . c l e a r () ; r e t u r n ; } int ma in () { u s i n g n a m e s p a c e std ;

(41)

// O r d e n a l i n h a s d i g i t a d a s

co ut << " D i g i t e d i v e r s a s l i n h a s de texto , e d e p o i s p r e s s i o n e ctr l + d :\ n "; O r d e n a L i n h a s A r q u i v o ( cin , cou t ) ;

co ut << "\ n E n t r e com o n ome do a r q u i v o a ser o r d e n a d o :" < < en dl ; s t r i n g n o m e A r q u i v o ; g e t l i n e ( cin , n o m e A r q u i v o ) ; i f s t r e a m fin ( n o m e A r q u i v o . c _ s t r () ) ; o f s t r e a m f out ((" O r d e n a d o " + n o m e A r q u i v o ) . c _ s t r () ) ; O r d e n a L i n h a s A r q u i v o ( fin , fo ut ) ; r e t u r n 0; }

(42)

[ b u e n o @ l d s c 0 5 Parte - III ] $ ./ a . out

D i g i t e d i v e r s a s l i n h a s de texto , e d e p o i s p r e s s i o n e ct rl + d : T e s t a n d o a o r d e m

em que o t e x t o vai sai r se r´a que vai dar

c e r t o ?

T e s t a n d o a o r d e m c e r t o ?

em que o t e x t o vai sai r se r´a que vai dar

E n t r e com o n ome do a r q u i v o a ser o r d e n a d o : E n t r a d a . dat

No exemplo da listagem 3 usamos copy(), para copiar dados de um arquivo de disco para um vetor. A seguir ordenamos o vetor e o enviamos para tela.

(43)

Listing 3: Usando copy() para copiar dados de um arquivo de disco para um <vector>. 1 # i n c l u d e < a l g o r i t h m > 2 # i n c l u d e < fstream > 3 # i n c l u d e < ios tre am > 4 # i n c l u d e < ite rat or > 5 # i n c l u d e < vector > 6 7 int ma in () 8 { 9 u s i n g n a m e s p a c e std ; 10 i f s t r e a m in (" d a d o s . dat ") ; 11 vector < int > v ; 12 co py ( i s t r e a m _ i t e r a t o r < int >( in ) , i s t r e a m _ i t e r a t o r < int >() , b a c k _ i n s e r t e r ( v ) ) ; 13 so rt ( v . b e g i n () , v . end () ) ;

14 co py ( v . b e g i n () , v . end () , o s t r e a m _ i t e r a t o r < int >( cout , "\ n ") ) ; 15 r e t u r n 0;

(44)

[ b u e n o @ l d s c 0 5 Parte - III ] $ ./ a . out 15 25 35 48 65 75 98

Na listagem 4 apresentamos o uso de fun¸c˜oes gen´ericas como nth_element() e find() para obter a mediana de um grupo de dados. A listagem ´e documentada.

Note que estamos acostumados a usar container<tipo>::value_type para obter a informa¸c˜ao do tipo de valor armazenado no container. Mas na fun¸c˜ao Mediana() n˜ao temos o container. Temos apenas os iteradores. Ou seja, precisamos obter o container a partir dos iteradores. Este ´e o motivo para criarmos o apelido typedef typename std::iterator_traits<iterador>::value_type value_type;

(45)

Listing 4: Usando <vector> com algoritmos gen´ericos: C´alculo da mediana. 1 # i n c l u d e < ios tre am > 2 # i n c l u d e < a l g o r i t h m > 3 # i n c l u d e < f u n c t i o n a l > 4 # i n c l u d e < ite rat or > 5 # i n c l u d e < vector > 6

7 te mpl ate < t y p e n a m e i ter ado r , t y p e n a m e o p e r a d o r C o m p a r a c a o >

8 i t e r a d o r M e d i a n a ( i t e r a d o r first , i t e r a d o r last , o p e r a d o r C o m p a r a c a o o p C o m p ) 9 {

10 // C ria a p e l i d o

11 t y p e d e f t y p e n a m e std :: i t e r a t o r _ t r a i t s < ite rad or >:: v a l u e _ t y p e v a l u e _ t y p e ; 12 std :: vector < v a l u e _ t y p e > tmp ( first , last ) ;

13 14 // D e t e r m i n a p o s i ¸c ~a o m ´e d i a 15 t y p e n a m e std :: vector < v a l u e _ t y p e >:: s i z e _ t y p e p o s i c a o = tmp . s ize () / 2; 16 17 // L o c a l i z a no c o n t a i n e r r e c e b i d o o v a l o r da m e d i a n a 18 std :: n t h _ e l e m e n t ( tmp . b e g i n () , tmp . b e g i n () + posicao , tmp . end () , o p C o m p ) ; 19 r e t u r n std :: fi nd ( first , last , tmp [ p o s i c a o ]) ; 20 } 21 22 int ma in () 23 {

(46)

24 // C ria v e t o r e a r m a z e n a d a d o s 25 std :: vector < int > v ; 26 v . p u s h _ b a c k ( 1 2 4 3 ) ; v . p u s h _ b a c k ( 2 3 6 7 ) ; v . p u s h _ b a c k ( 7 2 8 4 ) ; 27 v . p u s h _ b a c k ( 7 3 8 3 ) ; v . p u s h _ b a c k ( 3 9 2 8 ) ; v . p u s h _ b a c k ( 6 0 3 2 ) ; 28 v . p u s h _ b a c k ( 8 7 3 4 ) ; v . p u s h _ b a c k ( 7 3 8 2 ) ; v . p u s h _ b a c k ( 9 2 8 4 ) ; 29 30 // D e t e r m i n a a m e d i a n a e m o s t r a na t ela

31 int m e d i a n a = * M e d i a n a ( v . b e g i n () , v . end () , std :: less < int >() ) ; 32 std :: c out < < m e d i a n a << std :: en dl ;

33 r e t u r n 0; 34 }

(47)

[ b u e n o @ l d s c 0 5 Parte - III ] $ ./ a . out 72 84

No exemplo da listagem 5 criamos uma classe TCSeries que recebe dois parˆametros, o n´umero de elementos a serem criados e o incremento. Note que o operador() ´e sobre-carregado, e retorna o pr´oximo valor da s´erie. Ou seja, o objeto TCSeries se comporta como uma fun¸c˜ao que ´e chamada n vezes.

Um objeto do tipo TCSeries ´e criado na chamada ao m´etodo generat_n(), passa-mos para o construtor o valorInicial e o incremento. O m´etodo generat_n(), executa nRepeti¸c˜oes (chamadas) ao operator() do objeto criado, e envia para tela os valores retornados.

(48)

Listing 5: Usando generator_n() para gerar uma s´erie de dados. 1 # i n c l u d e < a l g o r i t h m > 2 # i n c l u d e < ios tre am > 3 # i n c l u d e < ite rat or > 4 5 t e m p l a t e < t y p e n a m e T > 6 c l a s s T C S e r i e s 7 { 8 p u b l i c : 9 // C o n s t r u t o r 10 T C S e r i e s ( c o n s t T & n =0 , c o n s t T & i =1) : p r o x i m o ( n - i ) , i n c r e m e n t o ( i ) {} 11 // O p e r a d o r s o b r e c a r r e g a d o 12 T o p e r a t o r () () 13 { r e t u r n p r o x i m o += i n c r e m e n t o ; } 14 p r i v a t e : 15 T p r o x i m o ; 16 T i n c r e m e n t o ; 17 }; 18 19 int ma in () 20 { 21 int v a l o r I n i c i a l , i n c r e m e n t o , n R e p e t i c o e s ; 22 std :: c out < < " E n t r e com o v a l o r i n i c i a l :"; 23 std :: cin >> v a l o r I n i c i a l ; std :: cin . get () ;

(49)

24 std :: c out < < " E n t r e com o v a l o r do i n c r e m e n t o :"; 25 std :: cin >> i n c r e m e n t o ; std :: cin . get () ;

26 std :: c out < < " E n t r e com o n ´u m e r o de e l e m e n t o s :"; 27 std :: cin >> n R e p e t i c o e s ; std :: cin . get () ;

28 std :: g e n e r a t e _ n (

29 std :: o s t r e a m _ i t e r a t o r < int >( std :: cout ,"\ n ") , // D e s t i n o

30 n R e p e t i c o e s , // N ´u m e r o r e p e t i ¸c ~o e s 31 TC Ser ies < int >( v a l o r I n i c i a l , i n c r e m e n t o ) // O b j e t o f u n ¸c ~a o 32 ) ;

(50)

E n t r e com o v a l o r i n i c i a l :12 3 E n t r e com o v a l o r do i n c r e m e n t o :3 E n t r e com o n ´u m e r o de e l e m e n t o s :6 123 126 129 132 135 138

(51)

Senten¸cas para c´odigo gen´erico

ê Dˆe uma olhada na Internet e procure por STL. Vocˆe encontrar´a muitos sites com exemplos interessantes.

ê next_permutation() e prev_permutation() permutam os elementos do container. Veja listagem ??.

ê No exemplo abaixo, o vetor v1 ´e adicionado ao fim de v2. A fun¸c˜ao back_inserter()

chama v2.push_back() para cada elemento de v1.

copy ( v1.begin(), v1.end(), back_inserter(v2) );

ê No exemplo abaixo, o deque d1 ´e adicionado no fim de d2, front_insert() chama a fun¸c˜ao push_front() para cada elemento de d2.

copy ( d1.begin(), d1.end(), front_inserter(d2) );

ê Se um algoritmo qualquer tem uma vers˜ao gen´erica e uma c´opia espec´ıfica para um determinado container (´e um m´etodo do container), ent˜ao a vers˜ao do container ´e mais r´apida.

(52)

ê A classe <string> pode ser usada como um vetor. Veja os exemplos.

Exemplo:

for(int i = 0; i < s.size(); i++) cout << s[i] << endl;

for(string::const_iterator it = s.begin(); it != s.end(); it++) cout << *it << endl;

ê Vocˆe encontra informa¸c˜oes e outros exemplos de uso das fun¸c˜oes da STL nas refe-rˆencias [?], e sobre programa¸c˜ao gen´erica, em [?].

(53)

Resumo do cap´ıtulo

Neste cap´ıtulo aprendemos a utilizar um conjunto de fun¸c˜oes que s˜ao utilizadas na programa¸c˜ao gen´erica e que s˜ao fornecidas com a STL. Vimos uma introdu¸c˜ao `a progra-ma¸c˜ao gen´erica, e a seguir apresentamos a classifica¸c˜ao das fun¸c˜oes gen´ericas (se modifica ou n˜ao o container, tipo de iterador utilizado, e tipos de opera¸c˜oes suportadas).

Vimos que as fun¸c˜oes gen´ericas s˜ao classificadas da seguinte forma: preenchimento, compara¸c˜ao, remo¸c˜ao, trocas, misturar/mesclar/inverter, pesquisa, ordena¸c˜ao, classifica-¸c˜ao, transforma¸c˜ao, matem´aticos, opera¸c˜oes com conjuntos, ordena¸cao de pilhas.

No final do cap´ıtulo vimos diversos exemplos.

(54)

Exerc´ıcios

1. Quais as fun¸c˜oes gen´ericas que n˜ao mudam o container?

2. Modifique a listagem 1. Acrescente o uso de: find first of(); adjacent find(); bi-nary search(); lower bound(); upper bound(); equal range(); search(); search n();.

3. Modifique a listagem 2, de tal forma que o usu´ario possa definir o nome do arquivo

de disco e a ordem de ordena¸c˜ao (ascendente/descendente).

4. S´o para sentir a diferen¸ca, implemente a listagem 3 sem usar a STL.

5. Modifique a listagem 4. Adicione o c´alculo da m´edio e desvio padr˜ao.

6. Modifique a listagem 5. Crie a possibilidade de se criar s´eries logar´ıtmicas.

7. Monte um exemplo que leia de um InputIterator e escreva para um OutputIterator.

8. Quais os algoritmos gen´ericos utilizados para opera¸c˜oes de transforma¸c˜ao?

9. Monte um exemplo que utilize as fun¸c˜oes de preenchimento (se¸c˜ao ) e de remo¸c˜ao

(55)

10. Monte um exemplo que utilize as fun¸c˜oes de compara¸c˜ao (se¸c˜ao ) e de trocas (se¸c˜ao ).

11. Monte um exemplo que fa¸ca pesquisas em um vetor (se¸c˜ao ) e localize n´umeros

primos.

12. Monte um exemplo que aplique algoritmos de transforma¸c˜ao em polinˆomios (se¸c˜ao

).

13. Implemente e teste a fun¸c˜ao unique2() (veja se¸c˜ao ).

14. Vocˆe deve comentar o c´odigo abaixo, e a seguir dizer o que faz o m´etodo M?

Exemplo:

#include <fstream> #include <iterator>

void CNome::M(string arqA, string arqB) {

(56)

std::ofstream fout( arqB.c_str() );

std::copy(std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>(),

std::ostreambuf_iterator<char>(fout)); }

15. Procure na Internet informa¸c˜oes sobre os algoritmos stable_partition e

sta-ble_sort.

16. Procure na Internet informa¸c˜oes sobre os algoritmos

Referências

Documentos relacionados

A condição de nitretação N350 teve um desempenho comparável com o aço UNS S32750 no estado de fornecimento durante o ensaio em estágios com formador de fresta, no que respeita a

(1998), utilizando o diferimento e administração da carga animal, sobre o crescimento de terneiros e novilhos sobre o campo natural de basalto no período hibernal

Este Trabalho de Conclusão de Curso foi julgado adequado para ob- tenção do Título de Licenciada em Matemática, e aprovado em sua forma final pelo Curso de Licenciatura em Matemática

Artibeus fimbriatus, Família Phyllostomidae, espécie de morcego frugívoro mais capturada no sítio Reserva Natural do Ribeirão Grande, município de Juquitiba, SP.. Espécies de

Fairclough (2001) aponta para a dialética, considerando o discurso moldado pela estrutura social e constitutiva dessa estrutura, contribuindo para a constituição

Assim não temos informação alguma do equilíbrio dos subsistemas, não obstante este problema pode ser solucionado tendo em conta que a energia e o volume total do sistema são

O referencial teórico situa-se na discussão das bases conceituais de formação, que se referem a um conjunto de ideologias, bem como as visões de ensino e aprendizagem adotadas

O fundador deve tornar-se um membro do conselho administrativo e abrir mão das operações ou tornar-se o diretor geral da organização e abrir mão das responsabilidades