Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
инфа 2 семестр.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.12 Mб
Скачать

14. Деревья, основные операции над деревьями, представление дерева массивом Деревья.

«Алгоритмы + структуры данных = программы» приводит следующее определение:

Определенe 1:

Древовидная структура с базовым типом Т – это либо: 1) пустая структура; либо 2) узел типа Т, с которым связано конечное число древовидных структур с базовым типом Т, называемых поддеревьями. Используя такое определение, можно сказать, что линейный список – это вырожденное дерево, т.е. это древовидная структура, у которой каждый узел имеет не более одного поддерева.

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

Представление деревьев:

1 ) 2)

3) 4)

5) ( a ( b ( d ( i ) ) ( e ) ( f ) ) ( c ( g ) ( h ( k ) ( l ) ) ) )

Определение 2:

Дерево – это неориентированный связный граф без циклов.

Определение 3:

Дерево – это неориентированный, связный граф с n вершинами (n -1) ребром.

Определение 4:

Дерево – это конечное множество элементов, называемых узлами, таких что:

Между узлами существует связь, отношение типа «исходный - порожденный». Узел y, который находится непосредственно под узлом x, называется непосредственным потомком (сыном) x, а узел x называется предком (отцом) y – ка. Если x находится на уровне i, то y на уровне (i+1).

Лишь один узел не имеет исходного (отца), он называется корнем дерева.

Максимальный уровень элемента дерева называется высотой или глубиной дерева.

Остальные узлы имеют только одного отца и могут иметь ноль или более потомков.

Если узел не имеет сыновей, он называется терминальным, узлом или листом дерева, узел, не являющийся терминальным, называется внутренним.

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

Количество ветвей или ребер, которые необходимо пройти, чтобы продвинуться от корня к узлу x, называется длиной пути к x. Отношение исходный – порожденный действует только в одном направлении, т.е. для любого узла его потомки никогда не станут его предками.

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

Бинарное дерево – это множество узлов, каждый из которых либо пуст, либо состоит из узла, связанного с двумя различными бинарными деревьями, называемыми левым и правым поддеревом узла, т.е. каждый узел бинарного дерева имеет 0, 1 или 2 сына.

Упорядоченность бинарных деревьев понимается следующим образом:

У каждого поля есть ключевое поле (ключ) и для каждого узла справедливо утверждение, что значение ключевого поля большее всех ключей в его левом поддереве, меньшее всех – в правом.

Операции над деревьями, представление дерева массивом Важнейшими операциями над деревьями являются:

  • Построение дерева.

  • Добавление элемента в упорядоченное дерево.

  • Удаление элемента из упорядоченного дерева (более сложная операция: сначала найти, потом удалить так, чтобы сохранить упорядоченность дерева).

Тривиальная ситуация, если это удаление листа, несложная удаление 1 потомка, более сложная, когда 2 потомка

  • Обход бинарного дерева

1) + a b

  • Поиск в дереве величины с ключом, равным данному

Представление в компьютере дерева с помощью массива:

Компоненты массива, моделирующего двоичное дерево, должны быть комбинированного типа, причем два поля должны указывать на левое и правое поддерево этого узла (содержать их адреса), а остальные поля - это информационная часть - данные, хранящиеся в этом узле.

Представим в виде дерева, а дерево в виде массива арифметическое выражение:

(a + b / c ) * ( d – e * f )

Struct T { char info;

int left, right;

} Tree[11];

Представление дерева массивом позволяет легко находить путь от корня к заданному узлу, если значением каждого элемент a[i] является указатель на родителя узла i. Корень ссылается либо на себя, либо на 0. Элементы массива могут быть, как и в предыдущем случае, комбинированного типа, но значением одного из полей является указатель на непосредственного родителя, например, дерево вида:

Можно представить массивом: a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a[10]

Значения массива: 0 1 1 2 2 5 5 5 3 3

цикл while (b) {cout << b <<“\t”; b = a[b] }; для b= 7 выведет на экран путь от вершины b к корню: 7 5 2 1

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

Дерево – это структура данных, которая может быть рекурсивно определена и поэтому для работы с деревьями предпочтительными оказываются рекурсивные алгоритмы. struct tnode {

int inf;

………………………

tnode *left,*right;

};

tnode *p,*q,*r;

Представили дерево для выражения (a + b / c) * (d – e * f), здесь информационное поле символьного типа.

Реализуем основные операции:

  1. построение дерева

  2. обход дерева

  3. добавление узла в дерево

  4. поиск узла с заданным значением ключевого поля 5. удаление узла из дерева.

1. Построение дерева с n узлами и минимальной высотой:

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

Пусть информационной частью будут номера вершин, вводимых с клавиатуры.

Рекурсивный алгоритм:

  1. взять один узел в качестве корня;

  2. построить левое поддерево, состоящее из nl = n/2 узлов тем же способом; 3) построить правое поддерево, состоящее из nr = n – nl – 1 УЗЛОВ тем же способом. Функция, не возвращающая значение: void Tree (tnode *&t, int n) { tnode *r, int nr, nl, x; if (n == 0) t = NULL; else { nl = n / 2; nr = n – nl – 1;

cout <<’введите номер вершины’ << endl;

cin >> x;

r = new tnode; r->inf = x; Tree(r->left, nl); Tree(r->right, nr);

};

};

Функция, возвращающая значение: tnode *Tree (int n) { tnode *r; int nr, nl, x;

if (n == 0) return NULL;

else {

nl = n / 2; nr = n- nl - 1; cout <<nl <<"\t" <<nr <<"\t";

cout <<“введите номер вершины" <<"\t";

cin >> x;

r = new tnode; r->inf = x;

r->left = Tree(nl); r->right = Tree(nr);

return r;

};

};

Если n = 21 и с клавиатуры введены номера вершин в следующем порядке:

8, 9, 11, 15, 19, 20, 21, 7, 3, 2, 1, 5, 6, 4, 13, 14, 10, 12, 17, 16, 18, то с помощью этой функции будет построено дерево: