Скачиваний:
123
Добавлен:
17.03.2015
Размер:
751.62 Кб
Скачать

Проектирование класса TreeNode

Рассмотрим подробно разработку класса TreeNode – «узел бинарного дерева». В состав узла входит поле данных, которое является открытым (public) элементом, то есть к нему можно обращаться непосредственно. Это позволяет читать или обновлять данные во время прохождения дерева, а также допускает возвращение ссылки на данные. Последняя особенность используется более сложными структурами данных, например, словарями. Указатели на правое и левое поддеревья являются закрытыми (private) элементами, доступ к которым осуществляется посредством функций Left() и Right().

//Предварительное описание класса «бинарное дерево поиска»

template <class T>

class BinSTree;

//Определение класса «узел бинарного дерева»

template <class T>

class TreeNode

{

//Указатели на левый и правый порожденные узлы

TreeNode<T> *left;

TreeNode<T> *right;

public:

//Открытый элемент данных класса, допускающий обновление

T data;

//Конструктор: инициализирует поле данных и указатели

//на порожденные узлы

TreeNode (const T& item, TreeNode<T> *lptr, TreeNode<T> *rptr):

data(item), left(lptr), right(rptr) { }

// Методы доступа к указателям на порожденные узлы

TreeNode<T>* Left (void) const;

TreeNode<T>* Right (void) const;

// Описание класса BinSTree как дружественного

friend class BinSTree<T>;

};

Конструктор инициализирует поле данных и указатели на узлы следующего уровня. Если оба указателя инициализировать значением NULL, то узел будет инициализирован как лист.

Если в параметр lptr или rptr конструктора поместить указатели на другой объект TreeNode, конструктор присоединяет этот объект как левый или правый порожденный узел.

Методы доступа Left и Right возвращают соответствующий указатель. Класс BinSTree объявляется дружественным классу TreeNode и может модифицировать указатели. Другие клиенты должны использовать конструктор для создания указателей и методы Left и Right для прохождения дерева.

Пример 1. 

//Указатели целочисленных узлов дерева

TreeNode<int> *root, *lchild, *rchild;

TreeNode<int> *p;

//Создать листья, содержащие 20 и 30 в качестве данных

lchild = new TreeNode<int> (20);

rchild = new TreeNode<int> (30);

//Создать корень, содержащий число 10 и двух сыновей

root = new TreeNode<int> (10, lchild, rchild);

root->data = 50; //Присвоить корню 50

Методы Left и Right возвращают значения полей левого и правого указателей. Благодаря этому клиент имеет доступ к левому и правому сыновьям узла.

Построение бинарного дерева

Бинарное дерево состоит из конечного множества объектов TreeNode, связанных между собой посредством полей Left и Right. Объект TreeNode создается динамически с помощью функции new.

TreeNode<int> *p; //Объявление указателя на узел дерева

p = new TreeNode(item);//Левый и правый указатели равны NULL

Вызов функции new обязательно должен включать значение данных, и необязательно указатели на правое и/или левое поддерево.

Определим функцию GetTreeNode, принимающую данные, и ноль или более указателей на объект TreeNode для создания и инициализации узла бинарного дерева. При недостаточном количестве доступной памяти программа прекращается сразу после выдачи сообщения об ошибке.

//Создать объект TreeNode с указательными полями lptr и rptr.

//По умолчанию указатели содержат NULL.

template <class T>

TreeNode<T> *GetTreeNode(T item, TreeNode<T> *lptr = NULL,

TreeNode<T> *rptr = NULL)

{

TreeNode<T> *p;

//Вызвать new для создания нового узла

//Передать туда параметры lptr и rptr

p = new TreeNode<T> (item, lptr, rptr);

//Если памяти недостаточно, завершить

//программу сообщением об ошибке

if (p == NULL)

{

cerr << “Ошибка при выделении памяти!\n";

exit(1);

}

//Вернуть указатель на выделенную системой память

return p;

}

Функция FreeTreeNode принимает указатель на объект TreeNode и освобождает занимаемую узлом память, вызывая оператор С++ delete.

//Освободить динамическую память, занимаемую данным узлом

template <class t>

void FreeTreeNode(TreeNode<T> *p)

{

delete p;

}

Функция GetTreeNode может быть использована для явного построения каждого узла дерева и, следовательно, всего дерева. Это было продемонстрировано на дереве с тремя узлами, содержащими 10, 20 и 30. Для более крупного экземпляра процесс будет немного утомительным, так как вы должны поместить в дерево все значения данных и указателей.

Создадим функцию MakeCharTree, строящую три дерева, узлы которых содержат символьные элементы данных. Эти деревья будут использоваться для иллюстрации методов TreeNode в следующем разделе. Параметры функции включают в себя ссылку на корень дерева и число n (0 < n < 2), которое служит для обозначения дерева. Следующие объявления создают указатель на объект TreeNode, с именем root, и назначают его корнем дерева Tree_2.

//Объявить указатель на корень

TreeNode<char> *root;

//Сформировать на этом корне дерево tree_2

MakeCharTree(root,2);

На рисунке 9 показаны три дерева, построенных этим методом. Мы не приводим здесь кода этой функции ввиду ее примитивности, потренируйтесь сами.

Рис. 9. Дерево MakeCharTree

Соседние файлы в папке Лабораторная работа4 Деревья