Análise e Projeto de Algoritmos Teste – Unidade II 27 de Setembro de 2016 Arrays associativos (também conhecidos como dicionários) se tornaram parte essencial de linguagens de programação e sistemas em geral. Um dos modelos mais utilizados de bancos de dados NoSQL, por exemplo, mantém dados organizados na forma de dicionários, sendo de grande aplicação prática no contexto de redes sociais. O exemplo abaixo ilustra um possível banco assim, mostrando o número de ”likes” dos perfis dos quatro grandes clubes de futebol SP e RJ (os demais campos foram omitidos por simplicidade) e sua posição no ranking de mais curtidos (do futebol brasileiro eixo RJ-SP). clubes-rj-sp { ”FLA”: { ”rank”: 2, ”likes”: 10.704.866, ... }, ”VAS”: { ”rank”: 6, ”likes”: 2.912.761, ...}, ”BOT”: { ”rank”: 8, ”likes”: 1.269.474, ...}, ”FLU”: { ”rank”: 7, ”likes”: 1.276.152, ...}, ”COR”: { ”rank”: 1, ”likes”: 11.061.016, ...}, PAL”: { ”rank”: 4, ”likes”: 3.859.612, ...}, ”SPO”: { ”rank”: 3, ”likes”: 6.691.683, ... }, ”SAN”: { ”rank”: 5, ”likes”: 3.484.663, ... }, } Em uma situação real, o exemplo acima representaria um banco de dados de magnitude considerável. Assim, projetar um estrutura de dados eficiente para seu armazenamento é essencial. Considerando as siglas dos times como chaves, analise as seguintes situações: 1. O armazenamento destas entradas é feito usando uma tabela hash com 8 posições de armazenamento (1,5pt): (a) Apresente uma função hash que mapeie as chaves do dicionário a índices da tabela hash (0,5.pt). Funções hash para tratar strings costumam considerar (i) o tamanho da string, (ii) o valor ASCII dos caracteres da string e/ou (iii) operações bita-bit sobre os caracteres da string. Neste caso, uma hash simples seria a soma dos valores ASCII dos caracteres, levando aos seguintes valores hash: • FLA: 70 + 76 + 65 = 211 % 8 = 3 • VAS: 86 + 65 + 83 = 234 % 8 = 2 • BOT: 66 + 79 + 84 = 229 % 8 = 5 • FLU: 70 + 76 + 85 = 231 % 8 = 7 • COR: 67 + 79 + 82 = 227 % 8 = 3 • PAL: 77 + 65 + 76 = 218 % 8 = 2 • SPO: 83 + 77 + 79 = 239 % 8 = 7 • SAN: 83 + 65 + 78 = 226 % 8 = 2 1 (b) Demonstre os estados da hash quando as entradas são inseridas na ordem apresentada no exemplo e: i. a resolução de conflitos é feita através de encadeamento (0,5pt). A única decisão a ser tomada neste caso é se os buckets serão mantidos ordenados ou não. Caso não sejam, temos o estado final da hash abaixo: [0] → [1] → [2] → VAS → PAL → SAN [3] → FLA → COR [4] → [5] → BOT [6] → [7] → FLU → SPO ii. a resolução de conflitos é feita através de sequenciamento (0,5pt). Neste caso, as colisões devem ser tratadas seguindo algum algoritmo para o cálculo do próximo bucket a ser testado. Considerando o sequenciamento dado por b = b + i2 , onde b é o número do bucket a ser testado (originalmente indicado pela função hash) e i é o número de colisões, temos os seguintes estados pré- e pós-conflito: [0] [0] [0] PAL [0] PAL [0] PAL [1] [1] [1] [1] [1] SAN [2] VAS [2] VAS [2] VAS [2] VAS [2] VAS [3] FLA [3] FLA [3] FLA [3] FLA [3] FLA [4] [4] COR [4] COR [4] COR [4] COR [5] BOT [5] BOT [5] BOT [5] BOT [5] BOT [6] [6] [6] [6] SPO [6] SPO [7] FLU [7] FLU [7] FLU [7] FLU [7] FLU 2. O armazenamento destas entradas é feito usando uma árvore: (a) Binária de busca (0,5.pt). FLA (211) & VAS (234) .& BOT (229) .& COR (227) . PAL (218) & SAN (226) (b) Rubro-negra (0,5.pt). 2 SPO (239) FLU (231) 3 4 5 6 7 8 9 (c) B de ordem 4 (0,5.pt). 10