- •Красноярск
- •Федеральное агентство по образованию гоу впо «Сибирский государственный технологический университет»
- •220301 Автоматизация технологических процессов и производств,
- •230201 Информационные системы и технологии,
- •230105 Программное обеспечение вычислительной техники и автоматизированных систем всех форм обучения Красноярск
- •Содержание
- •Введение
- •1 Состав языка
- •1.1 Алфавит языка
- •1.2 Идентификаторы
- •1.3 Ключевые слова
- •1.4 Знаки операций
- •1.5 Константы
- •1.6 Комментарии
- •2.1 Концепция типа данных
- •2.2 Основные типы данных
- •3 Структура программы
- •4 Ввод/вывод
- •5 Переменные и выражения
- •5.1 Переменные
- •5.2 Операции
- •5.3 Выражения
- •6 Базовые конструкции структурного программирования
- •6.1 Оператор «выражение»
- •6.1.1 Задачи для решения на тему «линейные алгоритмы»
- •6.2 Операторы ветвления
- •6.2.1 Условный оператор if
- •6.2.2 Оператор switch
- •6.2.3 Задачи для решения на тему «условные алгоритмы»
- •6.3 Операторы цикла
- •6.3.1 Цикл с предусловием (while)
- •6.3.2 Цикл с постусловием (do while)
- •6.3.3 Цикл с параметром (for)
- •6.3.4 Задачи для решения на тему «сочетание цикла и разветвления»
- •6.4 Операторы передачи управления
- •6.4.1 Оператор goto
- •6.4.2 Оператор break
- •6.4.3 Оператор continue
- •6.4.4 Оператор return
- •6.4.5 Задачи для решения на тему «вложенные циклы (вычисление суммы ряда)»
- •7 Указатели и массивы
- •7.1 Указатели
- •7.1.1 Инициализация указателей
- •7.1.2 Операции с указателями
- •7.2 Ссылки
- •7.3 Массивы
- •7.3.1 Задачи для решения на тему «одномерные массивы»
- •7.3.2 Задачи для решения на тему «двумерные массивы»
- •7.4 Строки
- •7.4.1 Функции стандартной библиотеки
- •7.4.2 Задачи для решения на тему «строки»
- •8.1 Переименование типов (typedef)
- •8.2 Перечисления (enum)
- •8.3 Структуры (struct)
- •8.4 Битовые поля
- •8.5 Задачи для решения на тему «структуры»
- •9 Функции
- •9.1 Объявление и определение функций
- •9.2 Глобальные переменные
- •9.3 Возвращаемое значение
- •9.4 Параметры функции
- •9.5 Передача массивов в качестве параметров
- •9.6 Параметры со значениями по умолчанию
- •9.7 Функции с переменным числом параметров
- •9.8 Рекурсивные функции
- •9.9 Задачи для решения на тему «функции»
- •10 Директивы препроцессора
- •10.1 Директива #include
- •10.2 Директива #define
- •11 Динамические структуры данных
- •11.1 Линейные списки
- •11.2 Стеки
- •11.3 Очереди
- •11.4 Бинарные деревья
- •11.5 Задачи на тему «динамические структуры»
- •Задание на курсовую работу
- •Библиографический список
- •660049, Красноярск, пр. Мира, 82
11.4 Бинарные деревья
Бинарное дерево - это динамическая структура данных, состоящая из узлов, каждый из которых содержит, кроме данных, не более двух ссылок на различные бинарные деревья. На каждый узел имеется ровно одна ссылка. Начальный узел называется корнем дерева. Узел, не имеющий поддеревьев, называется листом. Исходящие узлы называются предками, входящие - потомками. Высота дерева определяется количеством уровней, на которых располагаются его узлы.
Дерево является рекурсивной структурой данных, поскольку каждое поддерево также является деревом. Действия с такими структурами изящнее всего описываются с помощью рекурсивных алгоритмов. Например, функцию обхода всех узлов дерева в общем виде можно описать так:
function way_around ( дерево ){
way_around ( левое поддерево )
посещение корня
way_around ( правое поддерево )
}
Для бинарных деревьев определены операции:
- включения узла в дерево;
- поиска по дереву;
- обхода дерева;
- удаления узла.
Для каждого рекурсивного алгоритма можно создать его нерекурсивный эквивалент. В приведенной ниже программе реализована нерекурсивная функция поиска по дереву с включением и рекурсивная функция обхода дерева. Первая функция осуществляет поиск элемента с заданным ключом. Если элемент найден, она возвращает указатель на него, а если нет - включает элемент в соответствующее место дерева и возвращает указатель на него. Для включения элемента необходимо помнить пройденный по дереву путь на один шаг назад и знать, выполняется ли включение нового элемента в левое или правое поддерево его предка.
Программа формирует дерево из массива целых чисел и выводит его на экран.
#include <iostream.h>
struct Node{
int d;
Node *left;
Node *right;
};
Node * first (int d);
Node * search_insert(Node *root, int d);
void print_tree(Node *root, int l);
//-----------------------------------------------------------
int main(){
int b[] = {10, 25, 20, 6, 21, 8, 1, 30};
Node *root = first(b[0]);
for (int i = 1; i<8; i++) search_insert(root, b[i]);
print_tree(root, 0);
return 0;
}
//-----------------------------------------------------------
// Формирование первого элемента дерева
Node * first (int d){
Node *pv = new Node;
pv->d = d;
pv->left = 0;
pv->right = 0;
return pv;
}
//-----------------------------------------------------------
// Поиск с включением
Node * search_insert(Node *root, int d){
Node *pv = root, *prev;
bool found = false;
while (pv && !found){
prev = pv;
if (d == pv->d) found =true;
else if (d < pv->d) pv = pv->left;
else pv = pv->right;
}
if (found) return pv;
// Создание нового узла:
Node *pnew = new Node;
pnew->d = d;
pnew->left = 0;
pnew->right = 0;
if (d < prev->d)
// Присоединение к левому поддереву предка:
prev->left == pnew;
else
// Присоединение к правому поддереву предка:
prev->right = pnew;
return pnew;
} '
//-----------------------------------------------------------
// Обход дерева
void print_tree(Node *p, int level){
if (p){
print_tree(p->left, level +1); // вывод левого поддерева
for (int i = 0; i<level; i++)cout « " ";
cout « p->d « endl; // вывод корня поддерева
print_tree(p->right, level +1); // вывод правого поддерева
}
}
Текущий указатель для поиска по дереву обозначен pv, указатель на предка pv обозначен prev, переменная pnew используется для выделения памяти под включаемый в дерево узел. Рекурсии удалось избежать, сохранив всего одну переменную (prev) и повторив при включении операторы, определяющие, к какому поддереву присоединяется новый узел.
Удаление узла из дерева представляет собой не такую простую задачу, поскольку удаляемый узел может быть корневым, содержать две, одну или ни одной ссылки на поддеревья. Для узлов, содержащих меньше двух ссылок, удаление тривиально. Чтобы сохранить упорядоченность дерева при удалении узла с двумя ссылками, его заменяют на узел с самым близким к нему ключом. Это может быть самый левый узел его правого поддерева или самый правый узел левого поддерева. Реализация функции удаления из дерева оставлена для самостоятельной работы.
