Рассчитать высоту дерева

голоса
3

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

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

}

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

Задан 17/02/2010 в 09:07
источник пользователем
На других языках...                            


5 ответов

голоса
2

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

Ответил 17/02/2010 в 09:17
источник пользователем

голоса
14

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

Но я хотел бы написать это следующим образом:

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

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

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

Ответил 17/02/2010 в 09:19
источник пользователем

голоса
2

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

Предзаказ (глубина первая):

  1. Посетите корень.
  2. Траверса левого поддерева.
  3. Траверс правого поддерева.

Симметричный (симметричный):

  1. Траверса левого поддерева.
  2. Посетите корень.
  3. Траверс правого поддерева.

Postorder:

  1. Траверса левого поддерева.
  2. Траверс правого поддерева.
  3. Посетите корень.

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

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

Ответил 17/02/2010 в 09:27
источник пользователем

голоса
4

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

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

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

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

Ответил 17/02/2010 в 09:40
источник пользователем

голоса
0

Вот ответ:

int Help :: heightTree (node *nodeptr)
{
    if (!nodeptr)
        return 0;
    else
    {
        return 1 + max (heightTree (nodeptr->left), heightTree (nodeptr->right));
    }
}
Ответил 18/02/2015 в 20:02
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more