Calcule a altura de uma árvore
-
21-09-2019 - |
Pergunta
Estou tentando calcular a altura de uma árvore. Estou com o código escrito abaixo.
#include<iostream.h>
struct tree
{
int data;
struct tree * left;
struct tree * right;
};
typedef struct tree tree;
class Tree
{
private:
int n;
int data;
int l,r;
public:
tree * Root;
Tree(int x)
{
n=x;
l=0;
r=0;
Root=NULL;
}
void create();
int height(tree * Height);
};
void Tree::create()
{
//Creting the tree structure
}
int Tree::height(tree * Height)
{
if(Height->left==NULL && Height->right==NULL)
{return 0;
}
else
{
l=height(Height->left);
r=height(Height->right);
if (l>r)
{l=l+1;
return l;
}
else
{
r=r+1;
return r;
}
}
}
int main()
{
Tree A(10);//Initializing 10 node Tree object
A.create();//Creating a 10 node tree
cout<<"The height of tree"<<A.height(A.Root);*/
}
Isso me dá resultado correto. Mas em Algumas postagens(Página Google) Sugeriu -se que faça uma travessia postocerte e use esse método de altura para calcular a altura. Algum motivo específico?
Solução
Mas uma travessia da Postome não é exatamente o que você está fazendo? Supondo que a esquerda e a direita não sejam nulos, você primeiro height(left)
, então height(right)
, e depois algum processamento no nó atual. Isso é travessia da Postome, de acordo com mim.
Mas eu escrevia assim:
int Tree::height(tree *node) {
if (!node) return -1;
return 1 + max(height(node->left), height(node->right));
}
Editar: Dependendo de como você define a altura da árvore, o caso base (para uma árvore vazia) deve ser 0 ou -1.
Outras dicas
O código falhará nas árvores onde pelo menos um dos nós tem apenas um filho:
// code snippet (space condensed for brevity)
int Tree::height(tree * Height) {
if(Height->left==NULL && Height->right==NULL) { return 0; }
else {
l=height(Height->left);
r=height(Height->right);
//...
Se a árvore tiver dois nós (a raiz e uma criança esquerda ou direita), chamar o método na raiz não cumprirá a primeira condição (pelo menos uma das subárvores não está vazia) e ligará recursivamente para as duas crianças. Um deles é nulo, mas ainda assim será desreferente ao ponteiro nulo para executar o if
.
Uma solução correta é a postada por Hans aqui. De qualquer forma, você deve escolher quais são seus invariantes de método: ou você permite chamadas onde o argumento é nulo e lida com isso graciosamente ou precisa que o argumento seja não nulo e garante que você não chama o método com ponteiros nulos .
O primeiro caso é mais seguro se você não controlar todos os pontos de entrada (o método é público como no seu código), pois você não pode garantir que o código externo não passará por indicadores nulos. A segunda solução (alterando a assinatura para referência e tornando -a um método de membro do tree
classe) pode ser mais limpo (ou não) se você puder controlar todos os pontos de entrada.
A altura da árvore não muda com a travessia. Permanece constante. É a sequência dos nós que mudam dependendo da travessia.
Definições de Wikipedia.
Pré-encomenda (profundidade primeiro):
- Visite a raiz.
- Atravessar a subárvore esquerda.
- Atravessar a subárvore direita.
InOrder (simétrico):
- Atravessar a subárvore esquerda.
- Visite a raiz.
- Atravessar a subárvore direita.
PROTORMA:
- Atravessar a subárvore esquerda.
- Atravessar a subárvore direita.
- Visite a raiz.
"Visite" nas definições significa "calcular a altura do nó". Que no seu caso é zero (à esquerda e à direita são nulos) ou 1 + altura combinada das crianças.
Na sua implementação, a ordem de travessia não importa, daria os mesmos resultados. Não posso realmente dizer nada além disso, sem um link para sua fonte, afirmando que a Postler prefere.
Aqui está a resposta:
int Help :: heightTree (node *nodeptr)
{
if (!nodeptr)
return 0;
else
{
return 1 + max (heightTree (nodeptr->left), heightTree (nodeptr->right));
}
}