Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Проектирование программ и программирование на С++ Часть 1. Структурное.pdf
Скачиваний:
18
Добавлен:
15.11.2022
Размер:
3.8 Mб
Скачать

Run(p->left); //переход к левому п/д

Run(p->right);//переход к правому п/д

собработка p->data>

}

}

Результаты обхода сверху вниз для дерева поиска (см. рис. 20): 1 3 7 8 12 9 5.

19.10. Формирование дерева

Рассмотрим построение идеально сбалансированного дерева. При построении такого дерева надо распределять узлы таким обра­ зом, чтобы количество узлов в левом и правом поддеревьях отлича­ лось не более чем на единицу.

# include <iostream.h> struct point

{

int data; point*left,*right;

};

point* Tree(int n,point* p)

{

point*r; int nl,nr;

if(n==0){p=NULL;return p;}

nl=n/2;//считаем количество узлов в левом //поддереве

nr=n-nl-l;//считаем количество узлов

//в правом поддереве

r=new point;//создаем новый узел cout«" ?";

cin»r->data; //заполняем информационное

//поле

r->left=Tree(nl,r->left);//формируем //левое поддерево

r->right=Tree(nr,r->right);//формируем //правое поддерево

р=г;//связываем return р;

больше текущего осуществляется в правое поддерево, а меньше теку­ щего - в левое. Ключи не дублируется, поэтому необходимо прове­ рить, существует ли элемент с заданным ключом в дереве, и если су­ ществует, то завершить функцию добавления элемента.

p o i n t *

f i r s t ( i n t d ) //ф о р м и р о в а н и е

п ер в о го

//э л е м е н т а

д е р е в а

 

 

 

 

{

 

 

 

 

 

 

 

p o in t*

p=new

p o i n t ;

 

 

 

p -> k e y = d ;

 

 

 

 

 

p - > l e f t = 0 ;

 

 

 

 

 

p - > r ig h t= 0 ;

 

 

 

 

r e t u r n

p ;

 

 

 

 

 

}

 

 

 

 

 

 

 

//д о б а в л е н и е

эл ем ен та

d в д ер ев о

поиска

P o in t* A d d ( p o in t* r o o t, i n t d)

 

 

{

 

 

 

 

 

 

 

P o in t* p = r o o t, * r;

 

 

 

//ф л а г

для п роверки сущ ествован ия

элем ен та d

b o o l o k = f a ls e ;

 

 

 

w h ile(p & & !ok)

 

 

 

 

{

 

r= p ;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

if(d = = p - > k e y ) o k = tru e ;

 

 

 

 

e l s e

 

 

 

 

 

//п о д д е р е в о

i f ( d < p - > k e y ) p = p - > l e f t ; //п о й т и в л ев о е

e l s e

p = p - > r i g h t ; //п о й т и

в

п р аво е

//п о д д е р е в о

 

 

 

 

 

 

}

 

 

 

 

 

 

 

i f ( o k )

r e t u r n

р ;//н а й д е н о , не

добавл яем

//с о з д а е м

у з е л

 

 

 

p o in t*

q=new

p o i n t ( ) ; //в ы д ел и л и

пам ять

q -> k ey = d ;

 

 

 

 

 

q - > l e f t = 0 ;

 

 

 

 

 

q - > r ig h t = 0 ;

 

 

 

 

//д о б а в л я е м

в л ев о е

п одд ер ево

 

 

i f ( d < r - > k e y ) r - > l e f t = q ;

 

 

//д о б а в л я е м

в п р аво е

п одд ер ево

 

 

e l s e

r - > r i g h t

=q;

 

 

 

r e t u r n

q;

 

 

 

 

 

19.11. Удаление элемента из дерева

Рассмотрим удаление элемента из дерева поиска (см. рис. 21). Следует учитывать следующие случаи:

1.Узла с требуемым ключом в дереве нет.

2.Узел с требуемым ключом является листом, т.е. не имеет потомков.

3.Узел с требуемым ключом имеет одного потомка.

4.Узел с требуемым ключом имеет двух потомков.

Впервом случае необходимо выполнить обход дерева и срав­ нить ключи элементов с заданным значением.

Во втором случае нужно заменить адрес удаляемого элемента ну­ левым. Для этого нужно выполнить обход дерева и заменить адрес

удаляемого элемента нулевым. Например, при удалении элемента с ключом 7 мы меняем левое адресное поле элемента с ключом 8 на 0.

Третий случай похож на второй, так как мы должны заменить адресное поле удаляемого элемента адресом его потомка. Например, при удалении элемента с ключом 8 мы меняем левое адресное поле элемента с ключом 9 на адрес элемента с ключом 7.

Самым сложным является четвертый случай, так как возникает вопрос, каким элементом мы должны заменить удаляемый элемент. Этот элемент должен иметь два свойства. Во-первых, он должен иметь не более одного потомка, а во-вторых, мы должны сохранить упорядоченность ключей, т.е. он должен иметь ключ либо не мень­ ший, чем любой ключ левого поддерева удаляемого узла, либо не больший, чем любой ключ правого поддерева удаляемого узла. Та­ ким свойством обладают два узла: самый правый узел левого подде­ рева удаляемого узла и самый левый узел правого поддерева удаляе­ мого узла. Любым из них и можно заменить удаляемый элемент. Например, при удалении узла 9 его можно заменить узлом 12 (самый левый узел правого поддерева удаляемого узла).

Для удаления будем использовать рекурсивную функцию.

/^вспомогательная переменная для удаления уз­ ла, имеющего двух потомков*/

point *q;

Point* Del(Point* r)

{

/*удаляет узел, имеющий двух потомков, заменяя его правым узлом левого поддерева*/

i f ( r - > r i g h t 1=0) r = D e l ( r - > r i g h t ) ; / / и д е м

/ / в п равое п о д д е р е в о

 

e l s e / /д ош ли д о

с а м о г о п р а в о г о у з л а

{

/ / з а м е н я е м э т и м у з л о м у д а л я е м ы й q - > k e y = r - > k e y ;

q = r ;

r = r - > l e f t ;

}

r e t u r n г;

P o i n t * D e l e t e ( P o i n t * p , i n t KEY)

{

/ / P o i n t * q ;

i f ( p ) / / и щ е м у з е л

i f ( K E Y < p - > k e y ) / / и с к а т ь в л е в о м п о д д е р е в е p - > l e f t = D e l e t e ( p - > l e f t , K E Y ) ;

e l s e i f ( K E Y > p - > k e y ) / / и с к а т ь в п р а в о м

//поддереве

p->right=Delete(p->right, KEY); else//y3en найден

{

/ / у д а л е н и е

q = p ; / / з а п о м н и л и а д р е с у д а л я е м о г о у з л а / / у з е л и м ее т н е б о л е е о д н о г о п о т о м к а с л е в а

i f ( q - > r i g h t = = 0 )

p = q - > l e f t ; / / м е н я е м на п о т о м к а e l s e

/ / у з е л и м е е т н е б о л е е о д н о г о п о т о м к а с п р а в а i f ( q - > l e f t = = 0 )

p = q - > r i g h t ; / / м е н я е м на п о т о м к а e l s e / / у з е л и м е е т д в у х п о т о м к о в

p - > l e f t = D e l ( q - > l e f t ) ; d e l e t e q;

}

r e t u r n p;

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