pesquisa em memória primária - wordpress.com · 2019. 11. 20. · bruno hott 3 introdução –...

73
Pesquisa em Memória Primária Bruno Hott Algoritmos e Estruturas de Dados I DECSI – UFOP

Upload: others

Post on 10-Mar-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Pesquisa em Memória Primária

Bruno HottAlgoritmos e Estruturas de Dados IDECSI – UFOP

Page 2: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 2

Pesquisa em Memória Primária

● Introdução - Conceitos Básicos

● Pesquisa Sequencial

● Pesquisa Binária

● Árvores de Pesquisa

– Árvores Binárias de Pesquisa sem Balanceamento

– Árvores Binárias de Pesquisa com Balanceamento

– Árvores AVL

– Árvores Digitais

– Árvores Vermelho e Preto

● Transformação de Chave (Hashing‏)

– Listas Encadeadas,

– Endereçamento Aberto

Page 3: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 3

Introdução – Conceitos Básicos

● Estudo de como recuperar informação a partir de uma grande massa de informação previamente armazenada.

● A informação é dividida em registros.

● Cada registro possui uma chave para ser usada na pesquisa.

● Objetivo da pesquisa: Encontrar uma ou mais ocorrências de registros com chaves iguais à chave de pesquisa.

● Pesquisa com sucesso

X Pesquisa sem sucesso.

Page 4: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 4

Introdução – Conceitos Básicos

● Tabelas

– Conjunto de registros ou arquivos TABELAS⇒ TABELAS

– Tabela: associada a entidades de vida curta, criadas na memória interna durante a execução de um programa.

– Arquivo: geralmente associado a entidades de vida mais longa, armazenadas em memória externa.

Page 5: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 5

Escolha do Método de Pesquisa mais Adequado a uma Determinada Aplicação

● Depende principalmente:

– Quantidade dos dados envolvidos.

– Arquivo estar sujeito a inserções e retiradas frequentes

● Se conteúdo do arquivo é estável é importante minimizar o tempo de pesquisa, sem preocupação com o tempo necessário para estruturar o arquivo

Page 6: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 6

Algoritmos de PesquisaTipos Abstratos de Dados

● É importante considerar os algoritmos de pesquisa como tipos abstratos de dados (TADs‏), com um conjunto de operações associado a uma estrutura de dados, de tal forma que haja uma independência de implementação para as operações.

● Operações mais comuns:

(‏1 Inicializar a estrutura de dados.

(‏2 Pesquisar um ou mais registros com determinada chave.

(‏3 Inserir um novo registro.

(‏4 Retirar um registro específico.

(‏5 Ordenar um arquivo para obter todos os registros em ordem de acordo com a chave.

(‏6 Juntar dois arquivos para formar um arquivo maior.

Page 7: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 7

Dicionário

● Nome comumente utilizado para descrever uma estrutura de dados para pesquisa.

● Dicionário é um tipo abstrato de dados com as operações:

(‏1 Inicializa

(‏2 Pesquisa

(‏3 Insere

(‏4 Retira

● Analogia com um dicionário da língua portuguesa:

– Chaves palavras

– Registros entradas associadas com*pronúncia, definição, sinônimos, outras informações

Page 8: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 8

Pesquisa Sequencial

● Método de pesquisa mais simples:

– a partir do primeiro registro, pesquise seqüencialmente até encontrar a chave procurada; então pare.

● Armazenamento de um conjunto de registros por meio do tipo estruturado arranjo

Page 9: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 9

Pesquisa Sequencial

#define MAX 10

typedef struct{ long Chave; /* outros componentes */}TRegistro;

typedef struct{ TRegistro Item[MAX+1]; int n;}TTabela;

Page 10: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 10

Pesquisa Sequencial

//Implementação para as operações Inicializa, Pesquisa:

void inicializa(TTabela *T{‏){ T->n = 0;}

int pesquisa_seq(TTabela *T, long x{‏){ int i; T->Item[0].chave = x; i = T->n; while(T->Item[i].chave != x{‏) i--; return i;}

Page 11: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 11

Pesquisa Sequencial

//Implementação para a operacao Insere:

void Insere(Registro Reg, TTabela *T{‏){ if(T->n == MAX{‏) printf("Erro : tabela cheia\n"{‏); else{ T->n++; T->Item[T->n] = Reg; }}

Page 12: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 12

Pesquisa Sequencial

● Pesquisa retorna o índice do registro que contém a chave x;

● Caso não esteja presente, o valor retornado é zero.

● A implementação não suporta mais de um registro com uma mesma chave.

● Para aplicações com esta característica é necessário incluir um argumento a mais na função Pesquisa para conter o índice a partir do qual se quer pesquisar.

Page 13: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 13

Pesquisa Sequencial

● Utilização de um registro sentinela na posição zero do array:

– Garante que a pesquisa sempre termina: se o índice retornado por Pesquisa for zero, a pesquisa foi sem sucesso.

– Não é necessário testar se i > 0, devido a isto:● o anel interno da função Pesquisa é extremamente simples: o índice i é

decrementado e a chave de pesquisa é comparada com a chave que está no registro.

● isto faz com que esta técnica seja conhecida como pesquisa sequencial rápida.

Page 14: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 14

Pesquisa Sequencial:Análise

● Pesquisa com sucesso:

– melhor caso : C(n‏) = 1

– pior caso : C(n‏) = n

– caso médio: C(n‏) = (n + 1‏) / 2

● Pesquisa sem sucesso:

– C (n‏) = n + 1.

● O algoritmo de pesquisa sequencial é a melhor escolha para o problema de pesquisa em tabelas com até 25 registros.

Page 15: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 15

Pesquisa Binária

● Pesquisa em tabela pode ser mais eficiente se registros forem mantidos em ordem

● Para saber se uma chave está presente na tabela

(‏1 Compare a chave com o registro que está na posição do meio da tabela.

(‏2 Se a chave é menor então o registro procurado está na primeira metade da tabela

(‏3 Se a chave é maior então o registro procurado está na segunda metade da tabela.

(‏4 Repita o processo até que a chave seja encontrada, ou fique apenas um registro cuja chave é diferente da procurada, significando uma pesquisa sem sucesso.

Page 16: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 16

Exemplo de Pesquisa Binária para a Chave G

Page 17: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 17

Pesquisa Binária

int pesquisa_binaria(TTabela *T, long x{‏){ int i, esq, dir;

if(T->n == 0{‏) return 0;

esq = 1; dir = T->n; do{ i = (Esq + Dir{‏) / 2; if(x > T->Item[i].Chave{‏) esq = i+1; else dir = i-1; while( (x != T->Item[i].Chave{‏) && (esq <= dir{‏) {‏);

if(x == T->Item[i].chave{‏) return i; else return 0;

}

Page 18: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 18

Pesquisa Binária:Análise

● A cada iteração do algoritmo, o tamanho da tabela é dividido ao meio.

● Logo: o número de vezes que o tamanho da tabela é dividido ao meio é cerca de log n.

● Ressalva: o custo para manter a tabela ordenada é alto: a cada inserção na posição p da tabela implica no deslocamento dos registros a partir da posição p para as posições seguintes.

● Consequentemente, a pesquisa binária não deve ser usada em aplicações muito dinâmicas.

Page 19: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 19

Árvores de Busca

Bruno HottAlgoritmos e Estruturas de Dados IDECSI – UFOP

Page 20: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 20

Árvores de Pesquisa

● A árvore de pesquisa é uma estrutura de dados muito eficiente para armazenar informação.

● Particularmente adequada quando existe necessidade de considerar todos ou alguma combinação de:

(‏1 Acesso direto e sequencial eficientes.

(‏2 Facilidade de inserção e retirada de registros.

(‏3 Boa taxa de utilização de memória.

(‏4 Utilização de memória primária e secundária.

Page 21: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 21

Árvores Binárias de Pesquisa sem Balanceamento

● Para qualquer nó que contenha um registro

● Temos a relação invariante:

– Todos os registros com chaves menores estão na subárvore à esquerda.

– Todos os registros com chaves maiores estão na subárvore à direita.

Page 22: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 22

Árvores Binárias de Pesquisasem Balanceamento

● O nível do nó raiz é 0.

– Se um nó está no nível i então a raiz de suas subárvores estão no nível i+1.

– A altura de um nó é o comprimento do caminho mais longo deste nó até um nó folha.

– A altura de uma árvore é a altura do nó raiz.

Page 23: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 23

TAD-Árvore Binária de Pesquisa

typedef struct{ long chave; /* outros componentes */}TRegistro;

typedef struct TNo{ TRegistro reg; Tno *pEsq, *pDir;}TNo;

typedef TNo* TDicionario;

Page 24: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 24

Procedimento para Pesquisar na Árvore

● Para encontrar um registro com uma chave x:

(‏1 Compare-a com a chave que está na raiz.

(‏2 Se x é menor, vá para a subárvore esquerda.

(‏3 Se x é maior, vá para a subárvore direita.

(‏4 Repita o processo recursivamente, até que a chave procurada seja encontrada ou um nó folha é atingido.

(‏5 Se a pesquisa tiver sucesso então o conteúdo do registro retorna no próprio registro x.

Page 25: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 25

Procedimento para Pesquisar na Árvore

int pesquisa(TNo* pRaiz, TRegistro *pX{‏){ if(pRaiz == NULL{‏) return 0;

if(pX->chave < pRaiz->reg.chave{‏) return pesquisa(pRaiz->pEsq,pX{‏); if(pX->chave > pRaiz->reg.chave{‏) return pesquisa(pRaiz->pDir,pX{‏);

/* if(pX->chave == pRaiz->reg.chave{‏) */ *pX = pRaiz->reg; return 1;}

Page 26: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 26

Procedimento para Pesquisar na Árvore(não recursivo‏)

int pesquisa(TNo* pRaiz, TRegistro *pX{‏){ TNo* pAux = pRaiz;

while(pAux != NULL{‏){ if(pX->chave == pAux->reg.chave{‏){ *pX = pAux->Reg; return 1;

if (pX->chave > pAux->reg.chave{‏) pAux = pAux->pDir; else /* if (pX->chave < pAux->reg.chave{‏) */ pAux = pAux->pEsq; } return 0;}

Page 27: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 27

Procedimento para Inserir na Árvore

● Onde inserir?

– Atingir um apontador nulo em um processo de pesquisa significa uma pesquisa sem sucesso.

– O apontador nulo atingido é o ponto de inserção.

● Como inserir?

– Cria célula contendo registro

– Procura lugar na árvore

– Se registro não tiver na árvore, insere-o

Page 28: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 28

Procedimento para Inserir na Árvore

int insere(TNo** ppRaiz, TRegistro x{‏){ if(*ppRaiz == NULL{‏){ *ppRaiz = cria_no(x{‏); return 1; }

if(x.chave < (*ppRaiz{‏)->reg.chave{‏) return insere(&((*ppRaiz{‏)->pEsq{‏), x{‏); if(x.chave > (*ppRaiz{‏)->reg.chave{‏) return insere(&((*ppRaiz{‏)->pDir{‏), x{‏); return 0; /* elemento jah existe */}

Page 29: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 29

Procedimento para Inserir na Árvore(não recursivo‏)

int insere(TNo** ppRaiz, TRegistro x{‏){ TNo** ppAux = ppRaiz;

while (*ppAux != NULL{‏){ if(x.chave < (*ppAux{‏)->reg.Chave{‏) ppAux = &((*ppAux{‏)->pEsq{‏); else if(x.chave > (*ppAux{‏)->reg.chave{‏) ppAux = &((*ppAux{‏)->pDir{‏); else /* if(x.chave == (*ppAux{‏)->reg.chave{‏) */ return 0; }

*ppAux = cria_no(x{‏); return 1;}

Page 30: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 30

Procedimentos para Inicializar a Árvore

void inicializa(TNo** Dicionario{‏){ *TDicionario = NULL;}

Page 31: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 31

Retirada de um Registro da Árvore

● Como retirar?

● Folha?

● Nó interno, contendo um filho?

● Raiz da árvore ou subárvore?

Page 32: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 32

Procedimento para Retirar x da Árvore

● A retirada de um registro não é tão simples quanto a inserção.

● Se o nó que contém o registro a ser retirado possui no máximo um descendente, a operação é simples.

● No caso do nó conter dois descendentes o registro a ser retirado deve ser primeiro:

– substituído pelo registro mais à direita na subárvore esquerda;

– ou pelo registro mais à esquerda na subárvore direita.

Page 33: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 33

Exemplo de Retirada de um Registro da Árvore

● para retirar o registro com chave 5 da árvore basta trocá-lo pelo registro com chave 4 ou pelo registro com chave 6, e então retirar o nó que recebeu o registro com chave 5.

Page 34: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 34

Exemplo de Retirada de um Registro da Árvore

int retira(Registro x, Tno** p{‏){ TNo* pAux;

if(*p == NULL{‏) return 0; if(x.chave < (*p{‏)->reg.chave{‏) return retira(x, &(*p{‏)->pEsq{‏); if(x.chave > (*p{‏)->reg.chave{‏) return retira(x, &(*p{‏)->pDir{‏);

/* if(x == (*p{‏){‏) */ if((*p{‏)->pDir == NULL{‏){ pAux = *p; *p = (*p{‏)->pEsq; free(pAux{‏); return 1; } if((*p{‏)->pEsq == NULL{‏){ pAux = *p; *p = (*p{‏)->pDir; free(pAux{‏); return 1; }

/* dois filhos */ antecessor(*p, &(*p{‏)->pEsq{‏); return 1;}

Page 35: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 35

Exemplo de Retirada de um Registro da Árvore

void antecessor(TNo* q, TNo** r{‏){ TNo* pAux; if( (*r{‏)->pDir != NULL{‏){ antecessor(q, &(*r{‏)->pDir{‏); return; } q->reg = (*r{‏)->reg; pAux = *r; *r = (*r{‏)->pEsq; free(pAux{‏);}

Page 36: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 36

Exemplo de Retirada de um Registro da Árvore

Obs.: proc. recursivo Antecessor só é ativado quando o nó que contém registro a ser retirado possui 2 descendentes.

Solução usada por Wirth, 1976, p.211.

Page 37: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 37

Caminhamento Central

Percorrer a árvore:

Em que ordem chaves são recuperadas (usando caminhamento central‏)?

1, 2, 3, 4, 5, 6 e 7.

Page 38: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 38

Caminhamento Central

● Após construída a árvore, pode ser necessário percorrer todo os registros que compõem a tabela ou arquivo.

● Existe mais de uma ordem de caminhamento em árvores, mas a mais útil é a chamada ordem de caminhamento central.

● Uma característica importante do caminhamento central é que os nós são visitados de forma ordenada.

Page 39: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 39

Caminhamento Central

void central(TNo* pRaiz{‏){ if (pRaiz == NULL{‏) return;

central(p->pEsq{‏); printf("%ld\n", p->reg.chave{‏); central(p->pDir{‏);}

Page 40: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 40

Análise

● O número de comparações em uma pesquisa com sucesso:

– melhor caso: C(n‏) = O(1‏)

– pior caso: C(n‏) = O(n‏)

– caso médio: C(n‏) = O(log n‏)

● O tempo de execução dos algoritmos para árvores binárias de pesquisa dependem muito do formato das árvores.

Page 41: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 41

Análise

● Para obter o pior caso basta que as chaves sejam inseridas em ordem crescente ou decrescente. Neste caso a árvore resultante é uma lista linear, cujo número médio de comparações é (n + 1‏)/2.

● Para uma árvore de pesquisa aleatória o número esperado de comparações para recuperar um registro qualquer é cerca de 1,39 log n, apenas 39% pior que a árvore completamente balanceada.

Page 42: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 42

Árvores AVL

Bruno HottAlgoritmos e Estruturas de Dados IDECSI – UFOP

Page 43: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 43

Árvore AVL

● Árvore binária de busca tal que, para qualquer nó interno v, a diferença das alturas dos filhos de v é no máximo 1.

● Árvores AVL são balanceadas

88

44

17 78

32 50

48 62

2

4

1

1

2

3

1

1

Page 44: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 44

Árvores Binárias Balanceadas e AVL

● Inserindo os nós 30, 20, 40, 10, 25, 35 e 50 nesta ordem, teremos:

30

20

10 25

40

35 50

Page 45: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 45

Árvores Binárias Balanceadas e AVL

● Inserindo os nós 10, 20, 30, 40 e 50 nesta ordem, teremos:

10

20

30

40

50

Page 46: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 46

Árvores Binárias Balanceadas

● Existem ordens de inserção de nós que conservam o balanceamento de uma árvore binária.

● Na prática é impossível prever essa ordem ou até alterá-la.

Page 47: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 47

Árvores Binárias Balanceadas

● A vantagem de uma árvore balanceada com relação a uma degenerada está em sua eficiência.

● Por exemplo: numa árvore binária degenerada de 1.000.000 nós são necessárias, em média, 500.000 comparações (semelhança com arrays ordenados e listas encadeadas‏).

● Numa árvore balanceada com o mesmo número de nós essa média reduz-se a 20 comparações.

Page 48: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 48

AVL

● Algoritmo de balanceamento de árvores binárias.

● A origem da denominação AVL vem dos seus dois criadores: Adel’son-Vel’skii e Landis.

● Ano de divulgação: 1962.

Page 49: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 49

Árvore AVL (TAD‏)

typedef struct{ long chave; /* outros componentes */}TRegistro;

typedef struct{ TRegistro reg; TNo* pEsq, pDir;}TNo;

typedef TNo* TipoDicionario;

Page 50: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 50

Árvores AVL

● Uma árvore binária balanceada é aquela na qual, para cada nó, as alturas de suas sub-árvores esquerda e direita diferem de, no máximo, 1.

● Fator de balanceamento (FB‏) de um nó é a diferença entre a altura da sub-árvore esquerda em relação à sub-árvore direita.

FB(p‏) = altura(sub-árvore esquerda de p‏)

- altura(sub-árvore direita de p‏)

● Em uma árvore binária balanceada todos os FB de todos os nós estão no intervalo -1 FB 1

Page 51: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 51

FB e Altura

int fb(TNo* pRaiz{‏){ if(pRaiz == NULL{‏) return 0;

return altura(pRaiz->pEsq{‏) - altura(pRaiz->pDir{‏);}

int altura(TNo* pRaiz{‏){ int hEsq,hDir; if(pRaiz == NULL{‏) return 0;

hEsq = altura(pRaiz->pEsq{‏); hDir = altura(pRaiz->pDir{‏);

if(hEsq > hDir{‏) return hEsq+1; else return hDir+1;}

Page 52: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 52

AVL

● Inicialmente inserimos um novo nó na árvore normalmente.

● A inserção deste pode degenerar a árvore.

● A restauração do balanceamento é feita através de rotações na árvore no nó “pivô”.

● Nó “pivô” é aquele que após a inserção possui fator de balanceamento fora do intervalo.

Page 53: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 53

AVL

● Rotação simples para a direita (RSD‏)

– FB > 1 (subárvore esquerda maior que subárvore direita‏)

– E a subárvore esquerda desta subárvore esquerda é maior que a subárvore direita dela

– Então realizar uma rotação simples para a direita.

3

2

1

Page 54: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 54

AVL

● Rotação simples para a direita (RSD‏)

3

2

1

2

1 3

Page 55: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 55

AVL

● Rotação simples para a esquerda (RSE‏)

– FB < -1 (subárvore esquerda menor que subárvore direita‏)

– E a subárvore direita desta subárvore direita é maior que a subárvore esquerda dela

– Então realizar uma rotação simples para a esquerda.

1

2

3

Page 56: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 56

AVL

● Rotação simples para a esquerda (RSE‏)

1

2

3

2

1 3

Page 57: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 57

AVL

● Rotação dupla para a direita (rotação esquerda-direita - RED‏)

– FB > 1 (subárvore esquerda maior que subárvore direita‏)

– E a subárvore esquerda desta subárvore esquerda é menor ou igual que a subárvore direita dela

– Então realizar uma rotação dupla para a direita.

1

3

2

Page 58: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 58

AVL

● Rotação dupla para a direita (rotação esquerda-direita - RED‏)

1

3

2

2

1 3

3

2

1

Page 59: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 59

AVL

● Rotação dupla para a esquerda (rotação direita-esquerda RDE‏)

FB < -1 (subárvore esquerda menor que subárvore direita‏)

– E a subárvore direita desta subárvore direita é menor que a subárvore esquerda dela

– Então realizar uma rotação dupla para a esquerda.

Page 60: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 60

AVL

● Rotação dupla para a esquerda (rotação direita-esquerda RDE‏)

1

3

2

1

2

3

2

1 3

Page 61: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 61

Rotações Simples

void rse(TNo** ppRaiz{‏){ TNo *pAux;

pAux = (*ppRaiz{‏)->pDir; (*ppRaiz{‏)->pDir = pAux->pEsq; pAux->pEsq = (*ppRaiz{‏); (*ppRaiz{‏) = pAux;}

void rsd(TNo** ppRaiz{‏){ /* para casa */}

Page 62: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 62

Rotações Duplas

int balanca_direita(TNo** ppRaiz{ int fbd = fb((*ppRaiz{‏)->pDir{‏); if(fbd < 0{‏){ rse(ppRaiz{‏); return 1; else if(fbd > 0{‏){ /* rotacao dupla esquerda */ rsd(&((*ppRaiz{‏)->pDir{‏){‏); rse(ppRaiz{‏); /* &(*ppRaiz{‏) */ return 1; } return 0;}

int balanca_esquerda(TNo** ppRaiz{‏){ /* para casa */}

Page 63: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 63

Balanceamento

int balanceamento(TNo** ppRaiz{‏){ int fb = fb(*ppRaiz{‏); if(fb > 1{‏) return balanca_esquerda(ppRaiz{‏); else if (fb < -1{‏) return balanca_direita(ppRaiz{‏); else return 0;}

Page 64: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 64

Inserção em uma Árvore AVL

● Inserção como em uma árvore binária de pesquisa

● Sempre feita expandindo um nó externo. Exemplo:

Page 65: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 65

Reestruturação Trinodo

● x, y, z (filho, pai e avô‏) renomeados como a,b,c (percurso interfixado‏)

● rotações levam b para o topo

Caso 1: rotação simples à esquerda

Caso 2: rotação dupla à esquerda

(outros dois casos são simétricos‏)

Page 66: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 66

Exemplo de inserção (cont.‏)

88

44

17 78

32 50

48 62

2

5

1

1

3

4

2

1

54

1

T0 T2

T3

x

y

z

2

34

5

67

1

T1

88

44

17

7832 50

48

622

4

1

1

2 2

3

154

1

T 0 T1

T2

T3

x

y z

123

4

5

6

7

Desbalanceado

Balanceado

Page 67: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 67

Inserção

int insere(TNo** ppRaiz, TRegistro* x{‏){ if (*ppRaiz == NULL{‏){ *ppRaiz=(Tno*{‏)malloc(sizeof(TNo{‏){‏); (*ppRaiz{‏)->reg = *x; (*ppRaiz{‏)->pEsq = NULL; (*ppRaiz{‏)->pDir = NULL; return 1; }else if((*ppRaiz{‏)->reg.chave > x->chave{‏){ if(insere(&(*ppRaiz{‏)->pEsq,x{‏){‏){ if(balanceamento(ppRaiz{‏){‏) return 0; else return 1; } }

else if((*ppRaiz{‏)->reg.chave < x->chave{‏){ if(insere(&(*ppRaiz{‏)->pDir, x{‏){‏){ if(balanceamento(ppRaiz{‏) return 0; else return 1; }else return 0; }else return 0; /* valor já presente */}

Page 68: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 68

Implementação de Inserção

● Cálculo de fatores de balanceamento

– Custo: O(log n‏) ??

● Como melhorar?

– Cada nó: ● Fator de balanceamento● Profundidade x Altura

● Problema: atualizar dados durante rotações

Page 69: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 69

Remoção em uma árvore AVL

● Remoção em uma árvore binária de busca pode causar desbalanceamento. Exemplo:

Page 70: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 70

Rebalanceamento após uma remoção

● Seja z o primeiro nó desbalanceado encontrado acima de w. Seja y o filho de z com maior altura, e x o filho de y com maior altura.

● Executar restructure(x‏) para rebalancear z.

● Pode ocorrer desbalanceamento de outro nó acima, continuar verificação de balanceamento até à raiz.

Page 71: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 71

Remoção

int remove (TNo** ppRaiz, Registro* pX{‏){ if(*ppRaiz == NULL{‏) return 0; else if ((*ppRaiz{‏)->reg.chave == pX->chave{‏){ *pX = (*ppRaiz{‏)->reg; antecessor(ppRaiz, &((*ppRaiz{‏)->pEsq{‏){‏); balanceamento(ppRaiz{‏); return 1; }else if((*ppRaiz{‏)->reg.chave > pX->chave{‏){ if(remove((*ppRaiz{‏)->pEsq, pX{‏){‏){ balanceamento(ppRaiz{‏); return 1; }else return 0; }else /* código para sub-árvore direita */}

Page 72: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 72

Tempos de execução para árvores AVL

● uma única reestruturação é O(1‏)

– usando uma árvore binária implementada

– com estrutura ligada

● pesquisa é O(log n‏)

– altura de árvore é O(log n‏), não necesita reestruturação

● inserir é O(log n‏)

– busca inicial é O(log n‏)

– reestruturação para manter balanceamento é O(log n‏)

● remove é O(log n‏)

– busca inicial é O(log n‏)

– reestruturação para manter balanceamento é O(log n‏)

Page 73: Pesquisa em Memória Primária - WordPress.com · 2019. 11. 20. · Bruno Hott 3 Introdução – Conceitos Básicos Estudo de como recuperar informação a partir de uma grande massa

Bruno Hott 73

Verificação

int eh_arvore_avl(TNo* pRaiz{‏){ int fb; if(pRaiz == NULL{‏) return 1;

if(!eh_arvore_avl(pRaiz->pEsq{‏){‏) return 0; if(!eh_arvore_avl(pRaiz->pDir{‏){‏) return 0;

fb = fb(pRaiz{‏); if( (fb > 1{‏) || (fb < -1{‏) {‏) return 0; else return 1;}