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

➡ Абсолютно не важно — является дерево поисковым или нет, главное требование к нему, чтобы оно было бинарным.

Хочу рассмотреть следующее анонимное двоичное дерево. Почему анонимное? Потому что все узлы этого дерева не имеют ни ключей, ни каких-либо данных. Для исследования алгоритма мне это не важно!

анонимное бинарное дерево

Рисунок — стандартное анонимное бинарное дерево ( поиска )

Посчитать «глазами» количество узлов в этом дереве, используя представленную картинку, не составляет труда. Очевидно, что данное двоичное дерево содержит $11$ узлов. Но мне нужна программная функция, которая выполняет всю эту работу за меня. Выполняет быстро, правильно и надежно.

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

анонимное бинарное дерево с указанием всех ветвей

Рисунок — анонимное бинарное дерево с указанием всех ветвей

💡 А сейчас покажу основную идею алгоритма. Для этого я пронумерую все вершины ( в хаотичном порядке ) натуральными числами от $1$ до $n$, где $n$ — общее количество узлов двоичного дерева, а также выделю оранжевым цветом некоторые ветви. В итоге у меня получилась такая картина:

взаимосвязь количества ветвей и количества вершин двоичного дерева

Рисунок — взаимосвязь количества ветвей и количества вершин двоичного дерева

➡ И теперь я хочу посчитать количество оранжевых ветвей и количество вершин в этом дереве. Оказывается эти количества равны друг другу и составляют число $11$.

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

Другой важный момент заключается в том, что NULL-ветви при обходе дерева учитывать не нужно. То есть, если исследуется NULL-ребро необходимо искомое количество увеличивать на величину $0$.

И последний штрих: необходимо уловить связь между оранжевыми ребрами и числом рекурсивных вызовов функции, которая считает искомое количество. Общее количество рекурсивных вызовов будет равно общему числу всех связей, но, как мы раньше договорились, NULL-ветви учитываться не будут ( будет возвращаться для них число $0$ ).

В результате я закодировал на языке «чистый» Си следующую компактную рекурсивную функцию ( используется каскадная рекурсия ):

➡ Повторю: количество вызовов рекурсивной функции Nodes_count() равно общему количеству всех ребер двоичного дерева. Для данного дерева это число равно $23$. Это значение легко вычисляется по формуле $2 \cdot n + 1$, где $n$ — количество вершин дерева, а величине $+1$ соответствует указатель на вершину дерева ( или самый первый вызов функции Nodes_count() ).

Если говорить о вычислительной сложности данного алгоритма, то она составляет $O( 2 \cdot n + 1 ) = O( 2 \cdot n ) + O( 1 ) = O( n )$, где $n$ — общее количество вершин заданного бинарного дерева ( поиска ). Другими словами: чтобы посчитать количество узлов дерева необходимо каждый из них обойти по одному разу. Этого достаточно!

➡ Пишите в комментариях, что непонятно в рамках рассмотренного алгоритма поиска всех элементов заданного двоичного дерева. Также напишите, при каких обстоятельствах вам потребовалось находить это количество.

ВНИМАНИЕ Для заказа программы на двоичное дерево ( поиска ) пишите на мой электронный адрес proglabs@mail.ru