1 / 154

Espalhamento

Espalhamento. Sumário da Apresentação. Espalhamento A idéia inicial de espalhamento Métodos de Espalhamento Implementação das funções Hash Implementação do Espalhamento Hash com encadeamento em área separada Hash com encadeamento em área primária Hash usando Endereçamento Aberto

vega
Download Presentation

Espalhamento

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Espalhamento

  2. Sumário da Apresentação • Espalhamento • A idéia inicial de espalhamento • Métodos de Espalhamento • Implementação das funções Hash • Implementação do Espalhamento • Hash com encadeamento em área separada • Hash com encadeamento em área primária • Hash usando Endereçamento Aberto • Aplicação conta palavras (Java)

  3. Sumário da Apresentação • Espalhamento • A idéia inicial de espalhamento • Exemplo • Métodos de Espalhamento • Método da Divisão • Método do Meio do Quadrado • Método da Multiplicação • Implementação das funções Hash • Chaves Fundamentais • Chaves de Ponto Flutuante • Chaves de Cadeias de Caracteres • Espalhamento de Objetos • Espalhamento de Containers • Associações

  4. Sumário da Apresentação • Hash com encadeamento em área separada • Tabelas Hash Abstratas (só Java) • Encadeamento Separado • Implementação • Construtor e Destrutor (C++) • Construtor e métodos getLength e purge (Java) • Inserção e exclusão de itens • Encontro de itens • Hash com encadeamento em área primária • Tabelas de Espalhamento Encadeadas • Implementação • Construtor e Destrutor (C++) • Construtor e métodos getLength e purge (Java) • Inserção e encontro de itens • Exclusão de itens

  5. Sumário da Apresentação • Hash usando Endereçamento Aberto • Sondagem linear • Sondagem Quadrática • Duplo Hashing • Implementação • Construtor e Destrutor • Inserção de itens • Encontro de itens • Exclusão de itens

  6. Espalhamento

  7. Sumário do item Espalhamento • A idéia inicial de espalhamento • Exemplo • Métodos de Espalhamento • Método da Divisão • Método do Meio do Quadrado • Método da Multiplicação

  8. A idéia inicial de espalhamento • Exemplo: Deseja-se implementar um container de busca que será usado para armazenar cadeias de caracteres, K K = {“ett”; “tva”, “tre”, “fyra”; “fem”; “sex”²; “aju”, “atta”; “nio”; “tio”; “elva”; “tolv”}. Considere-se a definição de uma função de espalhamento, ou “hash”, como mostrado na figura abaixo: xh(x) xh(x) "ett" 1 "sju“ 7 "två" 2 "åtta“ 8 "tre“ 3 "nio“ 9 "fyra“ 4 "tio“ 10 "fem" 5 "elva“ 11 "sex“ 6 "tolv“ 12

  9. Espalhamento em memória Secundária • O Espalhamento em memória secundária é o processo preferencial para a implantação dos arquivos de acesso direto.

  10. Espalhamento em Memória Secundária 1- Agrupar um determinado número de registros em uma unidade com endereço comum chamada "bucket". 2- Calcular o espaço de armazenamento necessário para o arquivo. Esse dimensionamento do arquivo depende da densidade de empacotamento ou fator de carga que é a razão entre o número de registros nos arquivos e a capacidade total dos "buckets". 3- Escolher uma função "hash" que é a transformação a aplicar à chave para obter o endereço do "bucket". 4- Optar por uma técnica de resolução do problema de transbordamento. Ocorre transbordamento ou "overflow" quando se endereça um registro a um "bucket" já cheio.

  11. Buckets (1) • O arquivo é dividido em seções menores denominadas "buckets", que podem conter um ou mais registros. • A função "Hash" atribui a cada registro um endereço de "bucket" ("home address"), onde este pode ser acomodado. • O tamanho de “bucket” é determinado pelo número de registros que este pode armazenar, ou ainda, pelo número de "slots" que ele contém. Um "slot" é uma unidade de armazenamento que contém espaço para um registro. • Um arquivo com 1000 registros pode ser composto de 1.000 "buckets" de tamanho 1, ou 500 "buckets" de tamanho 2, etc... • Pode-se relacionar o tamanho do "bucket" a características físicas do meio de armazenamento. Logo, o tempo de transporte do “bucket” para a memória principal é proporcional ao tamanho do bucket.

  12. Buckets (2) • Ocorre uma colisão quando durante uma inclusão de registros, dois deles têm o mesmo endereço calculado pela função “hash”. Estes registros são chamados sinônimos. As colisões não constituem problemas enquanto não se atingir a capacidade do "bucket" correspondente. A partir daí, ocorre transbordamento, que consiste no fato de um registro não poder ser acomodado em "home bucket". • Define-se como "home bucket" aquele que está associado ao "home address" do registro, que fora calculado pela função "hash" aplicada à chave do registro. • Aumentando o tamanho dos "buckets" diminui a probabilidade de transbordamento mas aumenta o tempo de busca do registro no "bucket". Contudo, o acesso à memória principal é mais rápido comparado com o tempo de busca em memória secundária, uma vez que o “bucket” será transferido para memória principal.

  13. Métodos de Espalhamento

  14. Método do resto da Divisão • Para este caso a função hash é h(x) = x mod M, sendo M o número de endereços disponíveis para armazenamento. • Pode-se implementar um container de busca usando um array de tamanho n=12. Para inserir o item x, basta armazena-lo na posição h(x)-1 do array. • Os elementos do conjunto K são chamados de chaves. • É usual armazenar estas chaves em um array ou arquivo. • Imediatamente pode-se utilizar esta idéia para armazenar não apenas cadeias de caracteres e sim objetos dos quais um dos atributos seja uma chave do conjunto K. • A técnica de "hashing" proporciona uma recuperação de registros extremamente rápida se comparada com a recuperação seqüencial. O tempo de recuperação em arquivos sequenciais cresce com o tamanho do arquivo, o que não ocorre com o "hashing". No projeto de um arquivo de acesso direto os fatores que é necessário considerar são os seguintes:

  15. Método do Meio Quadrado • O espalhamento pelo meio do quadrado considera que M = 2k, o número de endereços (“buckets”), é um múltiplo de 2. Para palavras de tamanho W, com w bits as operações inteiras são feitas módulo W. • A função é hash de x é obtida elevando x ao quadrado módulo W e reduzindo este número ao domínio {0,1,...,M-1} por meio da multiplicação por dois elevado a w-k o que zera os w-k bits à esquerda. • O código que se segue mostra esta implementação unsigned int const k = 10; // M==1024 unsigned int const w = bitsizeof(unsigned int); unsigned int h(unsigned int x) { return (x * x) >> (w - k); }

  16. Método da Multiplicação • Uma variação do método do meio do quadrado é o método da multiplicação, pelo qual hash de x não multiplica x por si mesmo e sim por uma constante a • A escolha de a deve ser tal que seja relativamente primo com W, o que se consegue achando a' tal que aa’ = 1 (mod W). Ouseja, a' é a inversa de a modulo W. • Vale a propriedade axa'=aa'x=1x. • Para palavras de 32 bits pode-se escolher a = 2.654.435.769 cuja representação binária é 10 011 110 001 101 110 111 100 110 111 001. Sua inversa é • O código que se segue mostra esta implementação unsigned int const k = 10; // M==1024 unsigned int const w = bitsizeof(unsigned int); unsigned int const a = 2654435769U; unsigned int h(unsigned int x);

  17. Implementação das funções Hash

  18. Sumário do itemImplementação das funções Hash • Chaves Inteiras • Chaves de Ponto Flutuante • Chaves de Cadeias de Caracteres • Espalhamento de Objetos • Espalhamento de Containers • Associações

  19. Fundamentos • As chaves dos objetos podem ser de quaisquer tipos de dados até estruturas como associações ou containers. • Para um conjunto de chaves, K, e uma constante positiva M, uma função hash é da forma h: K  {0,1,..., M-1} • É conveniente implementar a função h como uma composição de duas funções f e g. A função f mapeia chaves em inteiros f: K  Z+ aonde Z+ é o conjunto dos inteiros não negativos. A função g mapeia inteiros não negativos em {0, 1, ..., M-1}, g: Z+  {0, 1, ..., M-1} • Desde que sejam conhecidas as funções f e g, a função hash h é definida como a composição delas: h = f  g • Ou seja, o valor de hash de uma chave x é dado por g(f(x)).

  20. Implementação das funções Hash Implementação C++

  21. Chaves Inteiras • A função f que mapeia chaves em inteiros para chaves constituídas de inteiros é f(x) = x • Definição da Função Hash de Inteiros // pgm08_01.cpp typedef unsigned int HashValue; HashValue Hash (char c) { return abs (c); } HashValue Hash (int i) { return abs (i); }

  22. Chaves de Ponto Flutuante • Todo real não nulo x pode ser expresso da forma x = m * 2e , sendo • A função f pode ser escrita • Sendo W o maior inteiro que pode ser expresso em uma palavra do computador x e y colidirão se suas mantissas diferirem de menos de 1/2W independente do valor dos expoentes. • Definição da Função Floating-Point Hash // pgm08_02.cpp HashValue Hash (double d) { if (d == 0) return 0; else { int exponent; double mantissa = std::frexp (d, &exponent); return (2 * fabs (mantissa) - 1) * ~0U; } }

  23. Chaves de Cadeias de Caracteres • Para chaves constituídas de cadeias de caracteres pode-se concatenar as representações dos caracteres. Sendo, por exemplo strings de comprimento 4 , estes strings podem ser transformados em inteiros pela expressão • Sendo potência de 2 pode-se escrever a função C++: HashValue Hash (string const& s) { return s[0] << 24 | s[1] << 16 | s[2] << 8 | s [3]; } • Para tratar strings de comprimento n pode-se fazer • O inconveniente é que não se está fixando limites para f(s). Pode-se corrigir isto fazendo aonde

  24. Chaves de Cadeias de Caracteres • Sendo W e B potencias de dois o valor calculado depende apenas dos últimos W/B caracteres do string. • Para e , todos os strings que possuam os mesmos quatro caracteres colidem. • Considerando f(s) como um polinômio em B, os coeficientes do polinômio, si, podem ser calculados pela Regra de Horner, que evita o cálculo dos expoentes de x. HashValue result = 0; for (unsigned int i = 0; s [i] != 0; ++i) result = result * B + s [i]; • Como o efeito de consideração de polinômio de base 2 é semelhante ao deslocamento (shift) basta concatenar os resultados parciais

  25. Chaves de Cadeias de Caracteres HashValue result = 0; for (unsigned int i = 0; s [i] != 0; ++i) result = result << b ^ s [i]; • Pode-se estudar os efeitos de consideração dos caracteres mais à esquerda e mais à direita ou ainda utilizar a regra do polinômio com coeficientes variáveis, por exemplo, obtidos de um array s. • Definição da Função Hash de Character String //pgm08_03.cpp unsigned int const shift = 6; HashValue const mask = ~0U << (bitsizeof (HashValue) - shift); HashValue Hash (std::string const& s) { HashValue result = 0; for (unsigned int i = 0; s [i] != 0; ++i) result = (result & mask) ^ (result << shift) ^ s [i]; return result; }

  26. Espalhamento de Objetos • Um template da classe Wrapper é usado para envelopar instâncias de tipos de dados C++ construídos em uma interface abstrata Object. Usando o template as quatro classes Char, Int, Double, and String são declaradas da forma: typedef Wrapper<char> Char; typedef Wrapper<int> Int; typedef Wrapper<double> Double; typedef Wrapper<string> String; • Como estas classes devem ser concretas devem ter implementações de todas as funções membros, inclusive a função Hash. • Definição da função Menbro Hash da Classe Wrapper<T> //pgm08_04.cpp template <class T> HashValue Wrapper<T>::Hash () const { return ::Hash (datum); }

  27. Espalhamento de Containers • A função hash f(c) de um container c, com n objetos, o1, o2, …, on é definida como • Para obter o hash de um container calcula-se a soma dos valores hash dos objetos contidos. • A função Container::Hash usa a função Accept para fazer um visitante especial HashingVisitor visitar todos os objetos do container. Quando visita um objeto chama a função Hash do visitado e acumula o resultado. • Definição da função Membro Hash da Classe Container

  28. Espalhamento de Containers // pgm08_05.cpp class HashingVisitor : public Visitor { HashValue value; public: HashingVisitor (HashValue _value) : value (_value) {} void Visit (Object& object) { value += object.Hash (); } HashValue Value () const { return value; } }; HashValue Container::Hash () const { HashingVisitor visitor (::Hash (typeid (*this).name())); Accept (visitor); return visitor.Value (); }

  29. Associações • Já que a função Accept é virtual todas as classes derivadas da classe Container fornecerão as implementações correspondentes. • Utilizando o conceito de chave pode-se escrever A = {(k,v):kK, v V} • A função hash pode ser expressa como fA(k,v) = fK(k) • Sedo fk a função hash associada ao conjunto K. • Uma Association possui dois objetos class Association : public Object, public Ownership { Object* key; Object* value; ...}; • Para definir a função hash de uma associação basta chamar a função membro hash do objeto para o qual a variável membro key aponta • DefiniçãodaFunção Hash Member daclasse Association HshValue Association::Hash() const { return key->Hash(): }

  30. Implementação das funções Hash Implementação Java

  31. Método hashCode da classe Int • A função f que mapeia chaves em inteiros para chaves constituídas de inteiros é f(x) = x // pgm08_01.java public class Int extends AbstractObject { protected int value; public int hashCode() { return value; } // ... }

  32. Método hashCode da classe Dbl • A definição da função f é: // pgm08_02.java public class Dbl extends AbstractObject { protected double value; public int hashCode() { long bits = Double.doubleToLongBits(value); return (int)(bits >>> 20); } // ... }

  33. Chaves de Cadeias de Caracteres • Para chaves constituídas de cadeias de caracteres pode-se concatenar as representações dos caracteres. Sendo, por exemplo strings de comprimento 4 , este string pode ser transformado em inteiro pela expressão • Sendo B=27potência de 2 pode-se escrever a função Java: static int f (String s) { return s.charAt(0) << 21 | s.charAt (1) << 14 | s.charAt (2) << 7 | s.charAt (3); } • Para tratar strings de comprimento n pode-se fazer • O inconveniente é que não se está fixando limites para f(s). Pode-se corrigir isto fazendo aonde

  34. Chaves de Cadeias de Caracteres • Sendo W e B are potencias de dois o valor calculado depende apenas dos últimos W/B caracteres do string. • Para e , todos os strings que possuam os mesmos quatro caracteres colidem. • Considerando f(s) como um polinômio em B, os coeficientes do polinômio, si, podem ser calculados pela Regra de Horner, que evita o cálculo dos expoentes de x. static int f (String s) { int result = 0; for (int i = 0; i < s.length (); ++i) result = result * B + s.charAt (i); return result; } • Como o efeito de consideração de polinômio de base 2 é semelhante ao deslocamento (shift) basta concatenar os resultados parciais

  35. Chaves de Cadeias de Caracteres static int f (String s) { int result = 0; for (int i = 0; i < s.length () ; ++i) result = result << b ^ s.charAt (i); return result; } • Pode-se estudar os efeitos de consideração dos caracteres mais à esquerda e mais à direita ou ainda utilizar a regra do polinômio com coeficientes variáveis, por exemplo, obtidos de um array s.

  36. Método hashCode da classe Str // pgm08_03.java public class Str extends AbstractObject { protected String value; private static final int shift = 6; private static final int mask = ~0 << (32 - shift); public int hashCode() { int result = 0; for(int i = 0; i < value.length (); ++i) result = (result & mask) ^ (result << shift) ^ value.charAt (i); return result; } // ... }

  37. Espalhamento de Containers • A função hash f(c) de um container c, com n objetos, o1, o2, …, on é definida como • Para obter o hash de um container calcula-se a soma dos valores hash dos objetos contidos.

  38. Método hashCode da classe AbstractContainer // pgm08_04.java public abstract class AbstractContainer extends AbstractObject implements Container { protected int count; public int hashCode() { Visitor visitor = new AbstractVisitor() { private int value; public void visit (Object object) { value += object.hashCode(); } public int hashCode() { return value; } }; accept (visitor); return getClass().hashCode() + visitor.hashCode (); }// ... }

  39. Associações • Já que a função Accept é virtual todas as classes derivadas da classe Container fornecerão as implementações correspondentes. • Utilizando o conceito de chave pode-se escrever • A função hash pode ser expressa como • Sedo fk a função hash associada ao conjunto K. • Uma Association possui dois objetos public class Association extends AbstractObject { protected Comparable key; protected Object value; ...}; • Para definir a função hash de uma associação basta chamar a função membro hash do objeto para o qual a variável key membro aponta

  40. Método hashCode da classe Association // pgm08_05.java public class Association extends AbstractObject { protected Comparable key; protected Object value; public int hashCode() { return key.hashCode(); } // ... }

  41. Implementação do Espalhamento

  42. Sumário do item Implantação do Espalhamento • Hash com encadeamento em área separada • Tabelas Hash Abstratas (só Java) • Encadeamento Separado • Hash com encadeamento em área primária • Tabelas de Espalhamento Encadeadas • Hash usando Endereçamento Aberto • Sondagem linear • Sondagem Quadrática • Duplo Hashing • Implementação

  43. Implementação do Espalhamento Implementação C++

  44. Tabelas Hash • Definição da Classe HashTable //pgm08_07.cpp class HashTable : public virtual SearchableContainer { protected: unsigned int length; public: HashTable (unsigned int); virtual unsigned int H (Object const&) const; };

  45. Implementação do EspalhamentoC++ Hash com encadeamento em área separada

  46. Tabelas Hash • Definição das funções H Member e do Constructor da Classe HashTable //pgm08_08.cpp HashTable::HashTable (unsigned int _length) : length (_length) {} unsigned int HashTable::H (Object const& object) const { return object.Hash () % length; } • O construtor de HashTable recebe um simples argumento e inicializa a variável membro de maneira adequada. A função membro corresponde à composição h = g  f. A função membro H recebe como argumento uma referencia constante a um objeto e retorna o resultado Hash modulo length.

  47. Encadeamento Separado • Tabela Hash usando Encadeamento Separado

  48. Definição da Classe ChainedHashTable // pgm08_09.cpp class ChainedHashTable : public HashTable { Array<LinkedList<Object*> > array; public: ChainedHashTable (unsigned int); // ... };

  49. Definição das funções Purge Member, Constructor e Destructor da Classe ChainedHashTable (1) // pgm08_10.cpp ChainedHashTable::ChainedHashTable (unsigned int _length) : HashTable (_length), array (_length) {}

  50. Definição das funções Purge Member, Constructor e Destructor da Classe ChainedHashTable (2) // pgm08_10.cpp (Continuação) void ChainedHashTable::Purge() { for (unsigned int i = 0; i < length; ++i) { if(IsOwner ()) { ListElement<Object*> const* ptr; for( ptr = array[i].Head (); ptr != 0; ptr = ptr->Next() ) delete ptr->Datum (); } array[i].Purge(); } count = 0; } ChainedHashTable::~ChainedHashTable () { Purge (); }

More Related