Algoritmos e Estruturas de Dados: Árvore Binária



Documentos relacionados
Algoritmos e Estruturas de Dados: Árvore Binária de Busca

Algoritmos e Estruturas de Dados: Lista Duplamente Encadeada

Estruturas de Dados. Prof. Gustavo Willam Pereira Créditos: Profa. Juliana Pinheiro Campos

EAD Árvore árvore binária

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

ALGORITMOS E ESTRUTURAS DE DADOS CES-11 CES-11 CES-11

Métodos Computacionais. Árvores

- UNIVERSIDADE DO VALE DO RIO DOS SINOS CIÊNCIAS EXATAS E TECNOLÓGICAS Curso: Informática / Ciência da Computação

DAS5102 Fundamentos da Estrutura da Informação

Linguagem C: Árvores Binarias

INF 1007 Programação II

PROGRAMAÇÃO II 4. ÁRVORE

Algoritmos e Estruturas de Dados: Tabela de Dispersão com Encadeamento

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

Algoritmos e Estruturas de Dados: Heap

1. Introdução Definição Conceitos relacionados... 2

Árvores e Árvores Binárias

2ª Lista de Exercícios

Árvores Binárias de Busca

EAD Árvore - representação usando listas ligadas

Árvore Binária de Busca

Figura 13.1: Um exemplo de árvore de diretório.

Busca. Pesquisa sequencial

Estruturas de Dados Aula 15: Árvores 17/05/2011

Prof. Yandre Maldonado - 1 PONTEIROS. Prof. Yandre Maldonado e Gomes da Costa

ESTRUTURAS DE DADOS I. Notas de Aula. Prof. Dr. Gilberto Nakamiti

Árvores Binárias - continuação

DAS5102 Fundamentos da Estrutura da Informação

Árvores Binárias de Busca

Árvores. Algoritmos e Estruturas de Dados 2005/2006

Estruturas de Dados I

BUSCA EM LISTAS LISTAS SEQÜENCIAIS, LISTAS SIMPLESMENTE E DUPLAMENTE ENCADEADAS E LISTAS CIRCULARES

- UNIVERSIDADE DO VALE DO RIO DOS SINOS CIÊNCIAS EXATAS E TECNOLÓGICAS Curso: Informática / Ciência da Computação

Árvores Binárias de Pesquisa. Programação II Prof. Mateus Raeder. Árvores Binárias de Pesquisa. Árvores Binárias de Pesquisa. Classe Nodo Binário

Pesquisa em Memória Primária. Prof. Jonas Potros

Trabalho 3: Agenda de Tarefas

Pesquisa em Memória Primária. Algoritmos e Estruturas de Dados II

FACULDADE CAMPO LIMPO PAULISTA MESTRADO EM CIÊNCIA DA COMPUTAÇÃO. Projeto e Análise de Algoritmos II Lista de Exercícios 2

Tipos de Dados, Tipos Abstratos de Dados Estruturas de Dados

Algoritmos e Estrutura de Dados III. Árvores

Algoritmos e Estrutura de Dados II

Árvores AVL. Prof. Othon M. N. Batista Estrutura de Dados

Algoritmos e Estruturas de Dados 2

ESTRUTURAS DE DADOS II MSc. Daniele Carvalho Oliveira

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Estruturas de Dados Árvores

Complexidade de Algoritmos

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

Estruturas de Dados Aula 11: TAD Pilha 09/05/2011

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

Mo:vação. Árvore AVL. Caracterís:cas. Origem. Exemplo. Exercício 1 Qual é a altura dos nodos 50 e 44?

BC1424 Algoritmos e Estruturas de Dados I. Aula 16: Árvores (introdução) Prof. Jesús P. Mena-Chalco. jesus.mena@ufabc.edu.br

Pesquisa Sequencial e Binária

- UNIVERSIDADE DO VALE DO RIO DOS SINOS CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS (C6/6) Curso: Informática

Aula 3 Alocação Dinâmica

Árvores Balanceadas. Árvore binária completamente balanceada. Ocorre quando a árvore está cheia ou quase cheia com o nível n-1 completo

Busca em Memória. Secundária

ESTRUTURAS DE DADOS AVANÇADAS (INF 1010) (a) Seja um TAD definido por uma lista circular implementada em um vetor.

- UNIVERSIDADE DO VALE DO RIO DOS SINOS CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS (C6) Curso: Informática

Árvores Binárias Balanceadas

Orientação a Objetos

struct arv { char info; struct arv* esq; struct arv* dir; };

PROGRAMAÇÃO II 3. PILHA DINÂMICA

Persistência de Dados

Estrutura da linguagem de programação C Prof. Tiago Eugenio de Melo tiago@comunidadesol.org

Estruturas de Dados. Árvores AVL. Cesar Tadeu Pozzer. Curso de Ciência da Computação UFSM (12/12/2007)

Programas operam sobre dados. Dados são relacionados e possuem estrutura. Como representar e manipular dados em um computador

Algoritmos e Estruturas de Dados

AED 2002/2003 p.1/21. Estrutura de dados elementar Métodos de travessia de árvores Procura em árvores binárias. Exemplos de clientes

Algoritmos e Estrutura de Dados. Prof. Tiago A. E. Ferreira

PROGRAMAÇÃO II 3. FILA DINÂMICA

Árvores de Suporte de Custo Mínimo

Árvores binárias de pesquisa com balanceamento. Algoritmos e Estruturas de Dados II

Algoritmos e Estruturas de Dados II. Trabalho Prático 2

Árvores Binárias. Observação: Material elaborado a partir do material do Professor Marcos Costa.

ESTRUTURA DE DADOS DCC013

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

DEPARTAMENTO DE ENGENHARIA INFORMÁTICA FACULDADE DE CIÊNCIAS E TECNOLOGIA DA UNIVERSIDADE DE COIMBRA

ESTRUTURA DE DADOS PILHA

Pilhas. Profa Morganna Diniz

Métodos Computacionais. Fila

Estrutura de Dados. Introdução a Ponteiros. Prof. Gerson Borges Estrutura de Dados I 1

1.6. Tratamento de Exceções

Introdução a Java. Hélder Nunes

Fila de Prioridade. Siang Wun Song - Universidade de São Paulo - IME/USP. MAC Estruturas de Dados

Projeto 1: Aprovação de Transação de Cartão de Crédito

Introdução a Programação. Ponteiros e Strings, Alocação Dinâmica

Sumário. 5COP096 Teoria da Computação Aula 8 Pesquisa em Memória Primária

Hashing. Rafael Nunes LABSCI-UFMG

Pedro Vasconcelos DCC/FCUP. Programação Funcional 15 a Aula Árvores de pesquisa

Algoritmos de pesquisa. Tabelas de dispersão/hash

Números positivos ordenados

Estruturas de Dados. Listas Dinâmicas Duplamente Encadeadas & Variantes. Listas Duplamente Encadeadas

{ fazer Pós-Ordem sem recursividade. Poderá cair na prova!!! }

Pesquisa em Memória Primária. Prof. Jonas Potros

Unidade IV: Ponteiros, Referências e Arrays

Transcrição:

Algoritmos e Estruturas de Dados: Árvore Binária Exemplo de árvore binária e são os filhos de Altura desta árvore é 4 é a raiz da sub-árvore esquerda de Rômulo Silva de Oliveira Departamento de Automação e Sistemas DAS UFSC romulo@das.ufsc.br http://www.das.ufsc.br/~romulo Maio/11 1 4 Mastering Algorithms with C Kyle Loudon O Reilly, 1999 Livros de algoritmos e estruturas de dados em geral Referências Cada nodo da árvore binária contem: Dados Pointer para nodo filho da esquerda Pointer para nodo filho da direita Caso não tenha um filho, NULL é usado para indicar isto Uma sub-árvore pode ser identificada pelo seu nodo raiz Um conjunto de árvores é uma floresta 2 5 Em computação, uma árvore consiste de elementos chamados nodos organizados hierarquicamente Nodo no topo é a raiz Os nodos imediatamente abaixo de um certo nodo s ão seus filhos Os quais podem ter seus próprios filhos Com exceção da raiz, cada nodo tem exatamente um nodo pai O número de filhos que um nodo pode ter depende do tipo da árvore Branching factor Árvores binárias (binary tree) Branching factor é 2 Relativamente simples porém poderosas 3 Métodos de Caminhamento Caminhar sobre a árvore significa visitar todos os nodos Visitar significa acessar o nodo de alguma forma O método de caminhamento define a ordem das visitas No caso de uma lista encadeada não existem muitas opções Mas existem várias opções no caso de uma árvore Métodos mais usuais: Pré-ordem Em-ordem Pós-ordem Por nível Podem ser usados para outros tipos de árvores também 6

Método de Caminhamento: Pré-Ordem, Esquerda, Direita,,,, 25, 42,, 60, 59, 65,, 72, 89 Método de Caminhamento: Por Nível, e depois todos os do nível abaixo, e assim por diante,,,,42,60,,,25,59,65,72,89 7 10 Método de Caminhamento: Em-Ordem Esquerda,, Direita, 02, 25,, 42,, 59, 60, 65,, 72,, 89 Balançeamento Balançear a árvore significa deixa-la com a menor altura poss ível, para um dado número de nodos Um nível precisa estar cheio para ser criado o nível de baixo Uma árvore binária está balanceada se a altura das duas sub- árvores de cada nodo nunca diferem por mais que 1 25 Rômulo Silva de DAS-UFSC, 8 Oliveira, maio/11 25 11 Método de Caminhamento: Pós-Ordem Esquerda, Direita,, 25,, 42,, 59, 65, 60, 72, 89,,, Rômulo Silva de DAS-UFSC, 9 Oliveira, maio/11 bitree_init Árvore Binária Interface 1/14 void bitree_init(bitree *tree, void (*destroy)(void *data)); Inicializa uma árvore binária especificada por tree. Esta operação deve ser chamada para uma árvore binária antes de qualquer operação. O argumento destroy provê uma maneira para liberar dados dinamicamente alocados quando bitree_destroy é chamada. Por exemplo, se a árvore contem dados dinamicamente alocados usando malloc, destroy deveria ser associada com free para liberar os dados quando a árvore binária for destruida. Para dados estruturados contendo diversos membros alocados dinamicamente, destroy deveria ser associada com uma fun ção definida pelo usuário a qual chama free para cada membro alocado dinamicamente assim como para a estrutura ela própria. Para uma árvore binária contendo dados que não devem ser liberados, destroy deve ser NULL. 12

bitree_destroy void bitree_destroy(bitree *tree); Árvore Binária Interface 2/14 Destrói a árvore binária especificada por tree. Nenhuma outra operação é permitida após a chamada de bitree_destroy a não ser que bitree_init seja chamada novamente. A operação bitree_destroy remove todos os nodos de uma árvore binária e chama a função passada como destroy para bitree_init uma vez para cada nodo quando o mesmo é removido, desde que destroy não seja NULL. bitree_rem_left Árvore Binária Interface 5/14 void bitree_rem_left(bitree *tree, BiTreeNode *node); Remove a subárvore cuja raiz é o filho esquerdo de node da árvore binária especificada por tree. Se node for NULL, todos os nodos da árvore são removidos. A função passada como destroy para bitree_init é chamada uma vez para cada nodo que é removido, desde que destroy não seja NULL. 13 16 bitree_ins_left Árvore Binária Interface 3/14 int bitree_ins_left(bitree *tree, BiTreeNode *node, const void *data); 0 se a inserção do nodo tiver sucesso, ou -1 caso contrário. Insere um nodo como o filho da esquerda do nodo node na árvore binária especificada por tree. Se node já tem um filho esquerdo, bitree_ins_left retorna -1. Se node for NULL, o novo nodo é inserido como o nodo raiz. A árvore deve estar vazia para ser possível inserir um nodo como o nodo raiz; caso contr ário, bitree_ins_left retorna -1. Quando sucesso, o novo nodo contem um pointer para od dados, logo a memória referenciada por data deve permanecer válida pelo tempo que o nodo permanecer na árvore binária. É responsabilidade do chamador gerenciar a memória associada com os dados. bitree_rem_right Árvore Binária Interface 6/14 void bitree_rem_right(bitree *tree, BiTreeNode *node); Esta operação é similar a bitree_rem_left, exceto que ela remove a sub-árvore cuja raiz é o filho direito de node da árvore binária especificada por tree. 14 17 bitree_ins_right Árvore Binária Interface 4/14 int bitree_ins_right(bitree *tree, BiTreeNode *node, const void *data); 0 se a inserção do nodo tiver sucesso, ou -1 caso contrário. Esta operação é similar a bitree_ins_left, exceto que ela insere um nodo como o filho direito de node na árvore binária especificada por tree. bitree_merge Árvore Binária Interface 7/14 int bitree_merge(bitree *merge, BiTree *left, BiTree *right, const void *data); 0 se a junção das árvores teve sucesso, ou -1 caso contrário. Junta as duas árvores binárias especificadas por left e right em uma única árvore binária merge. Após a junção estar completa, merge contem data em seu nodo raiz, e left e right são as sub-árvores esquerda e direita de sua raiz. Uma vez que as árvores foram juntadas, left e right estarão como se bitree_destroy tivesse sido chamada para elas. 15 18

bitree_size int bitree_size(const BiTree *tree); Número de nodos na árvore. Árvore Binária Interface 8/14 Macro que avalia o número de nodos na árvore binária especificada por tree. bitree_is_leaf int bitree_isleaf(const BiTreeNode *node); 1 se o nodo é uma folha, ou 0 caso contrário. Árvore Binária Interface 11/14 Macro que determina se o nodo especificado por node é uma folha na árvore binária. 19 22 bitree_root BiTreeNode *bitree_root(const BiTree * tree); Nodo na raiz da árvore. Árvore Binária Interface 9/14 Macro que obtem o nodo na raiz da árvore binária especificada por tree. bitree_data void *bitree_data(const BiTreeNode *node); Dados armazenados em um nodo. Árvore Binária Interface 12/14 Macro que obtem os dados armazenados no nodo de uma árvore binária especificado por node. 23 bitree_is_eob int bitree_is_eob(const BiTreeNode *node); 1 se o nodo marca o final de um galho, or 0 caso contr ário. Árvore Binária Interface 10/14 Macro que determina se o nodo especificado por node marca o final de um galho na árvore binária. bitree_left BiTreeNode *bitree_left(const BiTreeNode *node); Filho esquerdo da nodo especificado. Árvore Binária Interface 13/14 Macro que obtem o nodo de uma árvore binária que é o filho esquerdo de um nodo especificado por node. 21 24

bitree_right BiTreeNode *bitree_right(const BiTreeNode * node); Filho direito do nodo especificado. Árvore Binária Interface 14/14 Macro que obtem o nodo de uma árvore binária o qual é o filho direito do nodo especificado por node. Árvore Binária Header 3/3 #define bitree_size(tree) ((tree)->size) #define bitree_root(tree) ((tree)->root) #define bitree_is_eob(node) ((node) == NULL) #define bitree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL) #define bitree_data(node) ((node)->data) #define bitree_left(node) ((node)->left) #define bitree_right(node) ((node)->right) #endif 25 28 #ifndef BITREE_H #define BITREE_H #include <stdlib.h> typedef struct BiTreeNode_ { void *data; struct BiTreeNode_ *left; struct BiTreeNode_ *right; BiTreeNode; typedef struct BiTree_ { int size; int (*compare)(const void *key1, const void *key2); void (*destroy)(void *data); BiTreeNode *root; BiTree; Árvore Binária Header 1/3 26 #include <stdlib.h> #include <string.h> #include "bitree.h" Árvore Binária Implementação 1/9 void bitree_init(bitree *tree, void (*destroy)(void *data)) { tree->size = 0; tree->destroy = destroy; tree->root = NULL; 29 Árvore Binária Header 2/3 void bitree_init(bitree *tree, void (*destroy)(void *data)); void bitree_destroy(bitree *tree); int bitree_ins_left(bitree *tree, BiTreeNode *node, const void *data); int bitree_ins_right(bitree *tree, BiTreeNode *node, const void *data); void bitree_destroy(bitree *tree) { bitree_rem_left(tree, NULL); memset(tree, 0, sizeof(bitree)); Árvore Binária Implementação 2/9 void bitree_rem_left(bitree *tree, BiTreeNode *node); void bitree_rem_right(bitree *tree, BiTreeNode *node); int bitree_merge(bitree *merge, BiTree *left, BiTree *right, const void *data); 27 30

Árvore Binária Implementação 3/9 int bitree_ins_left(bitree *tree, BiTreeNode *node, const void *data) { BiTreeNode *new_node, **position; if (node == NULL) { // Allow insertion at the root only in an empty tree. if (bitree_size(tree) > 0) else { // Normally allow insertion only at the end of a branch. Árvore Binária Implementação 6/9 if ((new_node = (BiTreeNode *)malloc(sizeof(bitreenode))) == NULL) new_node->data = (void *)data; new_node->left = NULL; new_node->right = NULL; *position = new_node; tree->size++; if (bitree_left(node)!= NULL) position = &node->left; 31 34 Árvore Binária Implementação 4/9 if ((new_node = (BiTreeNode *)malloc(sizeof(bitreenode))) == NULL) new_node->data = (void *)data; new_node->left = NULL; new_node->right = NULL; *position = new_node; tree->size++; 32 void bitree_rem_left(bitree *tree, BiTreeNode *node) { BiTreeNode **position; if (bitree_size(tree) == 0) if (node == NULL) else position = &node->left; if (*position!= NULL) { bitree_rem_left(tree, *position); bitree_rem_right(tree, *position); if (tree->destroy!= NULL) tree->destroy((*position)->data); free(*position); *position = NULL; tree->size--; Árvore Binária Implementação 7/9 35 Árvore Binária Implementação 5/9 int bitree_ins_right(bitree *tree, BiTreeNode *node, const void *data) { BiTreeNode *new_node, **position; if (node == NULL) { // Allow insertion at the root only in an empty tree. if (bitree_size(tree) > 0) else { // Normally allow insertion only at the end of a branch. if (bitree_right(node)!= NULL) position = &node->right; 33 void bitree_rem_right(bitree *tree, BiTreeNode *node) { BiTreeNode **position; if (bitree_size(tree) == 0) if (node == NULL) else position = &node->right; if (*position!= NULL) { bitree_rem_left(tree, *position); bitree_rem_right(tree, *position); if (tree->destroy!= NULL) tree->destroy((*position)->data); free(*position); *position = NULL; tree->size--; Árvore Binária Implementação 8/9 36

int bitree_merge(bitree *merge, BiTree *left, BiTree *right, const void *data) { Árvore Binária Implementação 9/9 int postorder(const BiTreeNode *node, List *list) { Árvore Binária Caminhamento 3/3 bitree_init(merge, left->destroy); if (bitree_ins_left(merge, NULL, data)!= 0) { bitree_destroy(merge); bitree_root(merge)->left = bitree_root(left); bitree_root(merge)->right = bitree_root(right); merge->size = merge->size + bitree_size(left) + bitree_size(right); left->root = NULL; left->size = 0; right->root = NULL; right->size = 0; 37 if (!bitree_is_eob(node)) { if (!bitree_is_eob(bitree_left(node))) if (postorder(bitree_left(node), list)!= 0) if (!bitree_is_eob(bitree_right(node))) if (postorder(bitree_right(node), list)!= 0) if (list_ins_next(list, list_tail(list), bitree_data(node))!= 0) 40 int preorder(const BiTreeNode *node, List *list) { if (!bitree_is_eob(node)) { Árvore Binária Caminhamento 1/3 Permite várias operações interessantes Mas exige que o balaçeamento seja bom Árvore Binária Sumário if (list_ins_next(list, list_tail(list), bitree_data(node))!= 0) if (!bitree_is_eob(bitree_left(node))) if (preorder(bitree_left(node), list)!= 0) if (!bitree_is_eob(bitree_right(node))) if (preorder(bitree_right(node), list)!= 0) 38 Muitas operações ficam simples quando recursão é usada Mas exige espaço em pilha Capaz de garantir tempo de busca determinista Tabela hash fornece tempo de busca probabilista Existe o gasto de 2 pointers para cada nodo com dados 41 int inorder(const BiTreeNode *node, List *list) { if (!bitree_is_eob(node)) { if (!bitree_is_eob(bitree_left(node))) if (inorder(bitree_left(node), list)!= 0) Árvore Binária Caminhamento 2/3 if (list_ins_next(list, list_tail(list), bitree_data(node))!= 0) if (!bitree_is_eob(bitree_right(node))) if (inorder(bitree_right(node), list)!= 0)