Prova Substitutiva PMR3201/PMR2300 1o. semestre 2015 Prof. Thiago Martins

Documentos relacionados
Prova 2 PMR3201 1o. semestre 2016 Prof. Thiago Martins

Prova 2 PMR3201 1o. semestre 2015 Prof. Thiago Martins

Prova 2 PMR2300 1o. semestre 2015 Prof. Thiago Martins

Prova de Recuperação PMR3201/PMR2300 1o. semestre 2015 Prof. Thiago Martins

Prova 1 PMR2300 / PMR3201 1o. semestre 2015 Prof. Thiago Martins

Prova 1 PMR3201 Computação para Automação 1o. semestre 2016 Prof. Thiago de Castro Martins

Prova Substitutiva PMR3201 1o. semestre 2018 Prof. Thiago Martins

Lista 2 - PMR2300/3200

Prova de Recuperação PMR3201 1o. semestre 2017 Prof. Thiago Martins

Lista 1 - PMR2300. Fabio G. Cozman 3 de abril de 2013

Árvores. Thiago Martins, Fabio Gagliardi Cozman. PMR2300 / PMR3201 Escola Politécnica da Universidade de São Paulo

Árvores. Fabio Gagliardi Cozman. PMR2300 Escola Politécnica da Universidade de São Paulo

Lista 1 - PMR3201. Fabio G. Cozman, Thiago Martins 2017

UNIP - Ciência da Computação e Sistemas de Informação. Estrutura de Dados. AULA 5 Pilhas

UNIVERSIDADE DA BEIRA INTERIOR

Árvores Estrutura de Dados. Universidade Federal de Juiz de Fora Departamento de Ciência da Computação

Fabio G. Cozman, Thiago Martins 2017

ESTRUTURA DE DADOS E ALGORITMOS. Árvores Binárias de Busca. Cristina Boeres

Departamento de Ciência de Computadores Estruturas de Dados (CC114)

Árvores & Árvores Binárias

Edital de Seleção 053/2016 PROPESP/UFAM. Prova de Conhecimento. Caderno de Questões

UNIVERSIDADE DA BEIRA INTERIOR

Árvores. Thiago Martins, Fabio Gagliardi Cozman. PMR2300 / PMR3201 Escola Politécnica da Universidade de São Paulo

Edital de Seleção 032/2016 PROPESP/UFAM. Prova de Conhecimento. Caderno de Questões

Árvores. A Profundidade da Árvore B C D E. Árvores Implementação Genérica

Árvores Binárias. SCC Algoritmos e Estruturas de Dados I. Prof. Fernando V. Paulovich

Exame de Estruturas de Dados 2010.Junho.26

Fabrício J. Barth. BandTec - Faculdade de Tecnologia Bandeirantes

Filas de prioridade. Marcelo K. Albertini. 3 de Dezembro de 2013

Universidade de São Paulo

Algoritmos e Estrutura de Dados II. Árvore. Prof a Karina Oliveira.

Edital de Seleção 023/2018 PROPESP/UFAM. Prova de Conhecimento. Caderno de Questões

Fontes Bibliográficas. Estruturas de Dados Aula 15: Árvores. Livros:

Classes, Herança e Interfaces

Edital de Seleção 024/2017 PROPESP/UFAM. Prova de Conhecimento. Caderno de Questões

Filas de Prioridade. Uma fila de prioridade pode ser vista como uma generalização das filas com as seguintes duas operações:

Árvores. Estruturas de Dados. Prof. Vilson Heck Junior

Árvores. SCC-214 Projeto de Algoritmos. Thiago A. S. Pardo. Um nó após o outro, adjacentes Sem relações hierárquicas entre os nós, em geral

Divisão e Conquista. Norton T. Roman. Apostila baseada nos trabalhos de Cid de Souza, Cândida da Silva e Delano M. Beder

Análise e Complexidade de Algoritmos

Trabalho Prático 1. Valor: 1,0 pontos (10% da nota total) Data de Entrega: 02/05/2010

UNIVERSIDADE DA BEIRA INTERIOR

Projeto e Análise de Algoritmos Aula 4: Dividir para Conquistar ou Divisão e Conquista ( )

Universidade Federal do ABC Avaliação Disciplina Turma Professor Data Instruções para a prova (leia antes de começar): SelectionSort selectonsortrec

SUMÁRIO. Fundamentos Árvores Binárias Árvores Binárias de Busca

Estruturas de dados e algoritmos fundamentais

Algoritmos e Estruturas de Dados

Tabelas Hash. informação, a partir do conhecimento de sua chave. Hashing é uma maneira de organizar dados que:

Filas de prioridade. Marcelo K. Albertini. 27 de Novembro de 2014

Árvores & Árvores Binárias

Tabelas de Dispersão. Estrutura de Dados e Algoritmos

Ordenação: MergeSort. Prof. Túlio Toffolo BCC202 Aula 14 Algoritmos e Estruturas de Dados I

ESTRUTURA DE DADOS (TCC )

DAINF - Departamento de Informática

Tabelas de Dispersão. Tabela de Dispersão

Recursividade. Objetivos do módulo. O que é recursividade

Estruturas de Dados Pilhas, Filas, Listas

Tabelas Hash O Que é uma Tabela Hash? O Que é uma Tabela Hash? O Que é uma Tabela Hash? Inserindo um Novo Registro. O Que é uma Tabela Hash?

Recursividade. Métodos iterativos. Prof. Cesar Augusto Tacla. Métodos iterativos utilizam estruturas de repetição

Prof. Jesus José de Oliveira Neto

JAVA. José de Siqueira UFMG - ICEx - DCC

Lista Ordenada. Estrutura de Dados. Universidade Federal de Juiz de Fora Departamento de Ciência da Computação 1 / 35

Lista 2 - PMR2300/3200

Centro Federal de Educação Tecnológica de Minas Gerais Programa de Pós-Graduação em Modelagem Matemática e Computacional

Departamento de Ciência de Computadores Estruturas de Dados (CC114)

pior caso nas operações de manipulação é O(N) pior caso surge sistematicamente emusos correntes (ex: elementos previamente ordenados)

Listas Lineares Ordenadas

Exercícios: Árvores. Universidade Federal de Uberlândia - UFU Faculdade de Computação - FACOM Lista de exercícios de estrutura de dados em linguagem C

Listas Estáticas. SCC Algoritmos e Estruturas de Dados I. Prof. Fernando V. Paulovich. *Baseado no material do Prof.

Árvores. Algoritmos e Estruturas de Dados I. José Augusto Baranauskas Departamento de Física e Matemática FFCLRP-USP

Pilhas e Filas Encadeadas. Algoritmos e Estruturas de Dados I

Árvores B. Prof. Márcio Bueno. / Fonte: Material da Prof a Ana Eliza Lopes Moura

double x; x = enigmab1(100);

Grupo 2 - Implementação de uma Classe Simples

ÁRVORES BINÁRIAS DE BUSCA. Vanessa Braganholo Estruturas de Dados e Seus Algoritmos

ALGORITMOS E ESTRUTURAS DE DADOS CES-11 Prof. Paulo André Castro Sala 110 Prédio da Computação IECE - ITA

Teoria da Computação. Aula 4 Técnicas de Análise 5COP096. Aula 4 Prof. Dr. Sylvio Barbon Junior. Sylvio Barbon Jr

MAC121 ALGORITMOS E ESTRUTURAS DE DADOS I 2O. SEMESTRE DE 2017

Árvores. SCC-202 Algoritmos e Estruturas de Dados I. Lucas Antiqueira

Ordenação por Intercalação Métodos de Ordenação Parte 4

Técnicas de projeto de algoritmos: Indução

Estruturas de Dados Algoritmos de Ordenação

Arquivos Sequenciais. Estruturas de Dados II Vanessa Braganholo

Árvores Binárias de Busca

Dicionários. TAD Orientado a conteúdo

Algoritmos e Complexidade

8. Árvores. Fernando Silva DCC-FCUP. Estruturas de Dados. Fernando Silva (DCC-FCUP) 8. Árvores Estruturas de Dados 1 / 38

8. Árvores. Fernando Silva. Estruturas de Dados DCC-FCUP. Fernando Silva (DCC-FCUP) 8. Árvores Estruturas de Dados 1 / 38

Algoritmos de Ordenação

Métodos de Ordenação Parte I

i a[i]

Bucketsort. CLRS sec 8.4. Algoritmos p. 1

AED - Algoritmos e Estruturas de Dados Licenciatura em Engenharia Electrónica

Recursividade. Prof. Jesus José de Oliveira Neto

Projeto e Análise de Algoritmos

Árvores Estrutura de Dados. Universidade Federal de Juiz de Fora Departamento de Ciência da Computação

Classificação e Pesquisa

Árvores. Prof. Byron Leite Prof. Tiago Massoni Prof. Fernando Buarque. Engenharia da Computação. Poli - UPE

Árvores e Mapas. Luís Lopes. Estruturas de Dados DCC-FCUP

Transcrição:

Prova Substitutiva PMR3201/PMR2300 1o. semestre 2015 Prof. Thiago Martins Instruções: Escreva o nome e o número USP na folha de papel almaço. 1. (20 pontos) Considere a classe HashSep que implementa uma tabela de hash com encadeamento aberto e resolução linear (Em caso de colisão a próxima posição livre é usada). Essa tabela emprega duplicação do arranjo base quando o seu fator de ocupação (razão entre quantidade de entradas armazenadas e o tamanho do arranjo) atinge ou supera 80%. A duplicação é uma operação na qual o arranjo base é substituído por um novo arranjo com o dobro do comprimento do anterior e os elementos armazenados são re-inseridos no novo arranjo. As chaves empregadas são números inteiros e a função de espalhamento empregada é: hash (i) = ((a i + b) mod p) mod s Onde i é o índice a ser espalhado p é um número primo fixo s é o tamanho atual do vetor base e a e b são números aleatórios entre 1 e p 1 gerados na criação da tabela. A função setdata(int key Object x) adiciona um novo objeto à tabela Suponha que a tabela h no código abaixo tenha sido construída com p = 11 s = 4 a = 7 e b = 4. Mostre o conteúdo da tabela após a execução de cada linha: 1 h.setdata(1 "um"); 2 h.setdata(2 "dois"); 3 h.setdata(3 "tr^es"); 4 h.setdata(4 "quatro"); Para tanto desenhe um diagrama mostrando o conteúdo de cada posição do vetor base. Indique também para cada entrada armazenada quantos passos são necessários para encontrá-la em uma busca (1 para acesso imediato via função de hash e um passo adicional para etapa de busca linear). Resposta: Após h.setdata(1 "um"); Hash de índice 1 = (0 mod 4) = 0 índice: 0 1 2 3 Conteúdo: 1 um Passos: 1 Após h.setdata(2 "dois"); Hash de índice 2 = (7 mod 4) = 3 índice: 0 1 2 3 1 2 Conteúdo: um dois Passos: 1 1 Após h.setdata(3 "tr^es"); Hash de índice 2 = (3 mod 4) = 3. Há colisão com o já ocupado índice 3 e o já ocupado índice 0. índice: 0 1 2 3 1 3 2 Conteúdo: um três dois Passos: 1 3 1 1

Após h.setdata(3 "quatro"); A ocupação nesta inserção atinge os 100%. Neste caso um novo vetor é criado e os elementos são re-inseridos. As novas posições são: 1. Hash: (0 mod 8) = 0 2. Hash: (7 mod 8) = 7 3. Hash: (3 mod 8) = 3 4. Hash: (10 mod 8) = 2 índice: 0 1 2 3 4 5 6 7 1 4 3 2 Conteúdo: um quatro três dois Passos: 1 1 1 1 2. (20 pontos) Considere o problema de se determinar se um número está ou não presente em uma matriz na qual todas as colunas e linhas estão ordenadas em ordem crescente. Exemplo: 1 3 10 23 4 7 18 36 7 12 26 44 Uma maneira de se resolver este problema é dividir a matriz em quatro quadrantes noroeste nordeste sudeste e sudoeste. Em seguida o valor na posição no centro da matriz é verificada. Caso ele seja maior do que o número procurado o quadrante sudeste (inferior direito) é removido da busca (acrescido da coluna e linha centrais) e a busca prossegue nos 3 quadrantes seguintes. Caso ele seja menor o quadrante noroeste (acrescido da coluna e linha centrais) é eliminado da busca e ela prossegue nos 3 quadrantes restantes. A listagem a seguir contém uma implementação em Java deste algoritmo: static boolean procura ( int v int [][] a) { return procura (v a 0 a [0]. length -1 0 a. length -1); static boolean procura ( int v int [][] a int o int e int n int s) { if(o >e n > s) return false ; int x = ( o+e )/2; // Coordenadas do int y = (n+s )/2; // centro int t = a[y][x]; if( v == t) return true ; // Achou if(v >t) { // Descarta canto NO return procura (v a x+1 e n y) // NE procura (v a x+1 e y+1 s) // SE procura (v a o x y+1 s); // SO else { // Descarta canto SE return procura (v a x e n y -1) // NE procura (v a o x -1 y s) // SO procura (v a o x -1 n y -1); // NO A matriz é representada por um vetor de linhas passado no parâmetro a. O parâmetro v contém o valor a ser procurado. A função procura(int v int[][] a) chama a função recursiva procura(int 2

v int[][] a int o int e int n int s) na qual os parâmetros o e n e s são os limites da matriz a oeste (esquerda) leste (direita) norte (acima) e sul (abaixo). (a) (10 pontos) Escreva a equação de recorrência da ordem de complexidade deste algoritmo em função de N o número total de elementos da matriz. Resposta: O algoritmo divide a matriz em 4 quadrantes cada um com aproximadamente 1/4 do tamanho da matriz original. Em seguida chama a si mesmo em 3 destes quadrantes. A operação de divisão e escolha de quadrantes a rejeitar tem complexidade constante O(1). A equação recursiva é: ( ) N T (N) = 3T + O(1) 4 (b) (10 pontos) Resolva a equação de recorrência do item anterior e compare este algoritmo com uma busca sequencial na matriz. Resposta: Na notação do teorema Mestre tem-se A = 3 B = 4 e L = 0. Neste caso naturalmente A > B L e a solução é N log B A ou seja T (N) = O ( N log 4 3) O ( N 07925) A busca sequencial direta tem complexidade O (N). Isso significa que o algoritmo recursivo é assintoticamente mais rápido do que a busca sequencial. 3. (20 pontos) Em uma árvore a profundidade de um nó é definida como a profundidade de seu pai + 1 se ele não é raiz ou zero para o nó raiz. A altura de uma árvore é a maior profundidade nela encontrada + 1. A classe NoBinario implementa um nó de árvore binária. Seu campo esquerdo aponta para sub-árvore esquerda e seu campo direito aponta para a sub-árvore direita. Implemente uma função em Java que calcula a altura de uma árvore binária. Utilize a seguinte assinatura: static int altura(nobinario n) Onde n é o nó raiz da árvore. Resposta: Como a altura é a profundidade máxima mais um a altura em um nó é a maior altura de todas as sub-árvores mais um. Segue uma solução recursiva que chama a si mesma na sub-árvore esquerda e direita e retorna o maior valor + 1: static int altura ( NoBinario n) { if( n == null ) return 0; // Arvore vazia int alturaesquerda = altura ( n. esquerdo ); int alturadireita = altura ( n. direito ); if( alturaesquerda > alturadireita ) return alturaesquerda +1; return alturadireita +1; 4. (20 pontos) O algoritmo de Euclides Extendido é um dos algoritmos necessários para a geração de chaves de criptografia RSA. Como o nome sugere ele é uma extensão do clássico algoritmo de Euclides 3

para calcular o máximo divisor comum. Além de calcular como o algoritmo de Euclides o máximo divisor comum r de a e b ele também calcula um par de inteiros x y tal que: r = ax + by A listagem a seguir mostra uma implementação do Algoritmo de Euclides Extendido. Ela retorna o resultado em um objeto do tipo egcdresult com os campos r que contém o valor do máximo divisor comum r e os campos x e y com o valor final dos inteiros x e y respectivamente. 1 static void egcd ( int a int b egcdresult result ) 2 { 3 int xa = 1 ya = 0; 4 int xb = 0 yb = 1; 5 while (b!=0) { 6 int q = a/ b; // Quociente 7 int r = a - q* b; // Resto 8 a = b; 9 b = r; 10 // Guarda os valores anteriores de xb yb 11 int txb = xb; 12 int tyb = yb; 13 xb = xa - q* xb; 14 yb = ya - q* yb; 15 xa = txb ; 16 ya = tyb ; 17 18 result. r = a; 19 result.x = xa; 20 result.y = ya; 21 Este algoritmo supõe sempre que a > b. Seja a i b i x ai y ai x bi y bi os valores das variáveis a b xa ya xb yb ao final da i-gésima iteração do laço iniciado na linha 5 e a 0 b 0 xa 0 ya 0 xb 0 yb 0 os valores destas variáveis antes da entrada no laço. Da análise do Algoritmo de Euclides tradicional feita em sala são conhecidos os seguintes fatos: O algoritmo termina em tempo finito (note que o controle de fluxo deste algoritmo é idêntico ao algoritmo convencional). gcd(a 0 b 0 ) = gcd(a i b i ). b n = 0 gcd(a 0 b 0 ) = a n. Dado o exposto acima demonstre que a implementação do algoritmo de Euclides Extendido está correta. Resposta: Do sabido sobre o algoritmo de Euclides mostra-se que o algoritmo termina em tempo finito e que o valor final obtido a n (sendo n a última iteração do laço iniciado na linha 5) é efetivamente o valor de gcd(a 0 b 0 ). Resta provar que a n = x an a 0 + y an b 0. Sabe-se pelas linhas 6 7 8 e 9 do algoritmo que a i+1 = b i b i+1 = a i q i+1 ai {{ b i b i 4

Então se em uma determinada iteração i vale a i = x ai a 0 + y ai b 0 b i = x bi a 0 + y bi b 0 Então esta relação permanecer válida na próxima iteração i + 1 se: x ai+1 = x bi y ai+1 = y bi x bi+1 = x ai q i+1 x bi y bi+1 = y ai q i+1 y bi Esta relação é exatamente a imposta pelas linhas de 11 a 16. Ora mas claramente a relação é válida para i = 0: a 0 = x a0 a 0 + y a0 b 0 b 0 = x b0 a 0 + y b0 b 0 Então na n-ésima iteração vale a n = x an a 0 + y an b 0 e o algoritmo está correto. 5. (20 pontos) A listagem a seguir consiste em uma implementação em Java do algoritmo de ordenação quicksort empregando a classe Limites para armazenar os limites inferior (campo a) e superior (campo b) da ordenação. Nesta implementação o elemento pivô é o último elemento do vetor. (a) (0.5 pontos) Considere a ordenação do vetor [8 6 4 2 5]. Desenhe a árvore de chamada da função quicksort para este vetor. Em cada nó indique o vetor que foi passado para função e os valores do parâmetro t. Mostre que a árvore é uma árvore binária. Em que ordem a árvore do item acima é percorrida pelo algoritmo quicksort? (use a terminologia apropriada à teoria de árvores binárias) Resposta: [8a 6 4 2 5b ] [ ] 2 4 5 8 6 a b [2 4 5 8a 6b ] [ ] [ ] 2 4 5 8 6 2 4 5 8 6 ab b a [ ] ] 2 4 5 6 8 [2 4 5 6 b a 8ab A árvore construída é claramente binária pois cada nó tem no máximo dois descendentes. O algoritmo visita em cada etapa o nó pai depois chama a si próprio no filho esquerdo e a si próprio no filho direito. Esta é uma varredura em profundidade com ordem anterior. (b) (15 pontos) Reescreva o algoritmo Quicksort com o auxílio da pilha implementada pela classe PilhaAr sem usar nenhuma recursão. Os métodos relevantes da classe PilhaAr são: PilhaAr(): Construtor cria uma nova pilha vazia. 5

push(object x): Adiciona o objeto x à pilha. Object pop(): Remove o último objeto a ser adicionado (apresentado como valor de retorno) ou lança a exceção PilhaVazia se não ouver objetos na pilha. boolean pilhavazia(): Retorna verdadeiro se a pilha não tem mais objetos falso caso contrário. static void quicksort ( int s []) { quicksort (s new Limites (0 s. length -1)); static void quicksort ( int s[] Limites t) { if(t.a >=t.b) return ; int p=s[t.b]; // pivot int l=t. a; int r=t.b -1; while (l <= r) { while ((l <=r )&&( s[l]<=p)) l ++; while ((l <=r )&&( s[r]>=p)) r - -; if (l<r) { int temp =s[l]; s[l]=s[r]; s[r]= temp ; s[t.b]=s[l]; s[l]=p; quicksort (s new Limites ( t.a (l -1))); quicksort (s new Limites ((l+1) t.b )); Resposta: Como visto em curso é possível percorrer uma árvore binária em ordem anterior sem recursão com o uso de uma pilha. Por exemplo o código a seguir imprime os nós de uma árvore em ordem anterior sem recursão: static void imprimeanterior ( NoBinario n) { PilhaAr p = new PilhaAr (); p. push (n); while (!p. vazia ()) { n = ( NoBinario )p. pop (); if(n!= null ) { System. out. println (n. dado ); p. push (n. direito ); p. push (n. esquerdo ); O mesmo princípio pode ser aplicado a uma reimplementação do quicksort: static void quicksort ( int s []) { PilhaAr pilha = new PilhaAr (); pilha. push ( new Limites (0 s. length -1)); while (! pilha. vazia ()) { Limites t = ( Limites ) pilha. pop (); if(t.a >=t.b) continue ; int p=s[t.b]; int l=t. a; int r=t.b -1; while (l <= r) { 6

while ((l <=r )&&( s[l]<=p)) l ++; while ((l <=r )&&( s[r]>=p)) r - -; if (l<r) { int temp =s[l]; s[l]=s[r]; s[r]= temp ; s[t.b]=s[l]; s[l]=p; pilha. push ( new Limites (t.a (l -1))); pilha. push ( new Limites ((l+1) t.b )); Formulário Somas de sequências: n 1 i = i=0 n(n 1) 2 n 1 i=0(a 1) n 1 i 2 = n3 3 n2 i=0 a i = 1 an n 1 1 a i=0(a 1) 2 + n n 1 6 i=0 i 3 = n4 4 n3 2 + n2 4 ia i = a nan + (n 1)a n+1 (1 a) 2. Solução de equações de recorrência pelo Master Theorem: A equação: com T (1) = O(1) tem solução T (N) = A T O ( N log A) B T (N) = O ( N L log N ) O ( N L) ( ) N + cn L B se A > B L se A = B L se A < B L 7

Códigos-fonte de apoio Classe PilhaAr public class PilhaAr { public class PilhaVazia extends java. lang. RuntimeException { private Object arranjo []; private int topo ; public PilhaAr () { arranjo = new Object [16]; topo = -1; Classe Hash: public class Hash { class DataNotFound extends java. lang. RuntimeException { class Pair { int key ; Object value ; Pair ( int key Object value ) { this. key = key ; this. value = value ; public void push ( Object x) { if (++ topo == arranjo. length ) dupliquearranjo (); arranjo [ topo ] = x; public Object pop () { if ( topo < 0) throw new PilhaVazia (); return ( arranjo [topo - -]); public boolean pilhavazia () { return topo <0; private void dupliquearranjo () { Object na [] = new Object [2 * arranjo. length ]; for ( int i =0; i< arranjo. length ; i ++) na[i] = arranjo [i]; arranjo = na; Classe NoBinario public class NoBinario { Object dado ; NoBinario esquerdo direito ; public NoBinario ( Object x NoBinario e NoBinario d) { dado = x; esquerdo = e; direito = d; Classe egcdresult public class egcdresult { int r x y; Classe Limites public class Limites { int a; int b; public Limites ( int a int b) { this.a = a; this.b = b; int a b size count ; final int p = 11; Pair [] entries ; public Hash () { entries = new Pair [ size =4]; // Tamanho inicial : 4 java. util. Random rng = new java. util. Random (); // a = rng. nextint (p ); b = rng. nextint (p ); a = 7; b = 4; int gethash ( int key ) { int h = ((a* key + b)%p)% size ; if(h <0) h += size ; return h; public void setdata ( int key Object data ) { int i = gethash ( key ); while ( entries [i ]!= null && entries [i]. key!= key ) i = (i +1)% size ; if( entries [i ]== null ) { entries [i] = new Pair (key data ); count ++; // nova entrada checkcount (); else entries [i]. value = data ; public Object getdata ( int key ) { int i = gethash ( key ); while ( entries [i ]!= null && entries [i]. key!= key ) i = (i +1)% size ; if( entries [i ]== null ) return null ; else return entries [i]. value ; void checkcount () { // Verifica se h necesside de ampliar o hash if( count *5 > size *4) { // Limite em 80% de ocupacao size *= 2; Pair [] old = entries ; entries = new Pair [ size ]; count = 0; for ( Pair e : old ) { if(e== null ) continue ; // pula entradas vazias this. setdata (e.key e. value ); // Insere na tabela nova public void removedata ( int key ) { int i = gethash ( key ); while ( entries [i ]!= null && entries [i]. key!= key ) i = (i +1)% size ; if( entries [i ]== null ) throw new DataNotFound (); count - -; int j=i; while ( true ) { entries [i] = null ; boolean skip = true ; while ( skip ) { j = (j +1)% size ; if( entries [j ]== null ) return ; int k = gethash ( entries [j]. key ); if(i <=j) skip = (i<j )&&(k <=j); else skip = (i<k ) (k <=j); entries [i] = entries [j]; i = j; 8