Рассчитайте высоту дерева - PullRequest
3 голосов
/ 17 февраля 2010

Я пытаюсь вычислить высоту дерева. Я не согласен с кодом, написанным ниже.

#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);*/

}

Это дает мне печальный результат. Но в некоторых сообщениях (страница с поиском в Google) было предложено сделать обход по Postorder и использовать этот метод высоты для вычисления высоты. Любая конкретная причина?

Ответы [ 5 ]

15 голосов
/ 17 февраля 2010

Но разве пост-заказ не является именно тем, что вы делаете? Предполагая, что left и right оба не равны NULL, вы сначала делаете height(left), затем height(right), а затем некоторую обработку в текущем узле. По моему мнению, это обход заказа.

Но я бы написал так:

int Tree::height(tree *node) {
    if (!node) return -1;

    return 1 + max(height(node->left), height(node->right));
}

Редактировать: в зависимости от того, как вы определяете высоту дерева, базовый случай (для пустого дерева) должен быть 0 или -1.

4 голосов
/ 17 февраля 2010

Код не будет работать в деревьях, где хотя бы у одного из узлов есть только один дочерний элемент:

// 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);
//...

Если дерево имеет два узла (корень и левый или правый дочерний элемент), вызов метода в корне не выполнит первое условие (по крайней мере, одно из поддеревьев не пусто) и будет рекурсивно вызываться для оба дети. Один из них является нулевым, но все же он разыменует нулевой указатель для выполнения if.

Правильное решение - это сообщение, опубликованное Гансом здесь. В любом случае вы должны выбрать, какие у вас есть инварианты метода: либо вы разрешаете вызовы, когда аргумент равен нулю, и обрабатываете это изящно, либо вы требуете, чтобы аргумент был ненулевым, и гарантируете, что вы не вызываете метод с нулевыми указателями .

Первый случай безопаснее, если вы не контролируете все точки входа (метод общедоступен, как в вашем коде), поскольку вы не можете гарантировать, что внешний код не будет проходить нулевые указатели. Второе решение (изменение подписи на ссылку и превращение ее в метод-член класса tree) может быть более чистым (или нет), если вы можете контролировать все точки входа.

2 голосов
/ 17 февраля 2010

Определения из Википедии .

Предварительный заказ (сначала в глубину):

  1. Посетите корень.
  2. Пройдите по левому поддереву.
  3. Пройдите по правому поддереву.

Порядок (симметричный):

  1. Пройдите по левому поддереву.
  2. Посетите корень.
  3. Пройдите по правому поддереву.

Postorder:

  1. Пройдите по левому поддереву.
  2. Пройдите по правому поддереву.
  3. Посетите корень.

«Визит» в определениях означает «рассчитать высоту узла». Который в вашем случае равен нулю (левые и правые равны нулю) или 1 + общий рост детей.

В вашей реализации порядок обхода не имеет значения, он даст те же результаты. Не могу действительно сказать вам больше, чем без ссылки на ваш источник, заявив, что заказывать предпочтительнее.

2 голосов
/ 17 февраля 2010

Высота дерева не меняется при обходе. Это остается постоянным. Это последовательность узлов, которые меняются в зависимости от обхода.

0 голосов
/ 18 февраля 2015

Вот ответ:

int Help :: heightTree (node *nodeptr)
{
    if (!nodeptr)
        return 0;
    else
    {
        return 1 + max (heightTree (nodeptr->left), heightTree (nodeptr->right));
    }
}
...