219 lines
5.5 KiB
C
219 lines
5.5 KiB
C
|
#include <stdint.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
|
|||
|
typedef struct tree {
|
|||
|
int key;//datatype
|
|||
|
struct tree *left, *right;
|
|||
|
struct tree *parent; // необязательное поле
|
|||
|
} tree;
|
|||
|
|
|||
|
|
|||
|
void preorder(tree *root)
|
|||
|
{
|
|||
|
if(root == NULL)
|
|||
|
return;
|
|||
|
printf("%d ",root->key);
|
|||
|
if(root->left)//! NULL
|
|||
|
preorder(root->left);
|
|||
|
if(root->right)//! NULL
|
|||
|
preorder(root->right);
|
|||
|
}
|
|||
|
|
|||
|
void inorder(tree *root) {
|
|||
|
if(root == NULL)
|
|||
|
return;
|
|||
|
if(root->left)
|
|||
|
inorder(root->left);
|
|||
|
printf("%d ",root->key);
|
|||
|
if(root->right)
|
|||
|
inorder(root->right);
|
|||
|
}
|
|||
|
|
|||
|
void postorder(tree *root)
|
|||
|
{
|
|||
|
if(root == NULL)
|
|||
|
return;
|
|||
|
if(root->left)
|
|||
|
postorder(root->left);
|
|||
|
if(root->right)
|
|||
|
postorder(root->right);
|
|||
|
printf("%d ",root->key);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//Вычисляем высоту дерева
|
|||
|
int heightTree(tree* p)
|
|||
|
{
|
|||
|
if (p == NULL)
|
|||
|
return 0;
|
|||
|
else
|
|||
|
{
|
|||
|
/* вычисляем высоту каждого поддерева */
|
|||
|
int lheight = heightTree(p->left);
|
|||
|
int rheight = heightTree(p->right);
|
|||
|
|
|||
|
if (lheight > rheight)
|
|||
|
return (lheight + 1);
|
|||
|
else
|
|||
|
return (rheight + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
//Печатаем все узлы на уровне level
|
|||
|
void printCurrentLevel(tree* root, int level)
|
|||
|
{
|
|||
|
if (root == NULL)
|
|||
|
return;
|
|||
|
if (level == 1)
|
|||
|
printf("%d ", root->key);
|
|||
|
else if (level > 1)
|
|||
|
{
|
|||
|
//если поменять местами то будет обход справа на лево
|
|||
|
printCurrentLevel(root->left, level - 1);
|
|||
|
printCurrentLevel(root->right, level - 1);
|
|||
|
}
|
|||
|
}
|
|||
|
//функция печати
|
|||
|
void printBFS(tree* root)
|
|||
|
{
|
|||
|
int h = heightTree(root);
|
|||
|
for (int i = 1; i <= h; i++)
|
|||
|
printCurrentLevel(root, i);
|
|||
|
}
|
|||
|
|
|||
|
void insert(tree **root,int key, tree *pt) {
|
|||
|
if(!(*root))
|
|||
|
{
|
|||
|
// дерево пустое или дошли до нужного места
|
|||
|
*root=(tree *)calloc(1,sizeof(tree));
|
|||
|
(*root)->key=key;
|
|||
|
(*root)->parent=pt;
|
|||
|
// c calloc строчка ниже не нужа
|
|||
|
(*root)->left=(*root)->right= NULL;
|
|||
|
}
|
|||
|
else if( key < (*root)->key)
|
|||
|
insert( &((*root)->left) ,key,*root);
|
|||
|
else
|
|||
|
insert( &((*root)->right),key,*root);
|
|||
|
}
|
|||
|
|
|||
|
/* Рекурсивная реализация */
|
|||
|
tree* search_tree(tree *root, int key)
|
|||
|
{
|
|||
|
if(root==NULL || root->key == key)
|
|||
|
return root;
|
|||
|
else if(root->key > key)
|
|||
|
return search_tree(root->left, key);
|
|||
|
else
|
|||
|
return search_tree(root->right, key);
|
|||
|
}
|
|||
|
|
|||
|
/* Итеративная версия */
|
|||
|
tree* search_tree_i(tree *root, int key){
|
|||
|
tree *find=root;
|
|||
|
while(find && find->key!=key) {
|
|||
|
if( key < find->key )
|
|||
|
find = find->left;
|
|||
|
else
|
|||
|
find = find->right;
|
|||
|
}
|
|||
|
return find;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
tree * searchKey(tree *root, int key)
|
|||
|
{
|
|||
|
if(!root)
|
|||
|
return NULL;
|
|||
|
if(root->key == key)
|
|||
|
return root;
|
|||
|
if(key < root->key )
|
|||
|
return searchKey(root->left, key);
|
|||
|
return searchKey(root->right, key);
|
|||
|
}
|
|||
|
|
|||
|
tree* min_tree(tree *root)
|
|||
|
{
|
|||
|
tree *find=root;
|
|||
|
while(find && find->left) {
|
|||
|
find = find->left;
|
|||
|
}
|
|||
|
return find;
|
|||
|
}
|
|||
|
|
|||
|
tree* left_follower_key(tree *root) {
|
|||
|
if(root==NULL)
|
|||
|
return root;
|
|||
|
if(root->right)
|
|||
|
return min_tree(root->right);
|
|||
|
else {
|
|||
|
tree *y = root->parent;
|
|||
|
tree *x = root;
|
|||
|
while(y && x==y->right) {
|
|||
|
x = y;
|
|||
|
y = y->parent;
|
|||
|
}
|
|||
|
return y;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Удаление узла из дерева */
|
|||
|
tree* delete(tree *root, tree* pt) {
|
|||
|
tree *remove = NULL, *remove_son;
|
|||
|
/* Нет потомков или один потомок. Удаляем сам узел */
|
|||
|
if(pt->left == NULL || pt->right == NULL)
|
|||
|
remove = pt;
|
|||
|
else
|
|||
|
/* Два потомка. Удаляем его последователя.У последователя только один правый потомок, потому что это самый левый элемент правого поддерева.*/
|
|||
|
remove = left_follower_key(pt);// Всегда только один потомок
|
|||
|
/* Прикрепляем потомка удаляемого элемента к
|
|||
|
родителю, либо делаем этого потомка корнем дерева*/
|
|||
|
if(remove -> left != NULL) // не сработает если это последователь pt
|
|||
|
remove_son = remove->left;
|
|||
|
else
|
|||
|
remove_son = remove->right;
|
|||
|
if( remove_son ) // обновляем родителя у удаляемого потомка
|
|||
|
remove_son->parent = remove->parent;
|
|||
|
if(remove->parent==NULL) // если удаляем корень
|
|||
|
root = remove_son;
|
|||
|
else if (remove == remove->parent->left)
|
|||
|
remove->parent->left = remove_son;
|
|||
|
else
|
|||
|
remove->parent->right = remove_son;
|
|||
|
if(pt != remove)
|
|||
|
pt->key = remove->key;
|
|||
|
return remove;
|
|||
|
}
|
|||
|
|
|||
|
int main()
|
|||
|
{
|
|||
|
tree *tr = NULL;
|
|||
|
insert(&tr,10,NULL);
|
|||
|
insert(&tr,5, NULL);
|
|||
|
insert(&tr,15,NULL);
|
|||
|
insert(&tr,3, NULL);
|
|||
|
insert(&tr,7 ,NULL);
|
|||
|
insert(&tr,13,NULL);
|
|||
|
insert(&tr,18,NULL);
|
|||
|
insert(&tr,1, NULL);
|
|||
|
insert(&tr,6 ,NULL);
|
|||
|
printBFS(tr);
|
|||
|
printf("\n");
|
|||
|
|
|||
|
preorder(tr);
|
|||
|
printf("\n");
|
|||
|
postorder(tr);
|
|||
|
printf("\n");
|
|||
|
inorder(tr);
|
|||
|
printf("\n");
|
|||
|
printBFS(searchKey(tr,15));
|
|||
|
printf("\n");
|
|||
|
tree *del = NULL;
|
|||
|
del = delete(tr,searchKey(tr,15));
|
|||
|
free(del);
|
|||
|
inorder(tr);
|
|||
|
printf("\n");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|