lab10

advertisement
Лабораторная работа № 10
Деревья
1. ЦЕЛЬ РАБОТЫ:
структурами
получение навыков
работы с древовидными
2. ОСНОВНЫЕ СВЕДЕНИЯ
Дерево – это совокупность узлов и соединяющих их ветвей, причем в
каждый узел (за исключением одного - корня) ведет ровно одна ветвь.
Корень – это начальный узел дерева, в который не ведет ни одной ветви.
Предком для узла x называется узел дерева, из которого существует путь в
узел x. (потомок – наоборот)
Родителем для узла x называется узел дерева, из которого существует
непосредственная ветка в узел x. (сын – наоборот)
Листом дерева называется узел, не имеющий потомков.
Рассмотрим двоичное дерево
Двоичным деревом называется дерево, каждый узел которого имеет не
более двух сыновей.
Полным двоичным деревом называется дерево, у которого каждая
внутренняя вершина имеет непустые левое и правое поддеревья.
struct tree {
char data[80];
tree *l, *r;
};
Деревья очень удобны для поиска в них информации. Однако для быстрого
поиска требуется предварительная подготовка – дерево надо построить
специальным образом.
Значения всех вершин левого поддерева вершины x меньше x, а значения
всех вершин правого поддерева x больше или равно вершины x.
65, 120, 70, 40, 10, 45, 155
65
40
10
120
45
70
155
Построение дерева
Сравнить очередной элемент массива с ключом корня.
Если новый элемент меньше, включить его в левое поддерево, если больше
или равен, то в правое.
Если текущее дерево пустое, создать новую вершину и включить в дерево.
Удобно строить деревья с помощью рекурсии
void add (tree * &t, int data) {
if ( !t ) {
t = new tree;
t->key = data;
t->l = t->r = NULL;
return;
}
if ( data < t->key )
add( t->l, data );
else add ( t->r, data );
}
Одной из необходимых операций при работе с деревьями является
обход дерева, во время которого надо посетить каждый узел по одному разу
и (возможно) вывести информацию, содержащуюся в вершинах. Пример –
левое поддерево, корень, правое поддерево – узлы будут выведены в порядке
возрастания.
void print_t(tree *t)
{
if ( !t ) return;
print_t(t->l);
printf("%d ", t->key);
print_t(t->r);
}
Поиск по дереву
Сначала проверяем ключ корня, если он равен искомому, то нашли. Если он
меньше искомого, ищем в левом поддереве корня, если больше – то в правом.
Приведенная функция возвращает адрес нужной вершины, если поиск
успешный, и NULL, если требуемый элемент не найден.
tree * search (tree * t, int x) {
if ( ! t ) return NULL;
if ( x == t->key ) return t;
if ( x < t->key )
return search ( t->l, x );
return search ( t->r, x );
}
int main(){
tree *p=NULL, *t;
int m[80]={65, 120, 70, 40, 10, 45, 155};
int i;
for(i=0; i<7; i++)
add(p,m[i]);
print_t(p);
t=search(p,45);
if(t) cout<<t->key;
else cout<< "no found";
getch();
}
4. ВЫПОЛНЕНИЕ РАБОТЫ
a) Написать функцию построения двоичного дерева, содержащего
структуры. Структура содержит фамилию спортсмена, вид спорта,
количество очков. Добавлять новые записи так, чтобы они были
упорядочены фамилиям спортсменов.
b) Написать функцию обхода дерева.
c) Написать функцию поиска по заданной фамилии спортсмена.
5. КОНТРОЛЬНЫЕ ВОПРОСЫ
1.
2.
3.
4.
5.
Из каких узлов состоит дерево?
Какое дерево называется двоичным? Полным двоичным?
Объясните алгоритм построения двоичного дерева.
Объясните алгоритм обхода двоичного дерева.
Объясните алгоритм поиска в двоичном дереве.
Download