Capítulo IV – Árvores Gerais

Slides:



Advertisements
Apresentações semelhantes
LISTAS Dilvan Moreira, parcialmente baseado em material do prof. Ricardo Campello.
Advertisements

Estruturas de Dados Árvores Binárias
Recursividade Prof. Rosana Palazon.
Listas encadeadas Prof. Rosana Palazon.
Listas duplamente encadeadas
Programação II Estruturas de Dados
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
David Menotti Estruturas de Dados I DECOM – UFOP
Pesquisa em Memória Primária – Árvores de Busca
David Menotti Algoritmos e Estruturas de Dados I DECOM – UFOP
Estruturas de Dados I Prof.: Sergio Pacheco Prof.: Sergio Pacheco 1 1.
Listas com Ponteiros Listas encadeadas Listas circulares.
Lista Encadeada Circular Lista Duplamente Encadeada
Listas Encadeadas.
ALGORITMOS E ESTRUTURAS DE DADOS
exercícios listas encadeadas
Listas Encadeadas Raquel O. Prates, Luiz Chaimowicz, Jussara Almeida
Pesquisa em Memória Primária
Denise Guliato Faculdade de Computação – UFU
Árvores Binárias de Pesquisa
Implementação de FILAS com Alocação Dinâmica
Lista Encadeada Circular Lista Duplamente Encadeada
Algorítmos e estrutura de dados III Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Denise Guliato Faculdade de Computação – UFU
Estruturas de Dados Aula 11: TAD Pilha
Árvore Binária de Busca
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática Disciplina: Estrutura de Dados Professor: Cheli dos S. Mendes da Costa Listas.
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática
Estruturas de Dados Aula 17: Estruturas Genéricas
Estruturas de Dados Aula 7: Tipos Estruturados 23/04/2014.
Estruturas de Dados Aula 15: Árvores
Prof. Hilton Cardoso Marins Junior ÁRVORES BINÁRIAS.
Capítulo VI – Variáveis Indexadas 6.1 – A necessidade de variáveis indexadas 6.2 – Vetores e matrizes 6.3 – Aplicações com vetores numéricos 6.4 – Aplicações.
Estruturas de Dados Aula 10: Listas (parte 2) 07/05/2014.
CES-10 INTRODUÇÃO À COMPUTAÇÃO Aulas Práticas – 2014 Capítulo X Encadeamento de Estruturas por Ponteiros.
Alocação Dinâmica Dilvan Moreira. Objetivos  Entender o que são e como usar:  Gerenciamento de Memória  Alocação Dinâmica em C.
Princípios de Desenvolvimento de Algoritmos MAC122 Prof. Dr. Paulo Miranda IME-USP Alocação Dinâmica de Memória.
Estrutura de Dados (DPADF 0056) Aula 7 – Encadeamento de Memória Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior.
Capítulo II Listas Lineares Gerais CES-11 ALGORITMOS E ESTRUTURAS DE DADOS.
Estrutura de Dados (DPADF 0056) Aula 8 – Estr. Clássicas - Lista Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior.
INF1007: Programação 2 8 – Listas Encadeadas
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2016
INF1007: Programação 2 2 – Alocação Dinâmica
Capítulo II – Listas Lineares Gerais
Estrutura de Dados Revisão
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
INF1007 – Programação 2 9 – Pilhas
INF1007: Programação 2 6 – Ordenação de Vetores
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Estrutura de dados Pilhas e filas
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Árvores.
Capítulo IV – Árvores Gerais
FUNDAMENTO DE PROGRAMAÇÃO PROF. WELLINGTON FRANCO
Programação de Computadores I – Ponteiros
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas

Listas Encadeadas.
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
Fundamentos de Programação 1
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS
Programação de Computadores I – Ponteiros
Continuação.
Prof. Rafael Mesquita Fila Prof. Rafael Mesquita
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2019
Transcrição da apresentação:

Capítulo IV – Árvores Gerais 4.1 – Definições e terminologia básica 4.2 – Formas de representação de árvores 4.3 – Ordenação dos nós de uma árvore 4.4 – Operadores para o TAD árvore 4.5 – Estruturas contíguas para árvores 4.6 – Estruturas encadeadas para árvores

4.5 – Estruturas Encadeadas para Árvores 4.6.1 – Estrutura encadeada direta Esquema:

Declarações: Nó: ponteiro para célula const int maxfilhos = 5; typedef celula *noh; typedef celula *arvore; struct celula { informacao info; noh Filhos[5]; }; arvore A; Nó: ponteiro para célula Árvore: ponteiro para a célula da raiz Usa muitos ponteiros desnecessários (exemplo: folhas) Limita o número de filhos A Esquema usado em árvores balanceadas (implementação de dicionários)

4.6.2 – Estrutura com listas de filhos Esquema: celula raiz 1 ncel 11 Nó: índice num vetor de células Filhos: ordenados da esquerda para a direita Estrutura das listas: encadeada, sem nó- líder

4.6.2 – Estrutura com listas de filhos celula raiz 1 ncel 11 Não necessariamente a raiz fica no nó 1 Os nós podem ficar embaralhados no vetor, sem ordenação (pré-ordem, etc.) Facilita a inserção de nós

Declarações: typedef struct arvore arvore; struct arvore { noh raiz; celula Espaco[51]; int ncel; }; noh n1, n2, n3; arvore A1, A2, A3; informacao x, y, z; const int nulo = 0; typedef int noh; typedef celfilho *lista; typedef celfilho *posição; typedef struct celfilho celfilho; struct celfilho { noh filho; celfilho *prox; };   typedef struct celula celula; struct celula { informacao info; noh pai; lista list; celula raiz 1 ncel 11

Operadores: noh FilhoEsquerdo (noh n, arvore A) { if (A.Espaco[n].list == NULL) return nulo; else return A.Espaco[n].list->filho; } informacao Elemento (noh n, arvore A) { return A.Espaco[n].info; noh raiz (arvore A) { if (A.ncel == 0) return A.raiz; celula raiz 1 ncel 11

void Esvaziar (arvore *A){ Liberar todas as células de filhos; A->raiz = nulo; A->ncel = 0; } noh Pai (noh n, arvore A) { return A.Espaco[n].pai; celula raiz 1 ncel 11

Observação: esta estrutura é muito usada para grafos noh IrmaoDireito (noh n, arvore A) { noh pai; posição idir, p; if (n == A.raiz) return nulo; pai = A.Espaco[n].pai; p = A.Espaco[pai].list; while (p->filho != n) p = p->prox; idir = p->prox; if (idir == NULL) return nulo; else return idir->filho; } celula raiz 1 ncel 11 Observação: esta estrutura é muito usada para grafos

4.6.3 – Estrutura com encadeamento de pais e irmãos Esquema: info pai fesq idir Célula

a) Declarações info pai fesq idir Célula const celula *nulo = NULL; typedef celula *noh; typedef celula *arvore; typedef struct celula celula; struct celula { informacao info; noh pai, fesq, idir; }; arvore A1, A2, A3; info pai fesq idir Célula

Exemplo ilustrativo: montagem da seguinte árvore: Foi visto em CES-10

A A  B C  x x E  F  G  y x y arvore A; noh x, y; A = (noh) malloc (sizeof (celula)); A->info = 'A'; A->pai = A->idir = NULL; A->fesq = (noh) malloc (sizeof (celula)); x = A->fesq; x->info = 'B'; x->pai = A; x->fesq = (noh) malloc (sizeof (celula)); x->idir = (noh) malloc (sizeof (celula)); x->fesq->info = 'E'; x->fesq->pai = x; x->fesq->fesq = x->fesq->idir = NULL; x = x->idir; x->info = 'C'; x->pai = A; x->idir = NULL; y = x->fesq; y->info = 'F'; y->pai = x; y->fesq = NULL; y->idir = (noh) malloc (sizeof (celula)); y->idir->info = 'G'; y->idir->pai = x; y->idir->fesq = y->idir->idir = NULL; A A  B C  x x E  F  G  y x y

Os comandos anteriores formam apenas esta árvore em particular Ainda neste capítulo serão vistos algoritmos gerais de formação de árvores A A  B C  E  F  G 

b) Operações elementares FilhoEsquerdo (noh n, arvore A): n->fesq; IrmãoDireito (noh n, arvore: A): n->idir; Elemento (noh n, arvore A): n->info; Pai (noh n, arvore A): n->pai; Raiz (arvore A): A;   info pai fesq idir Célula

c) Operador Esvaziar (&n): anula o nó n e libera todas as células que se tornam inacessíveis devido a essa anulação   Por exemplo: Se n é o ponteiro A, todas as células da árvore serão liberadas Se n é o ponteiro fesq da célula que contém ‘A’, as células a serem liberadas são as de ‘B’, ‘E’, ‘C’, ‘F’, ‘G’, ‘D’, ‘H’, ‘I’, ‘J’ e ‘K’ Se n é o ponteiro idir da célula que contém ‘C’, as células a serem liberadas são as de ‘D’, ‘H’, ‘I’, ‘J’ e ‘K’ info pai fesq idir Célula Esvaziar (&A): esvazia a árvore A

Não deve ser aplicada ao ponteiro pai de nenhuma célula void Esvaziar (noh *n) { if ((*n)->fesq == NULL && (*n)->idir == NULL) free (*n); else if ((*n)->idir == NULL) { Esvaziar (&(*n)->fesq)); } else { Esvaziar (&((*n)->idir)); if ((*n)->fesq != NULL) Esvaziar (&((*n)->fesq)); *n = NULL;   info pai fesq idir Célula Se o argumento for &A : A = NULL n Não deve ser aplicada ao ponteiro pai de nenhuma célula Nesta função, n guarda o endereço de um ponteiro para celula

Esvaziar A: Esvaziar B: Esvaziar C: Esvaziar D: Esvaziar H: void Esvaziar (noh *n) { if ((*n)->fesq == NULL && (*n)->idir == NULL) free (*n); else if ((*n)->idir == NULL) { Esvaziar (&((*n)->fesq)); } else { Esvaziar (&((*n)->idir)); if ((*n)->fesq != NULL) (*n) = NULL;   Esvaziar A: Esvaziar B: Esvaziar C: Esvaziar D: Esvaziar H: Esvaziar I: Esvaziar J: Esvaziar K: Liberar K Liberar J Liberar I Liberar H Liberar D Esvaziar F: Esvaziar G: Liberar G Liberar F Liberar C Esvaziar E: Liberar E Liberar B Liberar A

d) arvore Criacao (informacao x, ListaArvores LA): H G F D C E B K J I ListaÁrvores

Situação no início da função Criacao (x, LA): Adota-se a estrutura contígua para a lista de árvores k x # ● 1 2 3 - - - - - - - - y - - - - - - ultimo Arvores LA a ● b ● c ● z ●

Aloca o nó-raiz da nova árvore e o preenche: x k k ● A (a ser retornado) ● ● # ● 1 2 3 ● ● ● ● - - - - - - - - y - - - - - - Arvores LA ultimo y a ● b ● c ● z ●

Procura primeira árvore não-nula em LA e a faz sub-árvore esquerda da raiz: x k k ● A (a ser retornado) ● # ● 1 2 3 ● ● ● ● - - - - - - - - y - - - - - - Arvores LA ultimo y a ● ● b ● c ● z ●

Percorre o vetor, procurando árvores não-nulas e acertando o pai e o idir de suas raizes: x k k ● A (a ser retornado) # ● 1 2 3 ● ● ● ● - - - - - - - - y - - - - - - Arvores LA ultimo y a b ● c ● z ● ● ● ● ●

arvore Criacao (informacao x, ListaArvores LA) { int i, j, ant; arvore A; A = malloc (sizeof (celula)); A->info = x; A->pai = A->fesq = A->idir = NULL; for (i = 1; i <= LA.ultimo && LA.Arvores[i] == NULL; i++); if (i <= LA.ultimo){ A->fesq = LA.Arvores[i]; for (j = i; j <= LA.ultimo; j++) if (LA.Arvores[j] != NULL) { if (j != i) LA.Arvores[ant]->idir = LA.Arvores[j]; LA.Arvores[j]->pai = A; LA.Arvores[j]->idir = NULL; ant = j; } return A; struct ListaArvores { int ultimo; arvore Arvores [51]; }

e) Formação de árvores: uma nova árvore pode ser formada pelos seguintes métodos (entre outros): Função Criação: vista no item d Leitura dos pares pais-filhos Formação interativa Leitura da forma parentética

e.1) Leitura dos pares pais-filhos: Usada para formar uma floresta O operador fornece todos os pares pais-filhos da floresta Por exemplo, seja uma floresta cujos nós das árvores guardam apenas um caractere cada Nessa floresta é proibido dois ou mais nós guardarem o mesmo caractere

O operador fornece os seguintes pares: A ordem entre dois irmãos é estabelecida pela ordem fornecida pelo operador Um filho não pode aparecer em mais de um par Não pode haver ciclos; Exemplo: Pai-Filho C-F R-S L-M R-T A-B C-G A-C N-P L-N A-D Pai-Filho A-B B-C C-D D-A

Floresta formada: Pai-Filho C-F R-S L-M R-T A-B C-G A-C N-P L-N A-D A

e.2) Formação interativa: constrói interativamente uma nova árvore, retornando-a Para o encadeamento de pais e irmãos é apresentada uma construção em largura A função elaborada será arvore NovaArvore (void) A seguir, uma saída típica para a execução dessa função

A arvore tem raiz? (s/n): s Digite a informacao da raiz: A Quantos filhos tem A? 3 1.o filho de A: B 2.o filho de A: C 3.o filho de A: D Quantos filhos tem B? 1 1.o filho de B: E Quantos filhos tem C? 2 1.o filho de C: F 2.o filho de C: G Quantos filhos tem D? 1 1.o filho de D: H Quantos filhos tem E? 0 Quantos filhos tem F? 0 Quantos filhos tem G? 0 Quantos filhos tem H? 3 1.o filho de H: I 2.o filho de H: J 3.o filho de H: K Quantos filhos tem I? 0 Quantos filhos tem J? 0 Quantos filhos tem K? 0

Perguntar pela raiz, alocando-a e colocando-a em ff: Idéia: Usar uma fila ff para guardar os nós já introduzidos na estrutura, para os quais não se indagou ainda sobre o número e o nome de seus filhos Perguntar pela raiz, alocando-a e colocando-a em ff: ff A A ●

Deletar ff, copiando sua frente no nó avulso x: ● x

Perguntar pelo número de filhos de x, guardando-o em nf: ff 3 nf A A ● x

Perguntar pelo 1º filho de x, alocando-o e colocando-o em ff: 3 nf A A ● x A alocação é a partir do filho esquerdo de x ● B ●

Perguntar pelos outros filhos de x, alocando-os e colocando-os em ff: 3 nf A A ● x A alocação é a partir do respectivo irmão esquerdo B ● C ● D ● ● ●

Deletar ff, copiando sua frente em x: 3 nf A A ● x B ● C ● D ● x

Perguntar pelo número de filhos de x, guardando-o em nf: ff nf 3 1 A A ● B ● C ● D ● x

Perguntar pelo filho de x, alocando-o e colocando-o em ff: 1 nf A A ● B C ● D ● x ● E ●

Deletar ff, copiando sua frente em x: 1 nf A A ● B C ● D ● x x E ●

Perguntar pelo número de filhos de x, guardando-o em nf: ff nf 1 2 A A ● B C ● D ● x E ●

Perguntar pelos filhos de x, alocando-os e colocando-os em ff: 2 nf A A ● B C D ● ● x E ● F ● G ● ●

Deletar ff, copiando sua frente em x: 2 nf A A ● E assim por diante B C D ● x x E ● F ● G ●

arvore NovaArvore () { arvore A; char c; fila ff; noh x, y; int nf, i; /* Verificacao da existencia de raiz */ write ("A arvore tem raiz? (s/n): "); read (c); while (c != 's' && c != 'n' && c != 'S' && c != 'N') read (c); if (c == 'n' || c == 'N') A = NULL; else { /* Leitura e armazenamento da raiz */ A = malloc (sizeof(celula)); write ("Digite a informacao da raiz: "); read (A->info); A->pai = A-> fesq = A->idir = NULL; InitFila (&ff); EntrarFila (A, &ff);

/* Leitura e armazenamento dos outros nos */ x = DeletarFila(&ff); write ("Quantos filhos tem ", x->info, "?"); read (nf); for (i = 1; i <= nf; i++) { if (i == 1) y = x->fesq = malloc(sizeof(celula)); else y = y->idir = malloc(sizeof(celula)); write (i, ".o filho de ", x->info, ":"); read (y->info); y->pai = x; y->fesq = y->idir = NULL; EntrarFila (y, &ff); } } while (FilaVazia(ff) == FALSE); } /* Fim do else */ return A; }

e.3) Leitura da forma parentética Digitar a forma, armazenando-a numa string, e analisar a cadeia, armazenando-a na estrutura com encadeamento de pais e irmãos Pode-se usar a seguinte formulação recursiva: Sendo c uma letra genérica, (c) é uma forma parentética correta Sendo α1, α2, α3, ... αn, formas parentéticas corretas (n > 0), então (c α1α2α3 ... αn) também é

Programa para somente analisar a parentética typedef char logic; const logic TRUE = 1, FALSE = 0; /* Prototipos de funcoes */ void Analisa (void); void Erro (char *); /* Variaveis globais */ char expr[100]; int i; char erro;

/* Programa principal */ int main () { write ("Forma parentetica: "); read (expr); i = 0; erro = FALSE; Analisa (); if (!erro && expr[i] != '\0') Erro("enter esperado"); if (erro) write ("\parentetica reprovada!"); else write ("parentetica valida!"); }

O programa para armazenar a árvore usa este programa como esqueleto /* Funcao Analisa: Verifica se a forma parentetica digitada estah correta */ void Analisa () { if (expr[i] != '(') {Erro ("( esperado"); return;} i++; if (isalpha (expr[i]) == FALSE) { Erro("Letra esperada"); return;} for (i++; expr[i] == '('; ) Analisa (); if (expr[i] != ')') {Erro (") esperado"); return;} } /* Funcao Erro: emite mensagem de erro */ void Erro (char *s) { erro = TRUE; write (s); O programa para armazenar a árvore usa este programa como esqueleto Fica como exercício