- •1. Внутренняя сортировка (сортировка массивов).
- •6. Рекурсия. Рекурсивные функции
- •2.2 Обьявление класса
- •2.3 Определение функций-членов класса
- •2.4 Использование класса
- •2.5 Управление доступом к классу
- •1 Частные члены класса
- •10. Понятие дерева. Классификация деревьев. Способы представления дерева.
- •1. Вставка элемента.
- •2. Удаление элемента.
- •3. Последовательный поиск в списке.
- •2 Защищенные члены класса
- •3 Общедоступные члены класса
- •2.6 Указатель this
- •11. Общие операции над деревьями. Процедуры добавления и удаления элемента. Количество листьев и узлов в дереве.
10. Понятие дерева. Классификация деревьев. Способы представления дерева.
Древовидная структура характеризуется множеством узлов (nodes), происходящих от единственного начального узла, называемого корнем (root). На Рис. 3 корнем является узел А. В терминах генеалогического дерева узел можно считать родителем (parent), указывающим на 0, 1 или более узлов, называемых сыновьями (children). Например, узел В является родителем сыновей E и F. Родитель узла H - узел D. Дерево может представлять несколько поколений семьи. Сыновья узла и сыновья их сыновей называются потомками (descendants), а родители и прародители – предками (ancestors) этого узла. Корень дерева — это единственный узел, нe имеющий непосредственного предка. Например, узлы E, F, I, J – потомки узла B. Каждый некорневой узел имеет только одного родителя, и каждый родитель имеет 0 или более сыновей. Узел, не имеющий детей (E, G, H, I, J), называется листом (leaf).
При представлении в памяти компьютера элементы дерева (узлы) связывают между собой таким образом, чтобы каждый узел был связан со своим непосредственным предком и/или своими непосредственными потомками. Наиболее распространенными способами представления дерева являются следующие три (или их комбинации).
При первом способе каждый узел (кроме корня) содержит указатель на узел, являющийся его непосредственным предком, т. е. на элемент, находящийся на более высоком уровне иерархии. Для корня дерева соответствующий указатель будет пустым. При таком способе представления, имея информацию о местоположении некоторого узла, можно, отслеживая указатели, подниматься на более высокие уровни иерархии. К сожалению, этот способ представления непригоден, если требуется не только подниматься вверх по дереву, но и спускаться вниз, и при этом нет возможности получать независимо ссылки на узлы дерева. Тем не менее такое представление дерева иногда используется в алгоритмах, где прохождение узлов всегда осуществляется в восходящем порядке. Преимуществом этого способа представления дерева является то, что в нем используется минимальное количество памяти, причем практически вся она эффективно используется для представления связей.
Второй способ представления применяют, если каждый узел дерева имеет не более двух (в общем случае не более К) непосредственных потомка. Тогда можно включить в представление узла указатели на этих потомков. В этом случае дерево называют двоичным (бинарным), а два поддерева каждого узла называют соответственно левым и правым поддеревьями этого узла. Разумеется, узел может иметь и только одно — левое или правое — поддерево (эти две ситуации в бинарных деревьях обычно считаются различными) или может вообще не иметь поддеревьев (и в этом случае узел называется концевым или терминальным узлом или листом дерева). При этом способе представления достаточно иметь ссылку на корень дерева, чтобы получить доступ к любому узлу дерева, спускаясь по указателям, однако, память при таком способе представления используется не столь эффективно— часть зарезервированной памяти будет содержать пустые указатели.
t
emplate
<class
T>
class Tree {
// Определение класса для узла дерева
struct Node { Т item; // содержимое узла Node *left; // указатель на левое поддерево
Node *right; // указатель на правое поддерево // Конструктор узлов дерева:
Node(const T & item, Node *left = NULL, Node *right = NULL) { Node::item = item;
Node::left = left; Node::right = right; } };
Третий способ представления дерева состоит в том, что каждый узел списка содержит список своих поддеревьев. При этом можно задать такой список, непосредственно используя шаблон классов List, так что описание структуры узла дерева в контексте описания шаблона для самого дерева могло бы выглядеть следующим образом:
struct Node { Т item; // содержание узла List<Tree<T>*> subtrees; // список поддеревьев };
Самые простые из деревьев считаются бинарные деревья.
Бинарное дерево-это конечное множество элементов, которое либо пусто, либо содержит один элемент, называемый корнем дерева, а остальные элементы множества делятся на два непересекающихся подмножества, каждое из которых само является бинарным деревом.
Эти подмножества называются левым и правым поддеревьями исходного дерева.
Сильноветвящиеся деревья могут содержать в своих узлах более, чем один ключ.
Разрешим тройные и четверные узлы, которые могут содержать два или три ключа соответственно. У тройного узла есть 3 выходящие из него ветви, одна ветвь для всех записей ключи которых меньше чем оба его ключа, одна для всех записей, которые больше либо равны первому ключу, но меньше второго , и одна для всех записей, которые больше его ключей или равны второму ключу. Аналогично, 4-ной узел имеет 4 ветви выходящие из него; по одной для каждого интервала определенного его 3 ключами. (Узлы в обычном бинарном дереве можно таким образом называть двойными узлами: один ключ, две ветви.)
Сильноветвящееся дерево можно представить с использованием связных списков для запоминания указателей сыновей каждой вершины.
Рассмотрим другую задачу. Пусть требуется ввести некоторую последовательность символов, заканчивающуюся точкой, и напечатать ее в обратном порядке (т.е. если на входе будет "ABcEr-1." то на выходе должно быть "1-rEcBA"). Представленная ниже программа сначала вводит все символы последовательности, записывая их в стек, а затем содержимое стека печатается в обратном порядке. Это основная особенность стека - чем позже элемент занесен в стек, тем раньше он будет извлечен из стека. Реализация стека выполнена в связанном хранении при помощи указателей p и q на тип, именованный именем STACK.
#include<stdio.h>
typedef struct st /* объявление типа STACK */
{ char ch;
struct st *ps; } STACK;
main()
{ STACK *p,*q;
char a;
p=NULL;
do /* заполнение стека */
{ a=getch(); q=malloc(sizeof(STR1)); q->ps=p; p=q; q->ch=a; } while(a!='.');
do /* печать стека */
{ p=q->ps;free(q);q=p;
printf("%c",p->ch);
} while(p->ps!=NULL); }
Node2 *prev;//указатель на предыдующий элемент
Node2 *next;//указатель на следующий элемент}
typedef Node2* PNode2;
