Árvores
David Menotti
Estruturas de Dados I
DECOM – UFOP
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 contéudo de um nó pode ser de qualquer
tipo que se deseje representar
© David Menotti
Estruturas de Dados I
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 raizes 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.
© David Menotti
Estruturas de Dados I
Caminho



Um caminho de ni a nk, onde ni é
antecedente a nk, é a sequência de nós para
se chegar de ni a nk.
Se ni é antecedente a nk, nk é descendente
de ni
O comprimento do caminho é o número de
nós do caminho – 1.
© David Menotti
Estruturas de Dados I
Outros conceitos





Nó que não tem antecedente: raiz;
Nós que não tem descendentes são
chamados de nós folhas.
(Os outros são os nós internos)
A altura de um nó na árvore é o caminho de
maior comprimento que se pode fazer deste
nó a uma folha.
A altura da árvore é a altura de sua raiz.
A profundidade de um nó é o comprimento
da raiz até o nó (só existe um caminho)
© David Menotti
Estruturas de Dados I
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 seus descendentes
estão à esquerda de b e todos os descendentes de
b.
© David Menotti
Estruturas de Dados I
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.
© David Menotti
Estruturas de Dados I
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
© David Menotti
Estruturas de Dados I
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
/* Folha retorna se n é uma folha da árvore ou nã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;
© David Menotti
Estruturas de Dados I
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;
© David Menotti
Estruturas de Dados I
Exercício


Crie um TAD TNo 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
© David Menotti
Estruturas de Dados I
Algoritmos
e Estrutura
TAD TNo
typedef int TItem;
typedef struct TNo* Apontador;
typedef struct TNo {
TItem
Item;
Apontador pEsq;
Apontador pDir;
} TNo;
© David Menotti
Estruturas de Dados I
Algoritmos
e Estrutura
Caminhamento: PreOrder
void PreOrderRec(TNo* pRaiz)
{
if (pRaiz == NULL)
return;
printf(“%d\t”,pRaiz->Item);
PreOrderRec(pRaiz->pEsq);
PreOrderRec(pRaiz->pDir);
}
© David Menotti
Estruturas de Dados I
Caminhamento: InOrder
void InOrderRec(TNo* pRaiz)
{
if (pRaiz == NULL)
return;
InOrder(pRaiz->pEsq);
printf(“%d\t”,pRaiz->Item);
InOrder(pRaiz->pDir);
}
© David Menotti
Estruturas de Dados I
Caminhamento: PostOrder
void PostOrderRec(TNo* pRaiz)
{
if (pRaiz == NULL)
return;
PostOrder(pRaiz->pEsq);
PostOrder(pRaiz->pDir);
printf(“%d\t”,pRaiz->Item);
}
© David Menotti
Estruturas de Dados I
Caminhamento: PreOrder
não recursivo
void PreOrderIt(TNo* pRaiz)
{
TNo* pAux;
TPilha P;
FPVazia(&P);
PEmpilha(&P,&pRaiz);
while(!PEhVazia(&P))
{
PDesempilha(&P,&pAux);
if (pAux == NULL)
continue;
printf(“%d\t”,pAux->Item);
PEmpilha(&P,pAux->pDir);
PEmpilha(&P,pAux->pEsq);
}
}
© David Menotti
Estruturas de Dados I
Caminhamento: InOrder
não recursivo
void InOrderIt(TArvoreBin* pRaiz)
{
TArvoreBin* pAux;
TPilha P; FPVazia(&P);
PEmpilha(&P,pRaiz);
pAux = pRaiz->pEsq;
while(!PEhVazia(&P) || pAux != NULL)
{
if (pAux == NULL)
{
PDesempilha(&P,&pAux);
printf("%d\t",pAux->Item);
pAux = pAux->pDir;
}
else
{
PEmpilha(&P,pAux);
pAux = pAux->pEsq;
}
}
}
© David Menotti
Estruturas de Dados I
Caminhamento: PostOrder
não recursivo
void PostOrderIt(TArvoreBin* pRaiz)
{
TArvoreBin *pAux;
TPilha P1,P2;
FPVazia(&P1);
FPVazia(&P2);
PEmpilha(&P2,pRaiz);
pAux = pRaiz;
while(!PEhVazia(&P2) )
{
PDesempilha(&P2,&pAux);
PEmpilha(&P1,pAux);
if (pAux->pEsq != NULL) PEmpilha(&P2,pAux->pEsq);
if (pAux->pDir != NULL) PEmpilha(&P2,pAux->pDir);
}
while(!PEhVazia(&P1) )
{
PDesempilha(&P1,&pAux);
printf("%d\t",pAux->Item);
}
}
© David Menotti
Estruturas de Dados I
Exercício


Crie um TADs TNo e TArvoreBin em C que
representem árvores binárias cuja
informação seja um inteiro e possuam
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
© David Menotti
Estruturas de Dados I
TADs TNo e TArvoreBin
typedef int TItem;
typedef struct TNo* Apontador;
typedef struct No {
TItem
iItem;
struct No* pEsq; /* Apontador pEsq; */
struct No* pDir; /* Apontador pDir; */
} TNo;
typedef struct
{
TNo* pRaiz;
} TArvoreBin;
© David Menotti
Estruturas de Dados I
Caminhamento: PreOrder
void PreOrderRecX(TArvoreBin* pArv)
{
PreOrderRec(pArv->pRaiz);
}
© David Menotti
Estruturas de Dados I
Caminhamento: InOrder
void InOrderRecX(TArvoreBin* pArv)
{
InOrderRec(pArv->pRaiz);
}
© David Menotti
Estruturas de Dados I
Caminhamento: PostOrder
void PostOrderRecX(TArvoreBin* pArv)
{
PostOrderRec(pArv->pRaiz);
}
© David Menotti
Estruturas de Dados I
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
© David Menotti
Estruturas de Dados I
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.
© David Menotti
Estruturas de Dados I
Classificação de Árvores

Árvore Binária Quase Completa

Uma árvore binária de nível n é uma árvore
binária quase completa se:


© David Menotti
Cada nó folha na árvore esta no nível n ou no nível n-1
Para cada nó nd na árvore com um descentente direito
no nível n, todos os descendentes esquerdos de nd que
são folhas estão também no nível n
Estruturas de Dados I
Download

slides - Decom