
Лекция 12
Бинарные деревья поиска
Бинарные деревья поиска (БДП) часто используются для представления данных, среди которых идет поиск элемента по ключу.
Если дерево организовано так, что для каждой вершины с адресом t справедливо утверждение: все ключи ее левого поддерева меньше ключа вершины с адресом t, а все ключи ее правого поддерева больше ключа вершины с адресом t, то такое дерево называется бинарным деревом поиска.
В БДП для обнаружения ключа достаточно, начав с корня, двигаться к левому или правому поддереву на основании лишь одного сравнения с ключом текущей вершины.
Предположим, что имеется описание класса, характеризующего БДП:
class bdp
{public:
int b;
char name[20];
bdp *left;
bdp*right;
void create_tree();//создание БДП
void output_tree(bdp *p);//вывод на экран БДП
void search(int key,bdp *p);//поиск элемента в БДП
void insert(bdp obj,bdp *&p);//вставка элемента в БДП
void delete_element(int key,bdp *&p);//удаление элемента из БДП
void delete_tree(bdp *&p);//удаление БДП из памяти компьютера
};
Предположим, что имеются следующие описания:
bdp *head;//указатель на корень дерева
bdp *q;//текущий указатель
Поиск элемента с заданным ключом в БДП
void bdp::search(int key,bdp *p)
{/*функция выводит на экран информационные поля найденного элемента или сообщает, что элемент не найден*/
while(p!=NULL&&p->b!=key)
{if(p->b<key)
p=p->right;
else
p=p->left;
}
if(p==NULL)
cout<<"\nЭлемент не найден";
else
{cout<<"\n------------------------";
cout<<"\n|nomer|name|";
cout<<"\n------------------------";
cout<<"\n"<<setw(6)<<p->b;
cout<<"|"<<setw(10)<<p->name<<"|";
cout<<"\n------------------------\n";
}
getch();
}
Включение элемента с заданным ключом в БДП
void bdp::insert(bdp obj,bdp *&p)
{if(p==NULL)
{p=new bdp;
p->b=obj.b;
strcpy(p->name,obj.name);
p->left=NULL;
p->right=NULL;
}
else
if(obj.b<p->b)
insert(obj,p->left);
else
if(obj.b>p->b)
insert(obj,p->right);
}
Исключение элемента с заданным ключом из БДП
Исключение элемента реализуется просто, если вершина является листом, либо вершиной с одним потомком. Для удаления листа или вершины с одним потомком достаточно скорректироватьссылку у предшествующей вершины. Основная трудность состоит в удалении вершины с двумя потомками. В этом случае нужно найти подходящую вершину, которую можно было бы вставить на место удаляемой. Такой элемент всегда существует: это либо самый правый элемент левого поддерева, либо самый левый элемент правого поддерева.
Алгоритм удаления элемента из БДП должен различать 3 случая:
1.элемента с заданным ключом в дереве нет;
2.элемент с заданным ключом имеет не более одной ветви;
3.элемент с заданным ключом имеет две ветви.
Определим функцию del() , которая заменяет удаляемый элемент с адресом q на самый правый элемент левого поддерева удаляемого элемента, если удаляемый элемент имеет две ветви.
void del(bdp *&r)
{
if(r->right==NULL)
{q->b=r->b;
strcpy(q->name,r->name);
q=r;
r=r->left;
}
else del(r->right);
}
void bdp::delete_element(int key,bdp *&p)
{
if(p==NULL)
cout<<"\nЭлемента нет";
else
if(key<p->b)
delete_element(key,p->left);
else
if(key>p->b)
delete_element(key,p->right);
else
{q=p;
if(q->right==NULL)
p=q->left;
else
if(p->left==NULL)
p=q->right;
else del(q->left);
delete q;
}
}
Вывод значений ключей элементов дерева по возрастанию
void bdp::output_tree(bdp *p)
{if(p!=NULL)
{output_tree(p->left);
cout<<"\n|"<<setw(6)<<p->b;
cout<<"|"<<setw(10)<<p->name;
cout<<"|";
output_tree(p->right);
}
}
Удаление БДП из динамической памяти
void bdp::delete_tree(bdp *&p)
{if(p!=NULL)
{delete_tree(p->left);
delete_tree(p->right);
delete p; p=NULL;
}
}
Создание БДП
void bdp::create_tree()
{int i;
bdp obj;
head=NULL;
for(i=0;i<n;i++)//n – количество вершин в дереве
{cin>>obj.b;
gets(obj.name);
insert(obj,head);
}
}