forked from UNN/2026-rff_mp
209 lines
4.4 KiB
C
209 lines
4.4 KiB
C
|
|
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
|
|||
|
|
#include "bst.h"
|
|||
|
|
#include "queue.h"
|
|||
|
|
/*
|
|||
|
|
3. Двоичное дерево поиска
|
|||
|
|
Узел — словарь: `{'val': '123', 'left': None, 'right': None}.`
|
|||
|
|
|
|||
|
|
Функции:
|
|||
|
|
|
|||
|
|
def bst_insert(root, name, phone) — рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется).
|
|||
|
|
|
|||
|
|
def bst_find(root, name) — поиск.
|
|||
|
|
|
|||
|
|
def bst_delete(root, name) — удаление, возвращает новый корень.
|
|||
|
|
|
|||
|
|
def bst_list_all(root) — центрированный обход (рекурсивно собирает записи в отсортированном порядке).
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
bst_node* create_bst_node(char name[NAME_LEN], char phone[PHONE_LEN])
|
|||
|
|
{
|
|||
|
|
bst_node* node = (bst_node*)malloc(sizeof(bst_node));
|
|||
|
|
|
|||
|
|
strcpy(node->name, name);
|
|||
|
|
strcpy(node->phone, phone);
|
|||
|
|
|
|||
|
|
node->left = NULL;
|
|||
|
|
node->right = NULL;
|
|||
|
|
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bst_node* bst_minimum(bst_node* node)
|
|||
|
|
{
|
|||
|
|
if (node->left == NULL)
|
|||
|
|
return node;
|
|||
|
|
return bst_minimum(node->left);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bst_node* bst_maximum(bst_node* node)
|
|||
|
|
{
|
|||
|
|
if (node->right == NULL)
|
|||
|
|
return node;
|
|||
|
|
return bst_maximum(node->right);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void print_bst(bst_node node)
|
|||
|
|
{
|
|||
|
|
//printf("value: %d\n", node.value);
|
|||
|
|
|
|||
|
|
printf("name: %s, phone: %s\n", node.name, node.phone);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void bst_inorder_traversal(bst_node* HEAD)
|
|||
|
|
{
|
|||
|
|
if (HEAD != NULL)
|
|||
|
|
{
|
|||
|
|
bst_inorder_traversal(HEAD->left);
|
|||
|
|
print_bst(*HEAD);
|
|||
|
|
bst_inorder_traversal(HEAD->right);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void bst_preorder_traversal(bst_node* HEAD)
|
|||
|
|
{
|
|||
|
|
if (HEAD != NULL)
|
|||
|
|
{
|
|||
|
|
print_bst(*HEAD);
|
|||
|
|
bst_preorder_traversal(HEAD->left);
|
|||
|
|
bst_preorder_traversal(HEAD->right);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bst_node* bst_search(bst_node* HEAD, char target_name[NAME_LEN])
|
|||
|
|
{
|
|||
|
|
/*
|
|||
|
|
Node search(x : Node, k : T):
|
|||
|
|
if x == null or k == x.key
|
|||
|
|
return x
|
|||
|
|
if k < x.key
|
|||
|
|
return search(x.left, k)
|
|||
|
|
else
|
|||
|
|
return search(x.right, k)
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if ((HEAD == NULL) || strcmp(HEAD->name, target_name) == 0)
|
|||
|
|
{
|
|||
|
|
return HEAD;
|
|||
|
|
}
|
|||
|
|
if (strcmp(target_name, HEAD->name) < 0)
|
|||
|
|
{
|
|||
|
|
return bst_search(HEAD->left, target_name);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return bst_search(HEAD->right, target_name);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bst_node* bst_insert(bst_node* HEAD, char name[NAME_LEN], char phone[PHONE_LEN])
|
|||
|
|
{
|
|||
|
|
/*
|
|||
|
|
Node insert(x : Node, z : T): // x — корень поддерева, z — вставляемый ключ
|
|||
|
|
if x == null
|
|||
|
|
return Node(z) // подвесим Node с key = z
|
|||
|
|
else if z < x.key
|
|||
|
|
x.left = insert(x.left, z)
|
|||
|
|
else if z > x.key
|
|||
|
|
x.right = insert(x.right, z)
|
|||
|
|
return x
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
if (HEAD == NULL)
|
|||
|
|
{
|
|||
|
|
return create_bst_node(name, phone);
|
|||
|
|
}
|
|||
|
|
else if (strcmp(name, HEAD->name) < 0)
|
|||
|
|
{
|
|||
|
|
HEAD->left = bst_insert(HEAD->left, name, phone);
|
|||
|
|
}
|
|||
|
|
else if (strcmp(name, HEAD->name) > 0)
|
|||
|
|
{
|
|||
|
|
HEAD->right = bst_insert(HEAD->right, name, phone);
|
|||
|
|
}
|
|||
|
|
return HEAD;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bst_node* bst_delete(bst_node* root, char target_name[NAME_LEN])
|
|||
|
|
{ // корень поддерева, удаляемый ключ
|
|||
|
|
if (root == NULL)
|
|||
|
|
return root;
|
|||
|
|
|
|||
|
|
if (strcmp(target_name, root->name) < 0)
|
|||
|
|
root->left = bst_delete(root->left, target_name);
|
|||
|
|
else if (strcmp(target_name, root->name) > 0)
|
|||
|
|
root->right = bst_delete(root->right, target_name);
|
|||
|
|
else {
|
|||
|
|
if (root->left != NULL && root->right != NULL)
|
|||
|
|
{
|
|||
|
|
strcpy(root->name, bst_minimum(root->right)->name);
|
|||
|
|
strcpy(root->phone, bst_minimum(root->right)->phone);
|
|||
|
|
|
|||
|
|
root->right = bst_delete(root->right, root->name);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bst_node* temp = root;
|
|||
|
|
if (root->left != NULL)
|
|||
|
|
root = root->left;
|
|||
|
|
else
|
|||
|
|
root = root->right;
|
|||
|
|
free(temp);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return root;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void delete_bst(bst_node* root)
|
|||
|
|
{
|
|||
|
|
if (root == NULL)
|
|||
|
|
return;
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
delete_bst(root->left);
|
|||
|
|
delete_bst(root->right);
|
|||
|
|
free(root);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void printTree(bst_node* node, int depth) {
|
|||
|
|
|
|||
|
|
if (node == NULL) return;
|
|||
|
|
|
|||
|
|
printTree(node->right, depth + 1);
|
|||
|
|
|
|||
|
|
for (int i = 0; i < depth; i++)
|
|||
|
|
printf("\t");
|
|||
|
|
//printf("%d\n", node->value);
|
|||
|
|
print_bst(*node);
|
|||
|
|
|
|||
|
|
printTree(node->left, depth + 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void treeLevelTraversal(bst_node* node) {
|
|||
|
|
if (!node) return;
|
|||
|
|
|
|||
|
|
Queue q;
|
|||
|
|
Queue* hq = &q;
|
|||
|
|
queueInit(hq);
|
|||
|
|
|
|||
|
|
queuePush(hq, node);
|
|||
|
|
while(!queueEmpty(hq))
|
|||
|
|
{
|
|||
|
|
bst_node* hn = queuePop(hq);
|
|||
|
|
//printf("%d\n", hn->value);
|
|||
|
|
print_bst(*hn);
|
|||
|
|
|
|||
|
|
if(hn->left)
|
|||
|
|
queuePush(hq, hn->left);
|
|||
|
|
if(hn->right)
|
|||
|
|
queuePush(hq, hn->right);
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
};
|