ν°μ€ν 리 λ·°
μλ£κ΅¬μ‘° : Binary Search Tree
dirmathfl 2021. 1. 17. 10:23μ΄μ§ νμ νΈλ¦¬λ₯Ό ꡬννκΈ° μν΄, ꡬκΈμ μ¬λ¬ μ½λλ€μ 보μμ§λ§, λ°μ΄ν° νμ μ μκ΄μμ΄ μ¬μ©ν μ μλ μ½λλ μμλ€. μ΄μ μ΄μ§ κ²μ νΈλ¦¬μ λμ μ리λ μ΄ν΄λ³΄λ€λ, ꡬνμ μ€μ μΌλ‘ κΈμ μ 리ν΄λ³΄κ³ μ νλ€.
BST?
μμ£Ό κ°λ΅νκ² `BST(Binary Search Tree)`μ λν΄ μ€λͺ νμλ©΄, λΆλͺ¨ λ Έλ(Parent Node)λ₯Ό κΈ°μ€μΌλ‘ μΌμͺ½ μμ(Left Child)μ λΆλͺ¨λ³΄λ€ μμ κ°μ΄λ©° μ€λ₯Έμͺ½ μμ(Right Child)μ λΆλͺ¨λ³΄λ€ ν° κ°μ κ°μ§λ€. `μμ μ΄μ§νΈλ¦¬(Complete Binary Tree)`κ° λ κ²½μ° νμμ ν¨μ¨μ±μ λμΌ μ μλ μλ£κ΅¬μ‘°μ΄λ€.
μ½λ
header
#ifndef BST_H
#define BST_H
typedef struct node {
struct node *left;
struct node *right;
char data[0];
} node_t;
typedef struct binary_tree {
node_t *root;
int count;
} bst_t;
bst_t *init_bst();
void free_bst(bst_t *);
void ins_bst(bst_t *, const void *, const void *, int, int (*)(const void *, const void *));
void del_bst(bst_t *, const void *, int, int (*)(const void *, const void *));
void *find_data_in_bst(bst_t *, const void *, int (*)(const void *, const void *));
void list_bst(bst_t *, void (*)(const void *));
#endif
νΈλ¦¬μ κ° λ Έλλ₯Ό λνλ΄λ κ΅¬μ‘°μ²΄μΈ `node_t`λΌλ ꡬ쑰체λ§μΌλ‘λ κΈ°λ₯μ ꡬνν μ μλ€. νμ§λ§ root λ Έλλ₯Ό ν¬μΈν νλ `bst_t` ꡬ쑰체λ₯Ό ν΅ν΄, λ³΄λ€ νΈλ¦¬νκ² μ¬μ©ν μ μκ³ `count`λ₯Ό ν΅ν΄ νμ¬ λ Έλμ μλ₯Ό νμΈν μ μλ€.
init
bst_t *init_bst()
{
bst_t *bst = (bst_t *)malloc(sizeof(bst_t));
if (bst == NULL) {
//error logging.
return NULL;
}
bst->root = NULL;
bst->count = 0;
return bst;
}
λ Έλλ€μ κ΄λ¦¬ν `bst_t` ꡬ쑰체λ μμ κ°μ΄ μ΄κΈ°ν ν μ μλ€.
free
static void free_node(node_t *node)
{
if (node != NULL) {
free_node(node->left);
free_node(node->right);
free(node);
}
}
void free_bst(bst_t *bst)
{
if (bst->root == NULL)
return;
free_node(bst->root);
free(bst);
}
`init`μλ λ¬λ¦¬ `free`μμλ λͺ¨λ λ Έλλ₯Ό μννλ©΄μ ν΄μ νμ¬μΌ νλ€.
insert
static node_t *init_node(const void *data, int data_size)
{
node_t *node= (node_t *)malloc(sizeof(node_t) + data_size);
if (node == NULL) {
// error logging.
return NULL;
}
node->left = node->right = NULL;
memcpy(node->data, data, data_size);
return node;
}
void ins_bst(bst_t *bst, const void *data, const void *key,
int data_size, int (*cmp_node)(const void *, const void *))
{
node_t *parent = NULL;
node_t *temp = NULL;
temp = bst->root;
while (temp) {
if (cmp_node(temp->data, key) == 0)
return;
parent = temp;
if (cmp_node(parent->data, key) > 0)
temp = parent->left;
else
temp = parent->right;
}
node_t *new = init_node(data, data_size);
if (parent) {
if (cmp_node(parent->data, key) > 0)
parent->left = new;
else
parent->right = new;
} else
bst->root = new;
bst->count++;
}
νμ¬ μ½μ νκ³ μ νλ κ°μ λ°λΌ, μ΄λ€ λ Έλλ₯Ό `parent`λ‘ νμ¬μΌ νλμ§ νμνλ€. κ²°κ³Όμ λ°λΌ νμν `parent`μ `child`κ° λλ€. λ§μ½ `parent`λ₯Ό μ°Ύμ§ λͺ»νλ€λ©΄, `root`κ° μλ μνμ΄λ€.
delete
void del_bst(bst_t *bst, const void *key, int data_size, int (*cmp_node)(const void *, const void *))
{
node_t *parent = NULL;
node_t *child = NULL;
node_t *temp = NULL;
if (bst->root == NULL)
return;
temp = bst->root;
while (temp != NULL && cmp_node(temp->data, key) != 0) {
parent = temp;
temp = (cmp_node(temp->data, key) > 0) ? parent->left : parent->right;
}
if (temp == NULL)
return;
if (temp->left == NULL && temp->right == NULL) {
if (parent) {
if (parent->left == temp)
parent->left = NULL;
else
parent->right = NULL;
} else
bst->root = NULL;
} else if (temp->left == NULL || temp->right == NULL) {
child = (temp->left != NULL) ? temp->left : temp->right;
if (parent) {
if (parent->left == temp)
parent->left = child;
else
parent->right = child;
} else
bst->root = child;
} else {
// succesor parent
node_t *s_parent = temp;
node_t *succesor = temp->right;
while (succesor->left != NULL) {
s_parent = succesor;
succesor = succesor->left;
}
if (s_parent->left == succesor)
s_parent->left = succesor->right;
else
s_parent->right = succesor->right;
memcpy(temp->data, succesor->data, data_size);
temp = succesor;
}
bst->count--;
free(temp);
}
`delete`λ λ€λ₯Έ κΈ°λ₯λ€μ λΉν΄ λ€μ 볡μ‘νλ€. μ΄λ 1) μμμ΄ μ‘΄μ¬νμ§ μλ κ²½μ°, 2) μμμ΄ νλ μ‘΄μ¬νλ κ²½μ°, 3) μμμ΄ λ μ‘΄μ¬νλ κ²½μ°μ λ°λΌ μ²λ¦¬ν΄μ£Όμ΄μΌ νκΈ° λλ¬Έμ΄λ€. μ¦ μμ μ½λλ μμ νκ³ μ νλ λ Έλμ μμΉκΉμ§ νμ ν, μμμ μ‘΄μ¬ μ¬λΆμ λ°λΌ μ²λ¦¬νλ κ²μ΄λ€.
find_data
void *find_data_in_bst(bst_t *bst, const void *key, int (*cmp_node)(const void *, const void *))
{
node_t *cur_node = bst->root;
int diff = 0;
while (cur_node) {
diff = cmp_node(cur_node->data, key);
if (diff == 0)
return cur_node->data;
else if (diff > 0)
cur_node = cur_node->left;
else
cur_node = cur_node->right;
}
return NULL;
}
`root`λΆν° μμ°¨μ μΌλ‘ νμνμ¬, μ°Ύκ³ μ νλ κ°μ΄ μλμ§ νμνλ€.
μ 체μ½λ
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bst.h"
bst_t *init_bst()
{
bst_t *bst = (bst_t *)malloc(sizeof(bst_t));
if (bst == NULL) {
//error logging.
return NULL;
}
bst->root = NULL;
bst->count = 0;
return bst;
}
static void free_node(node_t *);
void free_bst(bst_t *bst)
{
if (bst->root == NULL)
return;
free_node(bst->root);
free(bst);
}
static node_t *init_node(const void *, int);
void ins_bst(bst_t *bst, const void *data, const void *key,
int data_size, int (*cmp_node)(const void *, const void *))
{
node_t *parent = NULL;
node_t *temp = NULL;
temp = bst->root;
while (temp) {
if (cmp_node(temp->data, key) == 0)
return;
parent = temp;
if (cmp_node(parent->data, key) > 0)
temp = parent->left;
else
temp = parent->right;
}
node_t *new = init_node(data, data_size);
if (parent) {
if (cmp_node(parent->data, key) > 0)
parent->left = new;
else
parent->right = new;
} else
bst->root = new;
bst->count++;
}
void del_bst(bst_t *bst, const void *key, int data_size, int (*cmp_node)(const void *, const void *))
{
node_t *parent = NULL;
node_t *child = NULL;
node_t *temp = NULL;
if (bst->root == NULL)
return;
temp = bst->root;
while (temp != NULL && cmp_node(temp->data, key) != 0) {
parent = temp;
temp = (cmp_node(temp->data, key) > 0) ? parent->left : parent->right;
}
if (temp == NULL)
return;
if (temp->left == NULL && temp->right == NULL) {
if (parent) {
if (parent->left == temp)
parent->left = NULL;
else
parent->right = NULL;
} else
bst->root = NULL;
} else if (temp->left == NULL || temp->right == NULL) {
child = (temp->left != NULL) ? temp->left : temp->right;
if (parent) {
if (parent->left == temp)
parent->left = child;
else
parent->right = child;
} else
bst->root = child;
} else {
// succesor parent
node_t *s_parent = temp;
node_t *succesor = temp->right;
while (succesor->left != NULL) {
s_parent = succesor;
succesor = succesor->left;
}
if (s_parent->left == succesor)
s_parent->left = succesor->right;
else
s_parent->right = succesor->right;
memcpy(temp->data, succesor->data, data_size);
temp = succesor;
}
bst->count--;
free(temp);
}
void *find_data_in_bst(bst_t *bst, const void *key, int (*cmp_node)(const void *, const void *))
{
node_t *cur_node = bst->root;
int diff = 0;
while (cur_node) {
diff = cmp_node(cur_node->data, key);
if (diff == 0)
return cur_node->data;
else if (diff > 0)
cur_node = cur_node->left;
else
cur_node = cur_node->right;
}
return NULL;
}
static void search_node(node_t *, void (*)(const void *));
void list_bst(bst_t *bst, void (*print_data)(const void *))
{
printf("cur_nodes : %d\n", bst->count);
if (bst->root == NULL)
return;
search_node(bst->root, print_data);
}
/* Private functions */
static node_t *init_node(const void *data, int data_size)
{
node_t *node= (node_t *)malloc(sizeof(node_t) + data_size);
if (node == NULL) {
// error logging.
return NULL;
}
node->left = node->right = NULL;
memcpy(node->data, data, data_size);
return node;
}
static void free_node(node_t *node)
{
if (node != NULL) {
free_node(node->left);
free_node(node->right);
free(node);
}
}
static void search_node(node_t *node, void (*print_data)(const void *))
{
if (node != NULL) {
search_node(node->left, print_data);
print_data(node->data);
search_node(node->right, print_data);
}
}
ν μ€νΈ
#include "bst.h"
#include <string.h>
#include <stdio.h>
typedef struct {
char name[32];
}info;
void init_info(info *t, const char *name)
{
memset(t, 0, sizeof(info));
memcpy(t->name, name, 32);
}
int cmp_name(const void *a, const void *b)
{
return strcmp(((info *)a)->name, ((char *)b));
}
void print_data(const void *a)
{
printf("%s\n", (char *)a);
}
int main()
{
info temp;
init_info(&temp, "TEST1");
bst_t *bst = init_bst();
ins_bst(bst, &temp, "TEST1", sizeof(info), cmp_name);
init_info(&temp, "TEST2");
ins_bst(bst, &temp, "TEST2", sizeof(info), cmp_name);
list_bst(bst, print_data);
printf("-----------\n");
info *test = (info *)find_data_in_bst(bst, "TEST2", cmp_name);
printf("%s\n", test->name);
printf("-----------\n");
del_bst(bst, "TEST2", sizeof(info), cmp_name);
list_bst(bst, print_data);
init_info(&temp, "TEST5");
ins_bst(bst, &temp, "TEST5", sizeof(info), cmp_name);
del_bst(bst, "TEST2", sizeof(info), cmp_name);
del_bst(bst, "TEST5", sizeof(info), cmp_name);
del_bst(bst, "TEST1", sizeof(info), cmp_name);
list_bst(bst, print_data);
free_bst(bst);
}
μμ κ°μ main μμ μ½λλ₯Ό ν΅ν΄, ꡬνν `BST`μ init, insert, delete, find, search, freeκΉμ§ λͺ¨λ κΈ°λ₯λ€μ΄ μ μ μλνλ€λ κ²μ μ μ μλ€. μ¬κ·λ₯Ό μ¬μ©ν΄, λ³΄λ€ κ°λ¨νκ² κΈ°λ₯λ€μ μμ±ν μ μλ€. νμ§λ§ λ°λ³΅λ¬Έμ μ¬μ©νμ¬ κ΅¬νν¨μΌλ‘μ¨ `BST` ꡬνκ³Ό μ리μ λν΄ λ³΄λ€ λͺ ννκ³ , μ§κ΄μ μΌλ‘ μ΄ν΄ν μ μμλ€.
'ποΈββοΈ κΈ°λ° λ€μ§κΈ° > μλ£κ΅¬μ‘°μ μκ³ λ¦¬μ¦' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
μλ£κ΅¬μ‘°: Hash (6) | 2021.01.10 |
---|---|
μκ³ λ¦¬μ¦: μ λ ¬ (0) | 2020.06.17 |
μκ³ λ¦¬μ¦: DFSμ BFS (0) | 2020.06.16 |
μκ³ λ¦¬μ¦: Recursion (0) | 2020.06.16 |
μλ£κ΅¬μ‘°: Linked List (0) | 2020.06.15 |