Рацеев С.М. Программирование на языке Си
.pdf{
ELEMENT *q; q = root;
for(; ; )
{
if (q == NULL) return;
if (q->key == x)
{
(q->count)++; return;
}
else if (q->key > x)
if (q->left == NULL)
{
q->left = Node(x); return;
}
else q = q->left; else
if (q->right == NULL)
{
q->right = Node(x); return;
}
else q = q->right;
}
}
int main( )
{
ELEMENT *root = NULL; int a;
scanf("%d", &a); if (a != 0)
{
root = Node(a); scanf("%d", &a);
281
while (a != 0)
{
Insert(root, a); scanf("%d", &a);
}
}
Display(root); return 0;
}
Пример 6. Ниже приводится рекурсивная и итеративная функция, которая определяет, присутствует ли элемент x в дереве поиска:
/* рекурсивная функция поиска элемента */
int Search(ELEMENT *q, int x)
{
if (q == NULL) return 0;
else
if (q->key == x) return 1;
else
if (q->key > x)
return Search(q->left, x); else
return Search(q->right, x);
}
/*итеративная функция поиска элемента */
int Search2(ELEMENT *root, int x)
{
ELEMENT *q = root; for (;;)
{
if (q == NULL) return 0;
else
if (q->key == x) return 1;
else
if (q->key > x) q = q->left;
else q = q->right;
}
}
Пример 7. Написать функцию удаления вершины с заданным ключом x из дерева поиска.
При удалении вершины может возникнуть один из трех слу-
чаев:
282
вершины с ключом, равным x, нет;
вершина с ключом x имеет не более одного потомка;
вершина с ключом x имеет двух потомков.
Если удаляемая вершина является листом, то она удаляется, а соответствующий указатель в ее родительской вершине устанавливается в нулевое значение.
Если удаляемая вершина имеет только одного потомка, то она удаляется, а соответствующий указатель в ее родительской вершине устанавливается на этого потомка. В этом случае вершинапотомок занимает в дереве место удаленной вершины.
В третьем случае поступаем следующим образом. Пусть q – удаляемая вершина. Находим вершину Max левого поддерева вершины q с максимальным значением ключа. Вершина Max является самой правой вершиной левого поддерева вершины q. Затем заменяем ключ и счетчик вершины q на соответствующие значения вершины Max. После этого удаляем вершину Max.
/* 1 способ */
ELEMENT *Max(ELEMENT *q)
{
if (q == NULL) return NULL;
while (q->right != NULL) q = q->right;
return q;
}
void Delete(ELEMENT **q, int x)
{
ELEMENT *t; if (*q != NULL)
{
if ((*q)->key > x) Delete(&((*q)->left), x);
else
if ((*q)->key < x) Delete(&((*q)->right), x);
else
{
/* 2 способ */
ELEMENT **Max(ELEMENT **q)
{
if (*q == NULL) return NULL;
while ((*q)->right != NULL) q = &((*q)->right);
return q;
}
void Delete(ELEMENT **q, int x)
{
ELEMENT *t; if (*q != NULL)
{
if ((*q)->key > x) Delete(&((*q)->left), x);
else
if ((*q)->key < x) Delete(&((*q)->right), x);
else
{
283
if ((*q)->left == NULL) |
if ((*q)->left == NULL) |
{ |
{ |
t = *q; |
t = *q; |
*q = (*q)->right; |
*q = (*q)->right; |
free(t); |
free(t); |
} |
} |
else |
else |
if ((*q)->right == NULL) |
if ((*q)->right == NULL) |
{ |
{ |
t = *q; |
t = *q; |
*q = (*q)->left; |
*q = (*q)->left; |
free(t); |
free(t); |
} |
} |
else |
else |
{ |
{ |
t = Max((*q)->left); |
ELEMENT **r; |
(*q)->key = t->key; |
r = Max(&((*q)->left)); |
(*q)->count = t->count; |
(*q)->key = (*r)->key; |
Delete(&((*q)->left),t->key); |
(*q)->count = (*r)->count; |
} |
t = *r; |
} |
*r = (*r)->left; |
} |
free(t); |
} |
} |
|
} |
|
} |
|
} |
Пример 8. Нахождение высоты произвольного бинарного дерева.
long Height(ELEMENT *q)
{
if (q == NULL) return -1;
else
{
long i, j;
i= Height(q->left);
j= Height(q->right); if (i > j)
284
return i+1; return j+1;
}
}
Пример 9. Определение количества элементов на k-м уровне дерева.
/* переменная level отвечает за номер уровня вершины q */ long Count(ELEMENT *q, long level, long k)
{
if (q == NULL || level > k) return 0;
else
if (level == k) return 1;
else return Count(q->left, level+1, k) + Count(q->right, level+1, k);
}
Пример 10. Вывод на экран всевозможных путей, ведущих от корня к листьям бинарного дерева.
I способ. В данном случае для хранения вершин дерева, которые входят в состав очередного пути, используем динамический одномерный массив. Поскольку максимальная длина из всех имеющихся путей, идущих от корня к листьям, в точности равна высоте дерева плюс один, то размерность массива будет равна этому числу.
/* элемент бинарного дерева */ typedef struct ELEMENT
{
int data;
struct ELEMENT *left, *right; } ELEMENT;
/* вывод на экран очередного пути */ void PrintRoute(ELEMENT **a, long n)
285
{
long i;
for (i = 0; i < n; i++) printf("%d ", a[i]->data);
printf("\n");
}
/* обход элементов бинарного дерева и формирование путей */ void ObhodTree(ELEMENT *q, ELEMENT **a, long level)
{
if (q != NULL)
{
a[level] = q; /* записываем очередную вершину в массив a */ /* если вершина дерева является листом, то выводим
очередной путь на экран
*/
if (q->left == NULL && q->right == NULL) PrintRoute(a, level + 1);
else
{
ObhodTree(q->left, a, level + 1); ObhodTree(q->right, a, level + 1);
}
}
} |
|
|
int main( ) |
|
|
{ |
|
|
ELEMENT *root = NULL; /* корень дерева */ |
|
|
ELEMENT **a; |
/* массив для хранения путей */ |
|
long h; |
/* высота дерева |
*/ |
…/* создание бинарного дерева */ |
|
|
h = Height(root); |
/* вычисляем высоту дерева */ |
|
/* выделяем память для хранения вершин дерева, которые входят в состав очередного пути
*/
a = (ELEMENT **)malloc((h + 1)*sizeof(ELEMENT *));
286
ObhodTree(root, a, 0); free(a);
return 0;
}
II способ. Для решения данной задачи используем дополнительную структуру – двусвязный список, который будет содержать элементы очередного пути бинарного дерева. Функция ObhodTree() работает следующим образом. Если очередная вершина дерева q не нулевая, тогда
1)добавляем адрес вершины q в список;
2)если вершина q является листом, тогда печатаем список, иначе, если вершина q листом не является, тогда рекурсивно
вызываем функцию ObhodTree() для элементов левого поддерева вершины q, а затем для элементов правого поддерева данной вершины;
3) удаляем вершину q из списка.
#include<stdio.h>
#include<stdlib.h>
/* элемент бинарного дерева */ typedef struct TREE_ELEMENT
{
int data;
struct TREE_ELEMENT *left, *right; } TREE_ELEMENT;
/* элемент двусвязного списка */ typedef struct LIST_ELEMENT
{
TREE_ELEMENT *node;
struct LIST_ELEMENT *next, *prev; } LIST_ELEMENT;
/* создание заглавного элемента списка */
void CreateHead(LIST_ELEMENT **head, LIST_ELEMENT **last)
{
287
*head = (LIST_ELEMENT *)malloc(sizeof(LIST_ELEMENT)); (*head)->prev = (*head)->next = NULL;
*last = *head;
}
/* добавление к списку вершины дерева t */
void AddToList(LIST_ELEMENT **last, TREE_ELEMENT *t)
{
LIST_ELEMENT *q;
q = (LIST_ELEMENT *)malloc(sizeof(LIST_ELEMENT)); q->node = t;
q->next = NULL; q->prev = *last; (*last)->next = q; *last = q;
}
/* печать списка (вывод на экран очередного пути) */ void PrintList(LIST_ELEMENT *head)
{
LIST_ELEMENT *q; q = head->next; while (q != NULL)
{
printf("%d ", q->node->data); q = q->next;
}
printf("\n");
}
/* удаление из списка последнего элемента */ void DeleteFromList(LIST_ELEMENT **last)
{
LIST_ELEMENT *q; q = *last;
(*last)->prev->next = NULL; (*last) = q->prev;
288
free(q);
}
/* обход элементов бинарного дерева и формирование путей */ void ObhodTree(TREE_ELEMENT *q, LIST_ELEMENT *head,
LIST_ELEMENT **last)
{
if (q != NULL)
{
AddToList(last, q);
if (q->left == NULL && q->right == NULL) PrintList(head);
else
{
ObhodTree(q->left, head, last); ObhodTree(q->right, head, last);
}
DeleteFromList(last);
}
}
int main( )
{
LIST_ELEMENT *head = NULL, *last = NULL; TREE_ELEMENT *root = NULL;
… /* создание бинарного дерева */ CreateHead(&head, &last); ObhodTree(root, head, &last);
return 0;
}
Пример 11. На каждом уровне бинарного дерева T целых чисел найти минимальный и максимальный элементы.
Пусть min и max – два динамических массива размера h+1, где h – высота дерева T, причем min[i] (max[i]) будет содержать минимальный (максимальный) элемент i-го уровня дерева T, i=0,1,…,h.
289
/*инициализация начальных значений элементов массивов min и max:*/ void InitMinMax(ELEMENT *q, int level, int *min, int *max)
{
if (q)
{
min[level] = max[level] = q->data; InitMinMax(q->left, level+1, min, max); InitMinMax(q->right, level+1, min, max);
}
}
/*поиск минимальных и максимальных элементов на каждом уровне*/ void MinMax(ELEMENT *q, int level, int *min, int *max)
{
if (q)
{
if (q->data < min[level]) min[level] = q->data;
if (q->data > max[level]) max[level] = q->data;
MinMax(q->left, level+1, min, max); MinMax(q->right, level+1, min, max);
}
}
int main( )
{
ELEMENT *root = NULL;
int *min, *max; /* динамические массивы мин. и макс. значений */ int h; /* высота дерева */
…/* формируем дерево T */
h = Height(root); /* вычисляем высоту дерева */
/* выделяем память для динамических массивов min и max: */ min = malloc((h + 1)*sizeof(int));
290