Бинарные деревья.
Древовидные иерархические структуры данных широко применяются при классификации различных объектов (например, в биологии). Есть корень дерева, который ссылается на нескольких своих потомков (основных ветвей), те в свою очередь ссылаются на своих потомков (более мелких ветвей) и т.д. Последние потомки ни на кого не ссылаются (они называются листьями). Если у каждого предка не более двух потомков, то дерево называется бинарным.
Каждый узел бинарного дерева удобно хранить в виде следующей структуры
struct Node{
int d;
Node *left;
Node * right;
};
Здесь d – это данное, a left и right – указатели на левое и правое поддерево.
Если бинарное дерево организовано так, что для каждого узла в его левом поддереве все ключи меньше , чем у самого узла, а в правом – больше, то дерево называется деревом поиска.
Привести пример.
Каждое поддерево тоже является деревом, поэтому дерево является рекурсивной структурой данных. Работать с такими данными удобнее всего с помощью рекурсивных алгоритмов.
Пример. Напечатаем дерево.
Печатаем (дерево){
Печатаем (левое поддерево);
Печатаем (корень);
Печатаем (правое поддерево);
}
Для бинарных деревьев должны быть реализованы следующие операции:
Включение узла в дерево
Поиска по дереву
Обхода дерева
Удаления узла.
Для каждой операции можно создать рекурсивный алгоритм или его нерекурсивный аналог.
В качестве примера написаны рекурсивный вариант обхода дерева и нерекурсивный алгоритм поиска вершины с включением.
#include<iostream.h>
struct Node{
int d;
Node *left;
Node * right;
};
Node *first(int d);
Node *search_insert(Node * root,int d);
void print_tree(Node *p,int l);
main(){
int b[]={10,25,20,6,21,8,1,30};
Node *root=first(b[0]);
for(int i=1;i<8;i++){
search_insert(root,b[i]);
}
print_tree(root,0);
return(0);
}
Node *first(int d){
Node *pv=new Node;
pv->d=d;
pv->left = NULL;
pv->right = NULL;
return(pv);
}
Node *search_insert(Node * root, int d){
Node *pv = root;
Node *prev;
int found = 0;
while(pv && !found){
prev = pv;
if( d == pv ->d )
found = 1;
else if( d < pv ->d )
pv = pv -> left;
else
pv = pv -> right;
}
if(found)
return ( pv );
Node *pnew = new Node;
pnew -> d = d;
pnew -> left = NULL;
pnew -> right = NULL;
if( d< prev -> d)
prev -> left = pnew;
else
prev -> right = pnew;
return(pnew);
}
void print_tree( Node *p, int l){
if(p){
print_tree(p->left,l+1);
for(int i=0;i<l;i++)
cout << " ";
cout << p->d << endl;
print_tree(p->right, l+1);
}
}
Упр. Реализовать удаление узла из дерева.
Примечание. Это не очень простая задача. Для узлов, в которых меньше двух ссылок, удаление тривиально. Если в узле две ссылки, то его заменяют на узел с самым близким к нему ключом. Это может быть самый левый узел его правого поддерева или самый правый узел его левого поддерева.
Упр 2. Написать рекурсивный вариант алгоритма поиска вершины с включением.