IV Escola de Inverno - rcosta62br.unifei.edu.brrcosta62br.unifei.edu.br/OBI/aula_06.pdf · Grafos...

Post on 05-Oct-2020

0 views 0 download

Transcript of IV Escola de Inverno - rcosta62br.unifei.edu.brrcosta62br.unifei.edu.br/OBI/aula_06.pdf · Grafos...

IV Escola de InvernoMaratona de Programação UNIFEI 2016

Intermediário I

C++ STL - Standard Template Library

C++ STLA STL (Standard Template Library) é uma biblioteca de algoritmos e estruturas de dados genéricas, integrada à biblioteca padrão de C++ através de mecanismos de templates. Criada por Alexander Stepanov e Meng Lee (Hewlett-Packard), adicionada ao C++ em 1994.

Templates são implementações generalizadas para diferentes estruturas de dados. Sobre essa ferramenta, o STL nos fornece containers para armazenar e realizar operações numa coleção de objetos.

C++ STL - ContainersOs containers são indispensáveis na programação competitiva. Neste curso veremos os seguintes containers:

• Containers sequenciais: vector, deque e list

• Adaptadores de containers: stack, queue e priority_queue

• Containers associativos classificados: set e map

Container: vectorRepresentam o mesmo tipo de estrutura de um array em C, e podem ser manipulados com a mesma eficiência, mas mudam seu tamanho dinamicamente e automaticamente.

Neles, os elementos são armazenados de forma contígua e podem ser acessados aleatoriamente através do operador [].

Sua utilização é importante especialmente quando não conhecemos o tamanho do vetor com antecedência.

São bastante eficientes no acesso aos elementos e na inserção e remoção de elementos no fim (push_back e pop_back). Para operações de inserção e remoção de elementos em outros lugares, são piores que outras estruturas como list e deque.

Container: vectorPrincipais métodos:

Acesso a elemento:

operador [] front()back()

Iteradores: begin()end()

Capacidade: size()empty()

Modificadores: push_back pop_back()inserteraseclear()resize

Referência: http://www.cplusplus.com/reference/vector/vector/

Container: vectorIteradoresIteradores são ponteiros que contém o endereço de memória de um elemento do container.Nos containers sequenciais, os elementos são armazenados contiguamente.

Para os principais iteradores de vector:A.begin() - Ponteiro para o primeiro elemento de AA.end() - Ponteiro para um elemento nulo após o último elemento de AA.begin()+i - Ponteiro para o i-ésimo elemento de A*(A.begin()+i) - Valor do i-ésimo elemento de A

Ponteiros: São variáveis que armazenam o endereço de memória de uma variável. Para

acessar o valor da variável deve-se utilizar um * antes da variável.

Exercício:1) Crie um vetor vazio e insira valores aleatórios

de 0 a 9.

Para gerar um número aleatório de 0 a 9:

int x = rand() % 10;2) Para cada elemento do vetor, começando do

primeiro elemento: ● se for par, remova esse elemento;● se for ímpar, multiplique pelo tamanho

do vetor.1) Encontre a posição dos valores máximo e

mínimo do vetor resultante.2) Crie um novo vetor a partir do anterior com

todos os valores entre o máximo e o mínimo, inclusive.

3) Imprima o vetor resultante em ordem crescente.

Container: vector

Container: listSão listas duplamente encadeadas, que permitem operações de inserção e remoção de itens em tempo constante em qualquer posição da sequência e iteração nos dois sentidos.

Armazenam elementos de maneira não contígua, mantendo a ordem internamente através de uma associação: cada elemento possui uma ligação com seu antecessor e sucessor na lista. Não é possível utilizar o operador [].

Em comparação com deque e vector, a list se sai melhor nas operações de inserção, remoção e movimentação de elementos em qualquer posição do container para a qual um iterador já tenha sido obtido, e, portanto, se destaca também em algoritmos que fazem uso intensivo destas operações, como algoritmos de ordenação.

Container: listPrincipais métodos:

Acesso a elemento:

front()back()

Iteradores: begin()end()

Capacidade: size()empty()

Modificadores: push_backpush_frontpop_back()pop_front()inserteraseclear()resize

Referência: http://www.cplusplus.com/reference/list/list/

Container: listIteradoresNa list, os elementos não são armazenados contiguamente. Em vez disso, os iteradores são bidirecionais, onde um iterador possui uma ligação com o próximo elemento e o elemento anterior.

Iteradores bidirecionais só podem ser incrementados (++) ou decrementados (--). Para se percorrer uma lista, é necessário começar do primeiro (último) elemento e incrementar (decrementar) o ponteiro até a posição desejada.

list<int>::iterator it = A.begin(); - Iterador aponta para o primeiro elemento de Ait++; it++; it--; - it aponta para o 2º elemento de A*it - Valor do 2º elemento de Ait += 2; it = it - 1; - Não permitido. it não suporta essas operações.

Exercício:1) Crie uma lista vazia e insira valores aleatórios de 0 a 9.2) Imprima o vetor resultante em ordem crescente.

Para gerar um número aleatório de 0 a 9: int x = rand() % 10;

Para ordenar uma list: A.sort();

Container: list

Adaptador de Container: queuequeue é um adaptador de container projetado especificamente para operar em um contexto FIFO (first in, first out), onde elementos são sempre inseridos no fim e removidos apenas do início do container.

Exatamente como numa fila da vida real, o primeiro a entrar é o primeiro a sair.

Principais métodos:empty()size()front()back()pushpop()

Referência completa: http://www.cplusplus.com/reference/queue/queue/

Container: dequeDeque (acrônimo de “double-ended queue”) é, como o próprio nome nos indica, uma fila com duas extremidades. São um tipo de container de tamanho dinâmico que pode ser expandido ou diminuído nas duas extremidades (front e back).

Também permitem o acesso direto a todos os seus elementos (operador []).

Apresentam funcionalidade similar ao vector, mas com inserção e remoção eficiente de elementos também no começo da sequência, não somente no fim. Porém, os elementos não são necessariamente armazenados de forma contígua.

Principais métodos:

Acesso a elemento:

operador [] front()back()

Iteradores: begin()end()

Capacidade: size()empty()

Modificadores: push_backpush_frontpop_back()pop_front()inserteraseclear()

Referência completa: http://www.cplusplus.com/reference/deque/deque/

Adaptador de container: stackstack (pilha) é um adaptador de container projetado especificamente para operar em um contexto LIFO (last in, first out), onde elementos são SEMPRE inseridos e removidos apenas do final (topo) do container.Exatamente como uma pilha da vida real: o último a entrar é o primeiro a sair.

Principais métodos:empty()size()top()pushpop()

Referência completa: http://www.cplusplus.com/reference/stack/stack/

Exemplo: URI 1110 - Jogando Cartas Foraqueue<int> deck;vector<int> discarded;

discarded.clear();deck.clear();

int n=0;while(n<N) //montando o baralho deck.push_front(n++);

while(deck.size()>1){ //descarta uma carta discarded.push_back(deck.front()); deck.pop(); //tira uma carta do topo e coloca no fundo deck.push(deck.front()); deck.pop();}

Exercício: UVA 11034 - Ferry Loading IVhttps://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=1975

Resolva o exercício usando fila (queue).

Classe: pairCaso especial de tuple, o pair associa dois elementos que podem ter tipos diferentes.

Seus valores podem ser acessados com first e second.

Referência completa: http://www.cplusplus.com/reference/utility/pair/

4 Escola de InvernoAno 2016

Saída:

Container Associativo: mapMapas são containers associativos que armazenam elementos formados por uma combinação de um valor-chave e um valor mapeado seguindo uma ordem específica.

Os valores-chave são geralmente usadas para ordenar e identificar unicamente os valores mapeados. Um valor-chave não pode ter mais de um valor mapeado.

Os elementos do map são pairs.

map suporta o operador [], com o valor-chave de argumento e retorna/associa o valor mapeado. Para se percorrer todos os elementos de um map usa-se um iterador bidirecional (só pode ser incrementado com ++ e --).

O unordered_map é em geral mais eficiente que o map mas seu iterador só pode ser incrementado (apenas ++).

Referência completa: http://www.cplusplus.com/reference/map/map/

Container Associativo: mapPrincipais métodos:

Acesso a elemento:

operador []

Iteradores: begin()end()

Capacidade: size()empty()

Modificadores: inserteraseclear()

Operações: findcount

Referência completa: http://www.cplusplus.com/reference/map/map/

2: B23: API = 3.14151PI

Saída:

Container: setSet é um container que armazena elementos segundo uma ordem.

Num conjunto o valor é a própria chave que o identifica, unicamente, e nenhum elemento pode ser alterado, mas pode ser inserido ou removido do container.

Sets são containers geralmente mais lentos que unordered_sets para acessar elementos individuais mas possuem iteradores bidirecionais.

Referência: http://www.cplusplus.com/reference/set/set/

Container: set

Principais métodos:

Iteradores: begin()end()

Capacidade: size()empty()

Modificadores: inserteraseclear()

Operações: findcount

Referência: http://www.cplusplus.com/reference/set/set/

12

Saída:

Exercícios1) PAIR

Crie um vector de pair com elementos aleatórios, ordene e imprima o resultado.2) SET

● Crie dois vectors de 10 inteiros aleatórios de 0 a 6● Imprima os números que estão presentes nos dois vetores, sem repetí-los.

Ex.: Para os vetores:A = { 5, 2, 3, 3, 5, 0, 0, 0, 1, 2 }

B = { 4, 4, 1, 1, 0, 3, 1, 1, 0, 6 }imprima:0 1 3

1) MAPURI 1449 - https://www.urionlinejudge.com.br/judge/pt/problems/view/1449

Classe: bitsetUm bitset é um vetor de bits, armazena somente valores 0 ou 1.

Pode ser entendido como um array de booleanos (true ou false) mas com alocação de memória otimizada

Permite a conversão para inteiro, tanto na construção do vetor como na leitura.

O tamanho do bitset é fixo, informado na declaração da variável por uma variável constante (const <type>) ou mesmo um número. Nos problemas da maratona, em geral o tamanho do bitset é definido como o maior número (ou caso limite) dado no problema.

É possível utilizar um vector<bool> para o mesmo efeito, com o adicional de possuir tamanho variável. Apesar de muitos alegarem que o bitset é mais eficiente, isso não é um consenso.

Referência completa: http://www.cplusplus.com/reference/bitset/bitset/

Classe: bitset

Principais métodos:

Acesso a bits: operador []count()size()testany()none()

Operações de bits: setreset()flip

Operações de Bitset:

to_ulong()to_ullong()

000011 00100001010021020

Saída:

Referência completa: http://www.cplusplus.com/reference/bitset/bitset/

Classe: bitsetOperadores:

AND &

OR |

XOR (Exclusive OR) ^

SHL (Shift Left) <<

SHR (Shift Right) >>

NOT ~

EQUALITY ==

DIFFERENCE !=

100100101101001001

011000001011010011

01

Saída:

Referência completa: http://www.cplusplus.com/reference/bitset/bitset/

Classe: bitsetExemplo: Crivo de Erastótenes

No problema de encontrar número primos o Crivo de Erastótenes apresenta uma solução famosa por sua simplicidade e eficiência.

O algoritmo consiste em percorrer um vetor várias vezes marcando os múltiplos de cada número como não-primos.

Nessa situção o bitset é um candidato para armazenar essa informação binária (primo ou não-primo, 0 ou 1, true ou false), etc.

Referência completa: http://www.cplusplus.com/reference/bitset/bitset/

Grafos - Introdução

Grafos - DefiniçãoA teoria dos grafos é um ramo da matemática que estuda as relações entre os objetos de um determinado conjunto.

Grafos são comumente representados por um conjunto de vértices (nós) conectados entre si por arestas.

Estruturas que podem ser representadas por grafos estão em toda parte e muitos problemas de interesse prático podem ser formulados como questões sobre certos grafos.

Exemplos: Redes sociais, mapas de ruas, rotas comerciais, rede elétrica, árvore genealógica, etc.

Dizemos que dois vértices são adjacentes quando há uma aresta conectando os dois.

Grafos - Tipos de Grafos

Grafo valorado (ou ponderado)Possui valores associados aos vértices ou arestas

Grafo não-direcionadoConexões entre os vértices não têm um sentido, vale a ida e a volta.

Grafo direcionadoConexões entre vértices têm um sentido específico.

Grafos - RepresentaçãoMatriz de AdjacênciasMatriz quadrada de lado N, onde N é o número de vértices.

Lista de AdjacênciasLista contendo, em cada elemento, uma lista de vértices com os quais esse faz ligação

Grafos - Matriz de Adjacências

Grafos - Vetor de Adjacências

Grafos - DFS Depth-First-SearchProblema: Partindo de qualquer vértice, deseja-se percorrer o grafo para saber quais vértices podem e não podem ser visitados.

Solução: DFS. Percorre-se o grafo marcando num vetor auxiliar os vértices que já foram visitados. Dessa forma também conseguimos evitar que algoritmo fique preso em loops.

FIM