Árvores Binárias. 16/11 Representação e Implementação: Encadeada Dinâmica O TAD

Documentos relacionados
Árvores Binárias. 9/11 e 11/11 Conceitos Representação e Implementação

Árvores & Árvores Binárias

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

Árvores & Árvores Binárias

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

Árvores & Árvores Binárias

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

Árvores Binárias de Busca (ABB) 18/11

ÁRVORES ABB (ÁRVORES BINÁRIAS DE BUSCAS) Sérgio Carlos Portari Júnior

Aula 08. Estruturas de dados Árvore e Grafo

Árvores. Listas e árvores. Árvores. Árvores. Árvores. Árvores 03/11/2011. Listas lineares

Árvores Binárias de Busca (ABB) 18/11

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

INF 1010 Estruturas de Dados Avançadas. Árvores binárias

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

Árvores. Prof. César Melo DCC/ICE/UFAM

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

Árvore Binária de Busca. Prof. César Melo

ÁRVORES E ÁRVORE BINÁRIA DE BUSCA

Estruturas de Dados. Módulo 17 - Busca. 2/6/2005 (c) Dept. Informática - PUC-Rio 1

Árvores. Prof. César Melo DCC/ICE/UFAM

Árvores Binária de Busca. Prof. César Melo DCC/ICE/UFAM

Estrutura de Dados. Carlos Eduardo Batista. Centro de Informática - UFPB

Programação II. Árvores Binárias (Binary Trees) Bruno Feijó Dept. de Informática, PUC-Rio

Prof. Jesus José de Oliveira Neto

Árvores. Sérgio Carlos Portari Júnior

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

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

Pilhas e Filas Encadeadas. Algoritmos e Estruturas de Dados I

Árvores binárias de busca

ÁRVORE BINÁRIA DE BUSCA

DAINF - Departamento de Informática

ESTRUTURA DE DADOS. Árvores, árvores binárias e percursos. Cristina Boeres

AED2 - Aula 04 Vetores ordenados e árvores de busca

Métodos Computacionais. Árvores

Árvore binária - definição

Universidade Federal de Mato Grosso Estrutura de Dados II

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

Árvore Binária Exemplo de Implementação

CES-11. Algoritmos e Estruturas de Dados. Carlos Alberto Alonso Sanches Juliana de Melo Bezerra

Árvores. Prof. César Melo ICOMP/UFAM

Estruturas de Dados Aula 16: Árvores com Número Variável 13/06/2011

Listas: a última das 3 estruturas lineares (Pilhas, Filas e Listas)... árvores e grafos são não lineares!

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

UFJF - DCC - Estrutura de Dados e Laboratório de Programação II

ESTRUTURA DE DADOS DCC013. Árvore Binária de Busca

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

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

EAD Árvore - representação usando listas ligadas

Árvores binárias de busca

Árvores. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

Arvores, Percursos não recursivos, Arvores heterogêneas. Aula 19

Aula T13 BCC202 Árvores. Túlio Toffolo

INF 1620 P2-01/11/03 Questão 1 Nome:

ÁRVORE BINÁRIA DE BUSCA TDA-ABB

Bruno Hott Algoritmos e Estruturas de Dados I DECSI UFOP. Aula 08: Árvores

ÁRVORES. Prof. Yan ndre Maldonado - 1. Prof. Yandre Maldonado e Gomes da Costa

LISTAS ENCADEADAS OU NÃO- SEQÜENCIAIS. Estrutura de Dados

DATA STRUCTURES, AN ADVANCED APPROACH USING C

Arvores binárias. Fonte: PF 14 pf/algoritmos/aulas/bint.html

INF 1620 P2-23/10/04 Questão 1 Nome:

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

Pesquisa em Memória Primária Árvores de Busca. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

Estrutura de Dados II. Prof. Sérgio Portari

INF1007: Programação 2 10 Árvores Binárias. (c) Dept. Informática - PUC-Rio 1

Métodos Computacionais. Listas Encadeadas

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

EAD ARVORE BINÁRIA - ARMAZENAMENTO NÃO SEQUENCIAL COM VETORES

CES-11. Algoritmos e Estruturas de Dados. Árvores Operações sobre uma árvore Estruturas para armazenar árvores

Linguagem C: Árvores Binarias

INF1010 Lista de Exercícios 2

Estrutura de Dados. Carlos Eduardo Batista. Centro de Informática - UFPB

INF 1007 Programação II

Estruturas de Dados II

Algoritmos e Estruturas de Dados Prof. Osório PIP/CA - Aula 05 Pag.: 1

Universidade Federal de Mato Grosso

Árvores Binárias de Busca

Listas - Outras. Listas Circulares Nós Cabeça Listas Duplamente Ligadas/Encadeadas Aplicações

1. Listas sequenciais versus listas ligadas. Lista sequencial

Programação II. Listas Encadeadas (Linked Lists) Bruno Feijó Dept. de Informática, PUC-Rio

Aula 14 Listas Duplamente Encadeadas. prof Leticia Winkler

INF PROGRAMAÇÃO II LISTA DE EXERCÍCIOS 15

GGI026 - Árvore rubro-negra - Remoção

Instituto de C. Linguagem C: Listas. Luis Martí Instituto de Computação Universidade Federal Fluminense -

Árvores, Árvores Binárias e Árvores Binárias de Pesquisa. Rui Jorge Tramontin Jr.

Listas (Parte 1) Túlio Toffolo BCC202 Aula 09 Algoritmos e Estruturas de Dados I

Árvores Binárias. Algoritmos e Estruturas de Dados Flavio Figueiredo (

Árvores Binárias de Busca

Listas: nós de cabeçalho, listas não homogêneas, listas generalizadas

UNIVERSIDADE DE SÃO PAULO ICMC SCC 202 Algoritmos e Estrutura de Dados I - 2º Semestre 2010 Profa. Sandra Maria Aluísio;

ÁRVORES E ÁRVORES BINÁRIAS. Adaptado de Alexandre P

Á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

Listas: nós de cabeçalho, listas não homogêneas, listas generalizadas. SCC-502 Algoritmos e Estruturas de Dados I

Estruturas de Dados. Parte dos slides a seguir são adaptações, extensões e recodificações em C dos originais:

void ins_ele (ARV_BIN_BUSCA *arv, int v) { if (!(*arv)) maketree(arv, v); else if (v<info(*arv)) /* if (v<(*arv)->info) */ ins_ele(&((*arv)->left),

EAD ARVORE BINÁRIA - ARMAZENAMENTO NÃO SEQUENCIAL COM VETORES

1. Proponha algoritmos para: a. Calcular a altura dos nós de uma árvore binária dada, armazenando o valor da altura no nó.

Transcrição:

Árvores Binárias 16/11 Representação e Implementação: Encadeada Dinâmica O TAD

ED AB, encadeada dinâmica Para qualquer árvore, cada nó é do tipo info esq dir typedef int elem; typedef struct arv *Arv; AB.h a a RAIZ struct arv { elem info; b c b c }; struct arv* esq; struct arv* dir; AB.c e g e g 2/40

Árvore binária Operações do TAD 1. Criação de uma árvore Dois casos: seguindo a definição recursiva 1. Criar uma árvore vazia 2. Criar uma árvore com 2 subárvores (e,d): faz o papel de inserir nó 2. Verificar se árvore está vazia, mostrar o conteúdo do nó 3. Buscar o pai de um nó, buscar um nó 4. Retornar: nro de nós, nro de folhas, altura 5. Destruir árvore 6. Remover um nó Dois casos: 1. O nó não tem filhos 2. O nó tem um filho a esq, ou a dir ou os dois 7. Verificar nível de um nó 8. Verificar se é balanceada, se é perfeitamente balanceada Outras? 3/40

Operações com resolução similar: usam percursos Operações do TAD 1. Criação de uma árvore Dois casos: seguindo a definição recursiva 1. Criar uma árvore vazia 2. Criar uma árvore com 2 subárvores (e,d): faz o papel de inserir nó 2. Verificar se árvore está vazia, mostrar o conteúdo do nó 3. Buscar o pai de um nó, buscar um nó 4. Retornar: nro de nós, nro de folhas, altura 5. Destruir árvore 6. Remover um nó Dois casos: 1. O nó não tem filhos 2. O nó tem um filho a esq, ou a dir ou os dois 7. Verificar nível de um nó 8. Verificar se é balanceada, se é perfeitamente balanceada Imprime

Interface para as funções do TAD typedef int elem; // Tipo exportado typedef struct arv *Arv; // Cria uma árvore vazia Arv arv_criavazia (void); // Cria uma árvore com uma raiz e duas subárvores Arv arv_cria (elem c, Arv e, Arv d); //Libera toda a memória usada na árvore a Arv arv_destroi (Arv a); // Imprime a lista a void arv_imprime (Arv a); 5/40

// Verifica se a árvore a é vazia int arv_vazia (Arv a); // Retorna o conteúdo de um nó x na árvore a elem arv_mostra_no(arv a, int *erro); //Retorna (busca) o endereço de c na árvore a. Se c não está, retorna NULL Arv arv_busca (Arv a, elem c); // Retorna (busca) o endereço do pai de x na árvore a Arv arv_busca_pai(arv a, elem x); //Remove um elemento da árvore, caso ele esteja nela. Retorna erro = 0 se sucesso e erro = 1 se não encontra void arv_remove(arv a, elem x, int *erro); 6/40

//Retorna a altura de uma árvore binária a. Considera o nível da raiz = 1 int arv_altura(arv a); // Retorna o número de nós na árvore a int arv_numero_nos(arv a); //Retorna o número de folhas da árvore a int arv_nro_folhas(arv a); //função de percurso de pre-ordem na árvore = busca em profundidade void arv_percurso_pre_ordem(arv a); //função de percurso de em-ordem na árvore void arv_percurso_em_ordem(arv a); //função de percurso de pos-ordem na árvore void arv_percurso_pos_ordem(arv a); 7/40

AB - Percursos Objetivo: Percorrer uma AB visitando cada nó uma única vez. Um percurso gera uma seqüência linear de nós, e podemos então falar de nó predecessor ou sucessor de um nó, segundo um dado percurso. Não existe um percurso único para árvores (binárias ou não): diferentes percursos podem ser realizados, dependendo da aplicação. Utilização: imprimir uma árvore, atualizar um campo de cada nó, buscar um item, destruir uma árvore, etc. 8/40

AB Percursos em Árvores 3 percursos básicos para AB's: pré-ordem (Pre-order) in-ordem (In-order) pós-ordem (Post-order) A diferença entre eles está, basicamente, na ordem em que cada nó é alcançado pelo percurso Visitar um nó pode ser: Mostrar (imprimir) o seu valor; Modificar o valor do nó; Verificar se o valor pertence a árvore (membro) 9/40

Pré-ordem se árvore vazia; fim 1. visitar o nó raiz 2. percorrer em pré-ordem a subárvore esquerda 3. percorrer em pré-ordem a subárvore direita 10/40

AB - Percurso Pré-Ordem void arv_percurso_pre_ordem(arv a) { if (!arv_vazia(a)) { A printf("%d\n",a->info); // processa raiz arv_percurso_pre_ordem(a->esq); arv_percurso_pre_ordem(a->dir); B C } } D E F G H I Resultado: ABDGCEHIF 11/40

E se invertermos as chamadas recursivas? Trocar pre_ordem(a->esq); pre_ordem(a->dir); POR: pre_ordem(a->dir); pre_ordem(a->esq); Ainda é pré-ordem?? 12/40

In-Ordem se árvore vazia, fim 1. percorrer em in-ordem a subárvore esquerda 2. visitar o nó raiz 3. percorrer em in-ordem a subárvore direita 13/40

AB - Percurso In-Ordem void arv_percurso_em_ordem(arv a) { if (!arv_vazia(a)) { arv_percurso_em_ordem(a->esq); printf("%d\n",a->info); // processa raiz arv_percurso_em_ordem(a->dir); } } B A C D E F Resultado: DGBAHEICF G H I 14/40

E se invertermos as chamadas recursivas? Ainda é in-ordem? Qual o resultado para a árvore abaixo? I O I U H V D N A 15/40

Pós-ordem se árvore vazia, fim 1. percorrer em Pós-Ordem a subárvore esquerda 2. percorrer em Pós-Ordem a subárvore direita 3. visitar o nó raiz 16/40

AB - Percurso Pós-Ordem void arv_percurso_pos_ordem(arv a) { if (!arv_vazia(a)) { arv_percurso_pos_ordem(a->esq); arv_percurso_pos_ordem(a->dir); printf("%d\n",a->info); //processa raiz } } B A C D E F Resultado: GDBHIEFCA G H I 17/40

E se invertermos as chamadas recursivas? Ainda é pós-ordem? 18/40

Procedimento recursivo p/ destruir árvore, liberando o espaço alocado Usar percurso em pós-ordem Arv arv_destroi (Arv a) 19/40

Procedimento recursivo p/ destruir árvore, liberando o espaço alocado (percurso em pósordem) Porque não usamos pré ou in-ordem para esta tarefa??? Arv arv_destroi (Arv a) { if (!arv_vazia(a)) { arv_destroi(a->esq); /* libera sae */ arv_destroi(a->dir); /* libera sad */ free(a); /* libera raiz */ } return NULL; } 20/40

Função para verificar se valor está na árvore //Retorna (busca) o endereço de c na árvore a. Se c não está retorna NULL Arv arv_busca (Arv a, elem c) 21/40

Função para verificar se valor está na árvore Arv arv_busca (Arv a, elem c) { Arv aux; if (arv_vazia(a)) return NULL; /* árvore vazia: não encontrou */ else if (a->info==c) return a; else { aux = arv_busca(a->esq,c); /* busca na sae */ if (aux == NULL) aux = arv_busca(a->dir,c); /* busca na sad */ return aux; } } 22/40

Função para retornar o endereço do pai de um nó com elemento x // Retorna (busca) o endereço do pai de x na árvore a. Retorna NULL se for nula, tiver só raiz ou não achou o elemento x Casos: 1. Se a árvore é nula ou só tem raiz devolve NULL 2. Se tem filho à esquerda e é x devolve raiz 3. Se tem filho à direita e é x devolve raiz 4. Senão chama recursivamente à esquerda e se não achou chama recursivamente à direita Arv arv_busca_pai(arv a, elem x); 23/40

Arv arv_busca_pai(arv a, elem x) { Arv aux; if (arv_vazia(a)) // árvore vazia return(null); else if (a->esq == NULL && a->dir == NULL) // só tem raiz return(null); else if ((a->esq!=null) && (a->esq->info==x)) return(a); else if ((a->dir!=null) && (a->dir->info==x)) return(a); else { aux=arv_busca_pai(a->esq,x); if (aux==null) aux=arv_busca_pai(a->dir,x); return(aux); } } 24/40

TAD Arv arv_criavazia (void) { return NULL; } Arv arv_cria (elem c, Arv sae, Arv sad) { Arv p=(arv)malloc(sizeof(struct arv)); p->info = c; p->esq = sae; p->dir = sad; return p; } 25/40

int arv_vazia (Arv a) { return a==null; } 26/40

Exercício Mostra o conteúdo do nó Retornar o nro de nós Retornar o nro de folhas 27/40

Mostra o conteúdo do nó elem arv_mostra_no(arv a, int *erro){ *erro = 0; if (!arv_vazia(a)) return a->info; else *erro = 1; } 28/40

Função para retornar o número de nós int arv_numero_nos(arv a){ if (arv_vazia(a)) return 0; return 1 + arv_numero_nos(a->esq) + arv_numero_nos(a->dir); } 29/40

Função para retornar o nro de folhas int arv_nro_folhas(arv a){ if (arv_vazia(a)) return 0; else if ((a->esq == NULL) && (a->dir == NULL)) return 1; // definição de nó folha else return arv_nro_folhas(a->esq) + arv_nro_folhas(a->dir); } 30/40

Altura (considerando que o nível da raiz é 0) pré-condição: Árvore binária já tenha sido criada pós-condição: retorna a altura da árvore A definição de altura de uma árvore nos leva aos seguintes casos: Caso base: a altura de uma árvore vazia é -1 (por definição a altura das folhas é 0; portanto parece natural adotar -1 como a altura de uma árvore vazia) Caso recursivo: a altura de uma árvore que contém um nó (não nulo) é determinada como sendo a maior altura entre as subárvores esquerda e direita deste nó adicionado a um (uma unidade a mais de altura devido ao próprio nó) 31/40

Altura considerando o nível da raiz = 0 int arv_altura(arv a) { int alt_esq, alt_dir; /*altura = max(alte, altd) + 1*/ if (arv_vazia(a)) return -1; else { alt_esq = 1+ arv_altura(a->esq); alt_dir = 1+ arv_altura(a->dir); if (alt_esq > alt_dir) return(alt_esq); else return(alt_dir); } } 32/40

Altura considerando o nível da raiz = 1 //segue as nossas definições int arv_altura(arv a) { int alt_esq, alt_dir; /*altura = max(alte, altd) + 1*/ if (arv_vazia(a)) return 0; else { alt_esq = 1+ arv_altura(a->esq); alt_dir = 1+ arv_altura(a->dir); if (alt_esq > alt_dir) return(alt_esq); else return(alt_dir); } } 33/40

Exercício: Remover um nó //Remove um elemento da árvore, caso ele esteja nela. Retorna erro = 0 se sucesso e erro = 1 se não encontra void arv_remove(arv a, elem x, int *erro); Dois casos: 1. O nó não tem filhos 2. O nó tem um filho a esq, ou a dir ou os dois 34/40

Passos 1) Localize o pai do nó p (que contém x) // caso 1: só tem raiz e o x está nela // caso 2: não tem pai: árvore nula ou x não está na árvore // caso 3: o x está a esquerda do pai // caso 4: o x está a direita do pai 2) O nó não tem filhos: Remova o nó 3) O nó tem um filho a esq, ou a dir ou os dois: Troque o conteúdo de p com o do seu filho a esquerda/direita e chame novamente a função para trazer o x para as folhas

AB Percursos Percurso para expressões aritméticas + a * b c Pré-ordem: +a*bc In-ordem: a+(b*c) Pós-ordem: abc*+ Em algoritmos iterativos utiliza-se uma pilha ou um campo a mais em cada nó para guardar o nó anterior (pai) 36/40

Conclusões O processo de busca de informação em uma árvore binária como vimos até agora é caro. Se as chaves não estão em uma ordem préestabelecida, toda a estrutura precisa ser percorrida para encontrar uma determinada chave (no pior caso),o que não seria eficiente Veremos uma forma de melhorar o tempo de busca, utilizando Árvores Binárias de Busca 37/40

Percurso em árvores Outras formas/nomenclaturas Busca/percurso em largura Busca/percurso em profundidade Independente do tipo de árvore Tradicionalmente da esquerda para a direita

Percurso em árvores Em largura Um nível de cada vez

Percurso em árvores Em profundidade Um ramo da árvore de cada vez (=???)

Percurso em árvores Em profundidade Um ramo da árvore de cada vez (= pré-ordem)

Exercício: percurso em árvores Para a árvore abaixo, mostre quais seriam as saídas para os percursos em largura, profundidade (pré-ordem), em-ordem e pósordem

Percurso em árvores Em profundidade = pré-ordem Usa pilha (explicita ou implicitamente)

Percurso em árvores Teste a estratégia com a pilha explícita

Percurso em árvores Em largura Como implementar?

Percurso em árvores Em largura FILA Se o nó raiz for diferente de NULL, ele entra na fila Enquanto fila não vazia Retira-se/visita-se o primeiro da fila Se houver filhos desse nó, eles entram na fila

Percurso em árvores Teste a estratégia

Largura vs. profundidade Ao buscar um elemento Profundidade Vantagens? Desvantagens?

Largura vs. profundidade Ao buscar um elemento Profundidade Menos memória para guardar nós não visitados Pode buscar para sempre, demorando mais para achar o elemento

Largura vs. profundidade Ao buscar um elemento Largura Vantagens? Desvantagens?

Largura vs. profundidade Ao buscar um elemento Largura Acha o elemento mais rapidamente Mais memória para guardar nós não visitados

Largura vs. profundidade Use as estratégias para buscar o nó F Quem se sai melhor em termos de nós visitados e de memória?

Percurso em árvores Árvores encadeadas Mais ponteiros, mas pode facilitar busca e outras operações Ponteiros podem ser configurados para qualquer tipo de busca Filhos podem apontar para pais, para irmãos, para avôs, etc. A B C D E F G H I J K L M N

Exercícios 1) Função recursiva para verificar se uma AB é balanceada (usa a função altura) 4 Casos: 1) Se for nula ou tiver só a raiz: balanceada 2) Árvore tem as 2 subárvores não nulas: É balanceada se a diferença entre as alturas esq e dir for (0 ou 1 ou -1) e a sae for balanceada e a sad for balanceada 3. Se tem a sae não nula: é balanceada se a altura desta for 1 4. Se tem a sad não nula: é balanceada se a altura desta for 1 54/40

Exercícios 2) Função recursiva para verificar se uma AB é perfeitamente balanceada (usa a função nro_nós) 4 Casos: 1) Se for nula ou tiver só a raiz: perf. balanceada 2) Árvore tem as 2 subárvores não nulas: É perf. balanceada se a diferença entre nro_nós esq e dir for (0 ou 1 ou -1) e a sae for perf. balanceada e a sad for perf. balanceada 3. Se tem a sae não nula: é perf. balanceada se o nro_nós desta for 1 (tem um único filho a esq) 4. Se tem a sad não nula: é perf. balanceada se o nro_nós desta for 1 (tem um único filho a direita) 55/40

Exercícios 3) Função para calcular o nível de um nó. Dado o valor de um elemento, se ele está na árvore, retorna seu nível, retorna NULL c.c. OBS.: Nivel da raiz = 1*/ /*percorre a árvore com raiz em a em Pré-ordem, procurando pelo item dado e calculando e retornando seu nível na variável n*/ 56/40