Aula 03 - Dicionários
Quando começamos a chegar no fim de DevLife usamos cada vez mais Dicionários em nosso código. Os usamos para representar coleções de pares chave->valor em que para cada chave existe exatamente um valor. Como era possível compor dicionários dentro de dicionários dentro de dicionários (e por aí vai) conseguíamos usá-los para representar hierarquias complexas. O tipo Map
representa de maneira abstrata esse tipo de estrutura de dados.
O tipo Map
Um Map
é uma mapeamento chave $\rightarrow$ valor em que cada chave pode estar a associada a um único valor. Note que um valor pode estar associado a várias chaves, mas cada chave só possui um valor. As seguintes operações são suportadas:
NOVO_MAP()
- cria um novoMap
SET(M, K, V)
- associa o valorV
à chaveK
. Se a chaveK
já existir substitui o valor.GET(M, K)
- devolve o valor associado a chaveK
. Se não houver retornaVAZIO
REMOVE(M, K)
- remove o par com chaveK
. Se não houver não faz nada.TAMANHO(M)
- devolve o número de chaves que possuem um valor associado
Neste roteiro desenvolveremos juntos os algoritmos necessários para implementar uma versão simplificada do Map
usando duas List
.
Construindo em cima de outras ADT
Uma das grandes vantagens de definir (e usar) ADTs é que podemos construir algoritimos em mais alto nível. Podemos dizer, simplesmente, que vamos usar uma variável do tipo Array
e/ou List
e apontar para quais operações são suportadas. Isso nos ajuda a manter os algoritmos compactos e a dar enfoque nas ideias mais importantes para o problema que queremos resolver.
Dica 1
ADTs são conhecimento básico em Computação. Não precisamos repetir, toda vez, o código para implementar o tipo List
. Basta dizer que está usando esse tipo.
A implementação mais simples Map
é usando duas listas:
KEYS(M)
é umList
contendo uma lista de todas as chaves doMap
M
VALUES(M)
é umList
contendo uma lista de todas os valores doMap
M
Exercício 1
Resposta
Uma maneira fácil de fazer isto é
KEYS(M)
=[ "pastel de queijo", "pastel de carne", "pastel de soja" ]
VALUES(M)
=[ 2, 1, 5 ]
A ordem aqui não importa, desde que sejamos consistentes e mantenhamos a equivalência de índices para que as chaves e valores continuem "casadas".
Exercício 2
Resposta
Eles são iguais! O conjunto de chaves de ambos é igual e para toda chave o valor devolvido é o mesmo. Para um Map
a ordem não importa, somente a presença da chave e o valor associado a ela.
Exercício 3
Resposta
Próxima seção ;)
Vamos usar as seguintes convenções a partir de agora
M_K = KEYS(M)
M_V = VALUES(M)
A ideia central é Dada uma associação chave-valor (K, V)
, se guardamos a chave K
no índice i
de M_K
guardaremos o valor V
no mesmo índice i
em M_V
.
De maneira mais formal, seja $M$ um Map
, $N=$TAMANHO(M_K)
e $(K, V)$ uma associação chave valor presente em M
, então
$$ (K, V) \in M \Leftrightarrow \exists 0 \leq i < N \;\;\text{ tal que }\;\; M_K[i] = K,\; M_V[i] = V $$
Vamos agora desenvolver alguns algoritmos simples para nos familiarizarmos com essa dupla de listas.
Exercício 4
Exercício 5
Resposta
Lousa
Exercício 6
Resposta
Lousa
As operações REMOVE
e TAMANHO
são variações dos que já foram construídos nessa aula. Para registrar, escreva-os abaixo.
Exercício 7
Exercício 8
Agora acesse o PrairieLearn e implemente esse algoritmos no exercício prático.