Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры данных и алгоритмы. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
1 Мб
Скачать

Для определения дерева как единой структуры, нужно задать указатель на корень дерева:

tree *t;

Для инициализации дерева достаточно указателю t присвоить значение NULL:

t = NULL;

На рис. 3.3 представлено двоичное динамическое дерево d в соответствии с определением типа элемента, сделанным выше. Элементы дерева со степенью 0 и 1 имеют два или одно ссылочное поле со значением равным пустому указателю (NULL).

Обход дерева

Обрабатывая дерево, приходится просматривать его элементы – эта операция называется обходом дерева (или прохождение дерева).

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

d

NULL

NULL

 

NULL

 

NULL

 

NULL

 

 

 

NULL

NULL NULL

Рис. 3.3

71

Возможны два способа прохождения бинарного дерева (если дерево не пусто) – в глубину и в ширину:

а) в глубину:

– прямой (префиксный) порядок: корень, левое поддерево в прямом порядке, правое поддерево в прямом порядке (линейная расстановка узлов дерева, представленного на рис. 3.1, б: ABDCEGFHJ);

Алгоритм прямого обхода:

PREORDER(tree *t)

{

stack s = NULL; while (t != NULL)

{

PROCESS(d);

if (t->left != NULL && t->right != NULL)

{

PUSH(S, t->right); t = t->left;

}

else

if (t->left == NULL && t->right == NULL) if (s != NULL)

POP(s, t); else

t = NULL;

else

t = t->left != NULL ? t->left : t->right;

}

}

Рекурсивное описание алгоритма прямого обхода:

PREORDER(tree *t)

72

{

if (t != NULL)

{

PROCESS(t); PREORDER(t->left); PREORDER(t->right);

}

}

– обратный (инфиксный) порядок: левое поддерево в обратном порядке, корень, правое поддерево в обратном порядке (линейная расстановка узлов дерева, представленного на рис. 3.1, б: DBAEGCHFJ);

Алгоритм обратного обхода:

PREORDER(tree *t)

{

stack s = NULL;

for (char f = 1; f; )

{

while (t != NULL)

{

PUSH(s, t); t = t->left;

}

if (s != NULL)

{

POP(s, t); PROCESS(t); t = t-right;

}

else

f = 0;

}

}

73

Рекурсивное описание алгоритма обратного обхода:

INORDER(tree *t)

{

if (t != NULL)

{

INORDER(t->left); PROCESS(t); INORDER(t->right);

}

}

– концевой (постфиксный) порядок: левое поддерево в концевом порядке, правое поддерево в концевом порядке, корень (линейная расстановка узлов дерева, представленного на рис. 3.1.б: DBGEHJFCA);

Алгоритм концевого обхода:

POSTORDER(tree *t)

{

stack s = NULL; do

{

while (t != NULL)

{

PUSH(s, t, 0); t = t->left;

}

if (s != NULL)

{

do {

POP(s, t, f); if (f)

PROCESS(t);

} while (f && s != NULL);

74

if (!f)

{

PUSH(s, t, 1); t = t->right;

}

} while (s != NULL);

}

Рекурсивное описание алгоритма концевого обхода:

POSTORDER(tree *t)

{

if (t != NULL)

{

POSTORDER(t->left);

POSTORDER(t->right); PROCESS(t);

}

}

б) в ширину: узлы дерева посещаются слева направо, уровень за уровнем вниз от корня (линейная расстановка узлов дерева, представленного на рис. 3.1, б: ABCDEFGHJ).

Алгоритм обхода в ширину:

LEVELORDER(tree *t)

{

queue q = NULL; if (t != NULL)

{

PUSH(q, d); do {

POP(q, t); PROCESS(t);

75

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]