ELC1096 - Preparação para a Maratona de Programação
Primeiro Semestre de 2012
Professora: Juliana Kaizer Vizzotto
Templates em C++
- Imagine que queremos criar uma biblioteca em C++ para criar e manipular pilhas (
`stacks`
) de inteiros. Poderíamos fazer isso simplesmente como segue:class stack{ public: Stack(int size){ stack = new int[size]; topo=0; ... } ... int push(int in){ stack[topo++] = i; ... } ... private: int topo; int *stack; };
- E agora se precisarmos de um outra pilha de
`double`
ao invés de`int`
? - Ok! Podemos alterar o código acima para
`double`
! - Mas se quisermos um pilha genérica???
- Templates resolvem esse problema!!
template<class Type> class Stack { public: Stack(int size){ stack = new Type[size]; topo = 0; ... } ... void push(const Type &t){ stack[topo++]=t; ... } private: int topo; Type *stack; };
- No código acima usou-se a palavra-chave template, seguida do nome genérico ente
` < > `
. Neste caso,` Type `
. Se quiséssemos usar 2 tipos genéricos, ficaria` template< class Foo, class Bar> `
. - Agora, como se cria uma pilha de inteiros e de doubles?
int main(){ Stack<int> pilha1(10); Stack<double> pilha2(10); pilha1.push(2); pilha2.push(3.14); cout << pilha1.top() << "\n"; pilha2.pop(); return 0; }
Standard Template Library (STL) em C++
- A linguagem C++ fornece uma biblioteca de estrutura de dados genérica usando Templates pronta para o usuário/programador. Vamos revisar alguns das estruturas de dados fornecidas na biblioteca.
- Pilha A pilha é uma das estruturas de dados mais simples: ela representa um container de dados onde se coloca qualquer quantidade de valores e sempre se retira o último valor que foi colocado (o mais recente). A estratégia é chamada LIFO (Last-In,First-Out).
- Exemplo1: Receba como entrada um número N seguido de N inteiros. Imprima esses inteiros na ordem inversa que eles foram informados na entrada.
#include <stack> #include <iostream> using namespace std; int main(){ long N, num; stack<long> s; cin >> N; while (N>0){ cin >>num; s.push(num); N--; } while(!s.empty()){ cout << s.top() << endl; s.pop(); } }
- Dicas: Releia o enunciado da questão. Depois de ter certeza que entendeu o enunciado, marque 10 minutos. Durante esse tempo, tente elaborar um algoritmo para resolver a questão (não codifique nada, apenas idealize um algoritmo). Só continue lendo depois de fazê-lo.
- [Exercício: Parentheses Balance, questão 673 da Uva http://online-judge.uva.es/p/v6/673.html]
Filas
- Filas são containers de dados que seguem o regime LILO (Las-In, Last-Out), ou seja, o próximo valor removido da fila é aquele que está armazenado a mais tempo.
- [Exemplo The Dole Queue, questão 133 do UVa http://online-judge.uva.es/p/v1/133.html].
- Dada uma fila circular com N elementos numerados de 1 a N e dois inteiros
K e M, o objetivo é simular o sgeuinte algoritmo.
UM juiz inicia no começo da fila e caminha K posições na ordem crescente
dos números até chegar ao K-ésimo elemento. Outro juiz inicia no final da
fila e caminha M posições na ordem descresnte dos números até chegar ao
M-ésimo elemento. O K-ésimo e o M-ésimo elementos devem ser removidos da fila.
O procedimento continua até a fila esvaziar.
#include <cstdio> #include <queue> #include <iostream> using namespace std; queue<int> removeX(queue<int> q, int x){ queue<int> ret; while (!q.empty()){ if (q.front() !=x) ret.push(q.front()); q.pop(); } return ret; } int main(){ int N, k, m, i, d1, d2; while(true){ scanf("%d,%d,%d",&N,&k,&m); if (!N&&!k&&!m) return 0; queue<int> qk,qm; for (i=1;i<=N;i++) qk.push(i); for (i=1;i>=N;i--) qm.push(i); while (!qk.empty()){ for (i=0;i<k;i++){ d1 = qk.front(); qk.pop(); if (i !=k-1) qk.push(d1); } for (i=0; i<m;i++){ d2 = qm.front(); qm.pop(); if (i!=m-1) qm.push(d2); } if (d1==d2){ printf("%3d",d1); if (!qk.empty()) putchar(','); } else { qk = removeX(qk,d2); qm = removeX(qm,d1); printf("%3d%3d",d1,d2); if (!qk.empty()) putchar(','); } } } }
- A função
`removeX`
serve para remover todas as ocorrências de um valor x de uma fila q, retornando a fila resultante. Isso é útil para remover da fila o K-ésimo ou o M-ésimo elemento da fila. - Para esta questão são usadas as variáveis N,k e m lidas da entrada, assim como a variável contadora i, e as variáveis d1 e d2 que indicam respectivamente o k-ésimo e o m-ésimo elemento da fila. O laço principal lê os três inteiros da entrada e termina quando os três foram informados iguais a zero.
- A solução faz uso de duas filas de inteiros, chamadas qk e qm. Elas são iniciadas respectivamente com os números de 1 a N em ordem crescente e decrescente. Após determinamos o k-ésimo elemento da fila, que é armazenado na variável d1. Depois o m-ésimo elemento da fila é determinado, que é armazenado na variável d2. Tanto o elemento d1 quanto o elemento d2 não são devolvidos de volta para as respectivas filas. Logo a saída é exibida. Se o k-ésimo elemento e o m-ésimo elemento forem iguais esse elemento é apenas exibido sem a necessidade de removê-los (já que ele não foi devolvido para a mesma). Caso eles sejam diferentes, d2 é removido da fila qk e d1 é removido da fila qm. Depois disso os elementos d1 e d2 são impressos.
- [Exercícios Australian Voting, questão 10142 do UVa http://online-judge.uva.es/p/v101/10142.html]
- O objetivo é indicar qual(is) o(s) vencedor(es) de uma eleição em que participaram n candidatos e m eleitores. Cada eleitor vota em n candidatos na ordem de sua preferência. Se um candidato obtiver mais do que a metade dos votos dos eleitores, ele é eleito. Caso contrário, os votos dos candidatos empatados em último lugar devem ser ignorados e o voto daquele eleitor específico deve passar para a próxima preferência. O procedimento prossegue até que um candidato tem mais que 50% dos votos ou até que haja um empate entre todos os candidatos ainda não eliminados (caso em que todos eles devem ser impressos como vencedores).
Vector
- Exemplo:
#include <iostream> #include <vector> #include <string> //#include <stdio.h> using namespace std; int main(){ vector<string> VS; string frase; int N; cin >> N; getline(cin,frase); //limpa o buffer while (N > 0){ cout << "Digite uma frase: "; getline(cin,frase); VS.push_back(frase); N--; } int i; cout << VS.size() << endl; for (i=0;i< VS.size();i++){ cout << VS[i] << endl; } }