
Описание функций, используемых в программе
В программе используется 7 функций. Каждая из них выполняет свою уникальную, нигде не дублирующуюся функцию. Именно в этом и заключается смысл использования функций – использование функций решают проблему избыточности описания повторяющихся действий. Функции позволяют значительно сократить программный код и упростить процесс разработки программного продукта.
1) Функция построения дерева. В качестве входных параметров служат переменные str (в данную переменную записывается значение новой вершины, переданное из главной функции программы) и tt (переменная получает адрес памяти хранящий данные корня дерева).
Сначала проверяется следующее условие: является ли корень дерева пустым. При выполнении условия в поле данных корня записывается значение переменной. Если условие не выполняется, происходит проверка следующего условия: является ли переменная str меньше данных корня дерева. При выполнении данного условия проверяется еще одно: является ли левое поддерево пустым. Если левое поддерево пустое, то оно станет новой вершиной следующего поддерева и в него запишется значение переменной str. Если левое поддерево непустое, вызываем нашу функцию рекурсивно, но с параметрами tt-> pleft(указатель на левое поддерево) и str. Таким же образом проверяется и указатель на правое поддерево.
2) Функция удаления элемента дерева.
В качестве параметров в функцию будут входить node – значение узла дерева и parent - узел-родитель.
Удаление элемента из сортированного дерева немного сложнее, чем добавление. После этой операции программа должна перестроить другие узлы, чтобы сохранить в дереве соотношение «меньше чем». Следует рассмотреть несколько существующих вариантов.
Во-первых, если удаляемый узел не имеет потомков, допустимо просто убрать его из дерева. При этом порядок остальных узлов не изменяется (см. Рисунок 8).
Рисунок 8 Удаление листа дерева
Во-вторых, если удаляемый узел имеет один дочерний узел, можно заменить его дочерним узлом. При этом порядок потомков данного узла остается тем же, так как эти узлы также являются и потомками дочернего узла (см. Рисунок 9).
Рисунок 9 - Удаление узла с одним потомком
Если удаляемый узел имеет два дочерних, вовсе не обязательно, что один из них займет его место. Если потомки узла также имеют по два дочерних, то для размещения всех дочерних узлов в позиции удаленного узла просто нет места. У удаленного узла есть один лишний потомок, а дочерний узел, которым вы могли бы заменить исходный, имеет два дочерних узла, поэтому вы должны объявить три дочерних записи узла в данной позиции.
Чтобы решить эту проблему, вы должны заменить удаленный узел крайним
правым узлом дерева из левой ветви. Другими словами, двигайтесь вниз от удаленного узла по левой ветви. Затем двигайтесь вниз по правым ветвям до тех пор, пока не найдете узел без правой ветви. Это и есть нужный узел (см. Рисунок 10).
Рисунок 10 - Удаление узла с двумя потомками
3) Функция поиска повторяющихся элементов дерева. В данной функции используется булевый массив array (т.е. элементы данного массива могут принимать только два значения: true и false), который изначально состоит только из элементов, равных false. Используем цикл с предусловием (пока array[node->dann] имеет значение true), в котором будем вызывать функцию по удалению узла дерева. После цикла присвоим array[node->dann] значение true и осуществим проверку двух условий: является ля левое поддерево пустым (если является,то рекурсивно вызываем функцию с параметрами node->pleft, node->pleft) и является ли правое поддерево пустым (если является, то также вызываем рекурсивную функцию, но с параметрами node->pright, node->pright). Таким образом, в результате работы функции будут находиться повторяющиеся элементы, которые и будут удаляться.
4) Функция вывода дерева на экран. В качестве начальных параметров используются указатель на корень дерева и step – сдвиг для печати в виде дерева (начальное значение step =0)
Дерево печатается повернутым набок (вверху - правое поддерево, внизу - левое).
5) Функция обхода дерева. В качестве алгоритма обхода был выбран прямой обход дерева. Смысл алгоритма заключается в том, что каждый узел посещается до того, как посещены его потомки.
Для корня дерева рекурсивно вызывается следующая процедура:
а) Посетить узел.
б) Обойти левое поддерево.
в) Обойти правое поддерево.
6) Функция определения глубины дерева. В качестве параметра в функцию передается только узел дерева. Для нахождения глубины нам потребуется две переменные: a и b, которые изначально равны нулю. В переменную b будет записываться глубина дерева, переменная a – вспомогательная. Если узел непустой, то осуществляется дальнейшая проверка условий: если a>b, то a=b. Если непустое левое поддерево, то а увеличиваем на единицу и рекурсивно вызываем функцию с параметрами ptr-> pleft. Если левое поддерево непустое, то также увеличиваем переменную a на единицу и рекурсивно вызываем функцию с параметром ptr->pright.
7) Функция заполнения дерева случайными числами от 1 до 10 автоматически с использованием функции rand.