ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

728x90
๋ฐ˜์‘ํ˜•
์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด, ๊ตฌ๊ธ€์— ์—ฌ๋Ÿฌ ์ฝ”๋“œ๋“ค์„ ๋ณด์•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ ํƒ€์ž…์— ์ƒ๊ด€์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋Š” ์—†์—ˆ๋‹ค. ์ด์— ์ด์ง„ ๊ฒ€์ƒ‰ ํŠธ๋ฆฌ์˜ ๋™์ž‘ ์›๋ฆฌ๋‚˜ ์ดํ•ด๋ณด๋‹ค๋Š”, ๊ตฌํ˜„์„ ์ค‘์ ์œผ๋กœ ๊ธ€์„ ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

 

BST?

 

Binary search tree - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Data structure in tree form sorted for fast lookup A binary search tree of size 9 and depth 3, with 8 at the root. The leaves are not drawn. In computer science, a binary search tree (

en.wikipedia.org

 ์•„์ฃผ ๊ฐ„๋žตํ•˜๊ฒŒ BST(Binary Search Tree)์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์ž๋ฉด, ๋ถ€๋ชจ ๋…ธ๋“œ(Parent Node)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ ์ž์‹(Left Child)์€ ๋ถ€๋ชจ๋ณด๋‹ค ์ž‘์€ ๊ฐ’์ด๋ฉฐ ์˜ค๋ฅธ์ชฝ ์ž์‹(Right Child)์€ ๋ถ€๋ชจ๋ณด๋‹ค ํฐ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค. ์™„์ „์ด์ง„ํŠธ๋ฆฌ(Complete Binary Tree)๊ฐ€ ๋  ๊ฒฝ์šฐ ํƒ์ƒ‰์˜ ํšจ์œจ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

 

์ฝ”๋“œ

#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);
}

 

valgrind ํ…Œ์ŠคํŠธ ๋ฐ ์‹คํ–‰ ๊ฒฐ๊ณผ

 ์œ„์™€ ๊ฐ™์€ main ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด, ๊ตฌํ˜„ํ•œ BST์˜ init, insert, delete, find, search, free๊นŒ์ง€ ๋ชจ๋“  ๊ธฐ๋Šฅ๋“ค์ด ์ •์ƒ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์žฌ๊ท€๋ฅผ ์‚ฌ์šฉํ•ด, ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ธฐ๋Šฅ๋“ค์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•จ์œผ๋กœ์จ BST ๊ตฌํ˜„๊ณผ ์›๋ฆฌ์— ๋Œ€ํ•ด ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๊ณ , ์ง๊ด€์ ์œผ๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๊ธ€ ๋ณด๊ด€ํ•จ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€