Aula 08: Árvores
Bruno HottAlgoritmos e Estruturas de Dados IDECSI – UFOP
Bruno Hott 2
Conceitos básicos
● Organiza um conjunto de acordo com uma estrutura hierárquica.
● Contém elementos que são chamados de nós
● O “pai de todos” é a raiz (1º. da hierarquia)
● O nó que não tem filhos é denominado de folha
● Os demais nós são os nós internos
Bruno Hott 3
Conceitos sobre árvores
● Um caminho de ni a nk, onde ni é antecedente a nk, é a sequência de nós para se chegar de ni a nk
● O comprimento do caminho é o número de nós do caminho -1
● O nível de um nó é o comprimento da raiz até o nó +1
● A altura de um nó na árvore é o comprimento do maior caminho que se pode fazer deste nó até uma folha descendente.
● A altura da árvore é a altura de sua raiz.
Bruno Hott 4
Definição (Aho, Hopcroft e Ullman - 1983)
● Um único nó é uma árvore. Este nó é raiz da árvore.
● Suponha que n é um nó e T1, T2, …, Tk sejam árvores com raízes n1, n2, …, nk, respectivamente. Podemos construir uma nova árvore tornando n a raiz e T1, T2, …, Tk sejam subárvores da raiz. Nós n1, n2, …, nk são chamados filhos do nó n.
Bruno Hott 5
Caminhamento
● A ordem dos filhos dos nós em uma árvore pode ser ou não significativa.
– Exemplos, no heap, a ordem dos filhos não tem significado
– Outros casos, pode se ter um significado (como veremos em pesquisa em árvores binárias)
● Considera-se que se a e b são nós irmãos, e a está à esquerda de b, então todos os descendentes de a estão à esquerda de b e de todos os descendentes de b.
Bruno Hott 6
Caminhamento
● Diversas formas de percorrer ou caminhar em uma árvore listando seus nós, as principais:
– Pré-ordem (Pré-fixa)
– Central (Infixa)
– Pós-ordem (Pós-fixa)
● Para todas elas:
– Se T é uma árvore nula, então a lista é nula.
– Se T é uma árvore de um único nó então a lista contém apenas este nó.
– O tratamento é diferenciado para os filhos
– O que muda é a ordem de apresentação da raiz.
Bruno Hott 7
Pré-Ordem
● Pré-ordem: lista o nó raiz, seguido de suas subárvores (da esquerda para a direita), cada uma em pré-ordem.
Procedimento PREORDEM (n: TipoNo):Início Lista(n); Para cada filho f de n, da esquerda para direita faça PREORDEM(f);Fim
Bruno Hott 8
Central
● Central: lista os nós da 1ª. subárvore à esquerda usando o caminhamento central, lista o nó raiz n, lista as demais subárvores (a partir da 2ª.) em caminhamento central (da esquerda para a direita)
Procedimento CENTRAL (n: TipoNo);Início Se Folha(n) então Lista(n); Senão CENTRAL (FilhoMaisEsquerda(n)); Lista (n); Para cada filho f de n, exceto o mais à esquerda, da esquerda para a direita faça CENTRAL (f);Fim;
Bruno Hott 9
Pós-Ordem
● Pós-ordem: Lista os nós das subárvores (da esquerda para a direita) cada uma em pós-ordem, lista o nó raiz.
Procedimento POSORDEM Início Para cada filho f de n, da esquerda para direita faça POSORDEM(f); Lista(n);Fim;
Bruno Hott 10
Exercício
● Crie um TAD TArvoreBin em C cuja informação seja um inteiro e possua ponteiros para duas sub-árvores: esquerda e direita;
● Escreva funções que recebam um ponteiro para a raiz da árvore e façam:
– o caminhamento pré-ordem
– o caminhamento pós-ordem
– o caminhamento central
Bruno Hott 11
TAD TArvoreBin
typedef int TItem;
typedef struct TArvoreBin{ TItem item; struct TArvoreBin* pEsq; struct TArvoreBin* pDir;}TArvore;
Bruno Hott 12
Caminhamento: PreOrder
void PreOrderRec(TArvore* pRaiz){ if(pRaiz == NULL) return;
printf(“%d ”,pRaiz->item); PreOrderRec(pRaiz->pEsq); PreOrderRec(pRaiz->pDir);}
Bruno Hott 13
Caminhamento: InOrder
void InOrderRec(TArvore* pRaiz){ if(pRaiz == NULL) return;
InOrderRec(pRaiz->pEsq); printf(“%d ”,pRaiz->item); InOrderRec(pRaiz->pDir);}
Bruno Hott 14
Caminhamento: PostOrder
void PosOrderRec(TArvore* pRaiz){ if(pRaiz == NULL) return;
PosOrderRec(pRaiz->pEsq); PosOrderRec(pRaiz->pDir); printf(“%d ”, pRaiz->item);}
Bruno Hott 15
Caminhamento: PreOrder(não recursivo)
void PreOrderIt(TArvoreBin* pRaiz){ TArvoreBin* pAux; TPilha P; FPVazia(&P); Pempilha(&P,&pRaiz); while(!PVazia(&P)){ Pdesempilha(&P,&pAux); if(pAux == NULL) continue; printf(“%d\t”,pAux->item); PEmpilha(&P,pAux->pEsq); PEmpilha(&P,pAux->pDir); }}
Bruno Hott 16
Caminhamento: InOrder(não recursivo)
void InOrderIt(TArvoreBin* pRaiz){ TArvoreBin* pAux; TPilha P; FPVazia(&P); Pempilha(&P,pRaiz); Aux = pRaiz->pEsq; while(!PVazia(&P) || pAux != NULL){ if(pAux == NULL){ Pdesempilha(&P,&pAux); printf("%d\t",pAux->item); pAux = pAux->pEsq; }else{ Pempilha(&P,pAux); pAux = pAux->pDir;
} }}
Bruno Hott 17
Caminhamento: PostOrder(não recursivo)
void PostOrderIt(TArvoreBin* pRaiz){ TArvoreBin *pAux; TPilha P1,P2; FPVazia(&P1); FPVazia(&P2);
PEmpilha(&P2,pRaiz); pAux = pRaiz; while(!PVazia(&P2)){ PDesempilha(&P2,&pAux); PEmpilha(&P1,pAux); if(pAux->pEsq != NULL) PEmpilha(&P2,pAux->pEsq); if(pAux->pDir != NULL) PEmpilha(&P2,pAux->pDir); }
while(!PVazia(&P1) ){ PDesempilha(&P1,&pAux); printf("%d\t",pAux->item); }}
Bruno Hott 18
Classificação de Árvores
● Árvore Estritamente Binária
– Se cada nó não-folha em uma árvore binária não tem subárvores esquerda e direita vazias
Bruno Hott 19
Classificação de Árvores
● Árvore Binária Completa
– Uma árvore binária completa de nível n é a árvore estritamente binária, onde todos os nós folhas estão no nível n.
Bruno Hott 20
Classificação de Árvores
● Árvore Binária Quase Completa
– Cada nó folha na árvore esta no nível n ou no nível n-1
– Para cada nó nd na árvore com um descendente direito no nível n, todos os descendentes esquerdos de nd que são folhas estão também no nível n
Bruno Hott 21
Exercícios
● Escreva um algoritmo para imprimir o conteúdo de uma árvore binária levando em consideração os níveis de seus nós.
● Escreva algoritmos recursivos e não-recursivos para determinar:
– O número de nós em uma árvore binária
– A soma dos conteúdos de todos os nós em uma árvore binária, considerando que cada nó contém um inteiro
– A altura de uma árvore binária