Нахождение высоты бинарного дерева


0

Учитывая код для нахождения высоты бинарного дерева:

/* 
class Node 
int data; 
Node left; 
Node right; 
*/ 
int height(Node root) 
{ 
    if(root == null){ 
    return 0; 
} 
else{ 
    int left = height(root.left); 
    int right = height(root.right); 
    if(left > right){ 
     return 1 + left; 
    } 
    else{ 
     return 1 + right; 
    } 
} 
} 

Пример является:

 3 
/ \ 
    5  2 
/\ /
1 4 6 
    /
    7 

и высота потому 3->2->6->7

У меня большие проблемы с пониманием процесса рекурсии. Я был бы признателен всем, кто объясняет мне следующие вопросы:

1) При перемещении по дереву, выполните следующие две строки добавить 1 при каждом посещении узла? Большой вопрос: как это работает?

int left = height(root.left); 
int right = height(root.right); 

2) Должен ли я правильно понимаю ?: int left = height(root.left); ---> идет до левого узла ?? int right = height(root.right); ---> идет до самый правый узел ??

Что произойдет, если я имел следующее дерево:

 3 
/ \ 
    5  2 
/\ /
1 4 6 
// 
    3 7 
/
2 

и высота будет из 3->5->4->3->2?

У меня возникли трудности с пониманием рекурсию этих строк:

int left = height(root.left); 
int right = height(root.right); 

Мое понимание о тех линий left идет к левому узлу, а right идет в крайний правый узел.

Заранее благодарен!

  0

Предлагаю вам выполнить код в отладчике. Это очень простая функция, и пока вы не увидите, как работает код, я не думаю, что вы можете его полностью понять. 31 дек. 152015-12-31 00:11:59

  0

Вы выяснили, что если 'left' только отправился в самый левый узел, эта функция не сработает, но она работает, поэтому вы знаете, что это не может быть правильно. 31 дек. 152015-12-31 00:14:30

3

В принципе, у вас есть простое описание алгоритма, и вы реализуете его почти буквально, чтобы получить рекурсивное решение. Вы начинаете что-то вроде:

  • дерева без каких-либо узлов имеет высоту 0
  • дерево с любым количеством узлов имеет высоту 1 + максимальная высота между левым поддерево и правое поддерево

В рекурсивном алгоритме у вас всегда есть рекурсивный шаг (который в этом случае второй) и базовый регистр, который останавливает рекурсию (дерево без узлов).

Так в основном высота дерева с корнем 3

 3 
/ \ 
    5  2 
/\ /
1 4 6 
    /
    7 

является 1 + максимум между высотой двух поддеревьев, начиная с 3, например:

5    2 
/\   /
1 4   6 
      /
       7 

Так это то, что делается

int left = height(root.left); 
int right = height(root.right); 

Тогда рекурсивно, высота

5 
/\ 
1 4 

максимальна между высотой поддеревьев

1 4 

и так далее.

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


0

Чтобы ответить на ваши вопросы конкретно:

1) две линии, которые вы выдвинули на первый план:

int left = height(root.left); 
int right = height(root.right); 

не добавляют 1 к высоте дерева. Скорее, они назначают высоту левого поддерева и правого поддерева двум разным переменным.

Следующая если-то-иначе-ветви после назначения код, который добавляет 1 к высоте:

if(left > right) { 
    return 1 + left; 
} else { 
    return 1 + right; 
} 

2) Два рекурсивных вызовов:

int left = height(root.left); 
int right = height(root.right); 

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

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

Давайте рассмотрим пример, который вы опубликовали.

 3 
/ \ 
    5  2 
/\ /
1 4 6 
// 
    3 7 
/
2 

Используя рекурсию, высота будет выработанный первым узнать высоту детей ниже 2, что 0.

Чтобы найти высоту поддерева:

2 

он добавит 1 к высоте поддерева ниже, что равно 0, что даст нам высоту 1.

Затем добавить 1 к высоте поддерева:

3 
/
2 

Давать нам 1 + высота поддерева, начиная с 2 = 2.

Это будет продолжаться до поддеревьев:

4 
/
    3 
/
2 

1 + высота поддерева, начиная с 3 = 1 + (2) = 3

затем:

5 
/\ 
1 4 
/
    3 
/
2 

и, наконец, основное дерево:

 3 
/ \ 
    5  2 
/\ /
1 4 6 
// 
    3 7 
/
2 

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