【数据结构】二叉搜索树

1. Makefile

.PHONY: clean

CC = gcc
CFLAGS = -g -Wall -DDEBUG -std=c99

SOURCE = $(wildcard ./*.c)
BIN = $(patsubst %.c, %, $(notdir $(SOURCE)))

$(BIN): $(SOURCE)
	$(CC) $(CFLAGS) $(SOURCE) -o $@

clean:
	rm -rf $(BIN)

2. binary_search_tree.h

/*
* File Name: binary_search_tree.h
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#ifndef __BINARY_SEARCH_TREE_H__
#define __BINARY_SEARCH_TREE_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef int binary_search_tree_data_t;
typedef struct binary_search_tree_s {
    binary_search_tree_data_t data;
    struct binary_search_tree_s *left;
    struct binary_search_tree_s *right;
} binary_search_tree_t;

bool binary_search_tree_insert_data(binary_search_tree_t **root,
                                    binary_search_tree_data_t data);

bool binary_search_tree_insert_data_recursion(binary_search_tree_t **root,
                                              binary_search_tree_data_t data);

binary_search_tree_t *binary_search_tree_find_data(
        const binary_search_tree_t *root,
        binary_search_tree_data_t data);

binary_search_tree_t *binary_search_tree_find_data_recursion(
        const binary_search_tree_t *root,
        binary_search_tree_data_t data);

bool binary_search_tree_remove_data(binary_search_tree_t **root,
                                    binary_search_tree_data_t data);

bool binary_search_tree_remove_data_recursion(binary_search_tree_t **root,
                                              binary_search_tree_data_t data);

void binary_search_tree_in_order_recursion(const binary_search_tree_t *root);

void destroy_binary_search_tree(binary_search_tree_t **root);

#ifdef __cplusplus
}
#endif

#endif // __BINARY_SEARCH_TREE_H__

3. binary_search_tree.c

/*
* File Name: binary_search_tree.c
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#include "binary_search_tree.h"

static binary_search_tree_t *create_binary_search_tree(binary_search_tree_data_t data)
{
    binary_search_tree_t *new_binary_search_tree = NULL;

    do {
        new_binary_search_tree = (binary_search_tree_t *)calloc(
                1, sizeof(binary_search_tree_t));
        if (NULL == new_binary_search_tree) {
            perror("calloc new_binary_search_tree fail");
            break;
        }

        new_binary_search_tree->data = data;
        new_binary_search_tree->left = new_binary_search_tree->right = NULL;
    } while (0);

    return new_binary_search_tree;
}

bool binary_search_tree_insert_data(binary_search_tree_t **root,
                                    binary_search_tree_data_t data)
{
    if (NULL == *root) {
        *root = create_binary_search_tree(data);
        return NULL != *root;
    }

    binary_search_tree_t *cur = *root;
    // 记录待插入节点的父节点
    binary_search_tree_t *parent = NULL;

    while (NULL != cur) {
        parent = cur;

        if (data == cur->data) {
            return false;
        } else if (data < cur->data) {
            cur = cur->left;
        } else {
            cur = cur->right;
        }
    }

    if (data < parent->data) {
        // 要插入的节点 连接到 左子树
        parent->left = create_binary_search_tree(data);
    } else if (data > parent->data) {
        parent->right = create_binary_search_tree(data);
    }

    return true;
}

bool binary_search_tree_insert_data_recursion(binary_search_tree_t **root,
                                              binary_search_tree_data_t data)
{
    if (NULL == *root) {
        *root = create_binary_search_tree(data);
        return NULL != *root;
    }

    if (data == (*root)->data) {
        return false;
    } else if (data < (*root)->data) {
        return binary_search_tree_insert_data_recursion(&((*root)->left), data);
    } else {
        return binary_search_tree_insert_data_recursion(&((*root)->right), data);
    }
}

binary_search_tree_t *binary_search_tree_find_data(
        const binary_search_tree_t *root,
        binary_search_tree_data_t data)
{
    if (NULL == root) {
        return NULL;
    }

    binary_search_tree_t *cur = (binary_search_tree_t *)root;
    while (NULL != cur) {
        if (data == cur->data) {
            return cur;
        } else if (data < cur->data) {
            cur = cur->left;
        } else {
            cur = cur->right;
        }
    }

    return NULL;
}

binary_search_tree_t *binary_search_tree_find_data_recursion(
        const binary_search_tree_t *root,
        binary_search_tree_data_t data)
{
    if (NULL == root || data == root->data) {
        return (binary_search_tree_t *)root;
    }

    if (data < root->data) {
        return binary_search_tree_find_data_recursion(root->left, data);
    } else {
        return binary_search_tree_find_data_recursion(root->right, data);
    }
}

bool binary_search_tree_remove_data(binary_search_tree_t **root,
                                    binary_search_tree_data_t data)
{
    binary_search_tree_t *cur = *root;
    binary_search_tree_t *parent = NULL;

    while (NULL != cur) {
        if (data == cur->data) {
            if (NULL == cur->left) { /* 左孩子为空 */
                if (cur != *root) {
                    if (cur == parent->left) {
                        parent->left = cur->right;
                    } else {
                        parent->right = cur->right;
                    }
                } else {
                    *root = cur->right;
                }

                free(cur);
            } else if (NULL == cur->right) { /* 右孩子为空 */
                if (cur != *root) {
                    if (cur == parent->left) {
                        parent->left = cur->left;
                    } else {
                        parent->right = cur->left;
                    }
                } else {
                    *root = cur->left;
                }

                free(cur);
            } else {
                // 右子树中的最小节点
                binary_search_tree_t *min_right = cur->right;
                // 右子树中最小节点的父节点
                binary_search_tree_t *min_right_parent = cur;

                while (NULL != min_right->left) {
                    min_right_parent = min_right;
                    min_right = min_right->left;
                }

                cur->data = min_right->data;

                // 此时 min_right 的 左孩子是空, 因此需要连接 min_right->right
                if (min_right != min_right_parent->left) {
                    min_right_parent->right = min_right->right;
                } else {
                    min_right_parent->left = min_right->right;
                }

                free(min_right);
            }

            return true;
        } else {
            parent = cur;
        }

        if (data < cur->data) {
            cur = cur->left;
        } else {
            cur = cur->right;
        }
    }

    return false;
}

bool binary_search_tree_remove_data_recursion(binary_search_tree_t **root,
                                              binary_search_tree_data_t data)
{
    if (NULL == root) {
        return false;
    }

    if (data < (*root)->data) {
        return binary_search_tree_remove_data_recursion(
                &((*root)->left), data);
    } else if (data > (*root)->data) {
        return binary_search_tree_remove_data_recursion(
                &((*root)->right), data);
    } else {
        if (NULL == (*root)->left) { /* 左孩子为空 */
            binary_search_tree_t *tmp = *root;
            // 连接 右子树即可
            *root = (*root)->right;
            free(tmp);
        } else if (NULL == (*root)->right) { /* 右孩子为空 */
            binary_search_tree_t *tmp = *root;
            // 连接 左子树即可
            *root = (*root)->left;
            free(tmp);
        } else { /* 左右孩子 均不为空 */
            // 右 > 根 > 左, 因此需要该问题化简为: 查找右子树中的最小节点
            binary_search_tree_t *min_right = (*root)->right;

            // 找到 右子树中 最小的节点, 也就是 右子树中最左边那个节点
            while (NULL != min_right->left) {
                min_right = min_right->left;
            }

            // 用 右子树中最小的节点 替换 要删除的节点
            (*root)->data = min_right->data;
            // 删除右子树中最小的节点
            binary_search_tree_remove_data_recursion(&((*root)->right), min_right->data);
        }

        return true;
    }
}

void binary_search_tree_in_order_recursion(const binary_search_tree_t *root)
{
    if (NULL != root) {
        binary_search_tree_in_order_recursion(root->left);
        printf("%d ", root->data);
        binary_search_tree_in_order_recursion(root->right);
    }
}

void destroy_binary_search_tree(binary_search_tree_t **root)
{
    if (NULL == *root) {
        return;
    }

    destroy_binary_search_tree(&((*root)->left));
    destroy_binary_search_tree(&((*root)->right));

    free(*root);
    *root = NULL;
}

4. test_binary_search_tree.c

/*
* File Name: test_binary_search_tree.c
*
* Copyright (c) 2022, c code from sustzc.
* All rights reserved.
*/

#include "binary_search_tree.h"

void test()
{
    binary_search_tree_t *root = NULL;
    int i = 0;

    printf("Insert data to binary search tree\n");

    if (!binary_search_tree_insert_data(&root, 5)) {
        printf("binary_search_tree_insert_data 5 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data(&root, 2)) {
        printf("binary_search_tree_insert_data 2 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data(&root, 3)) {
        printf("binary_search_tree_insert_data 3 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data(&root, 8)) {
        printf("binary_search_tree_insert_data 8 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data(&root, 9)) {
        printf("binary_search_tree_insert_data 9 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data(&root, 5)) {
        printf("binary_search_tree_insert_data 5 failed(line: %d)\n", __LINE__);
    }

    if (!binary_search_tree_insert_data_recursion(&root, 1)) {
        printf("binary_search_tree_insert_data_recursion 1 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data_recursion(&root, 7)) {
        printf("binary_search_tree_insert_data_recursion 7 failed(line: %d)\n", __LINE__);
    }
    if (!binary_search_tree_insert_data_recursion(&root, 5)) {
        printf("binary_search_tree_insert_data_recursion 5 failed(line: %d)\n", __LINE__);
    }

    printf("in_order binary_search_tree(recursion):\n");
    binary_search_tree_in_order_recursion(root);

    printf("\n\nFind data (0 ~ 9):\n");
    for (i = 0; i < 10; i++) {
        binary_search_tree_t *found = binary_search_tree_find_data(root, i);
        printf("data: %d, find result : %s\n", i, found ? "found" : "not found");
    }

    printf("\n\nFind data recursion (0 ~ 9):\n");
    for (i = 0; i < 10; i++) {
        binary_search_tree_t *found = binary_search_tree_find_data_recursion(root, i);
        printf("data: %d, find result : %s\n", i, found ? "found" : "not found");
    }

    printf("\nDelete data to binary search tree\n");

    printf("\nRemove 2\n");
    if (!binary_search_tree_remove_data(&root, 2)) {
        printf("binary_search_tree_remove_data 2 failed(line: %d)\n", __LINE__);
    }
    printf("in_order binary_search_tree(recursion):\n");
    binary_search_tree_in_order_recursion(root);

    printf("\nRemove 66\n");
    if (!binary_search_tree_remove_data(&root, 66)) {
        printf("binary_search_tree_remove_data 66 failed(line: %d)\n", __LINE__);
    }
    printf("in_order binary_search_tree(recursion):\n");
    binary_search_tree_in_order_recursion(root);

    printf("\nRemove 5\n");
    if (!binary_search_tree_remove_data_recursion(&root, 5)) {
        printf("binary_search_tree_remove_data_recursion 5 failed(line: %d)\n", __LINE__);
    }
    printf("in_order binary_search_tree(recursion):\n");
    binary_search_tree_in_order_recursion(root);

    printf("\ndestroy_binary_search_tree\n");
    destroy_binary_search_tree(&root);
    printf("in_order binary_search_tree(recursion):\n");
    binary_search_tree_in_order_recursion(root);
}

int main(void)
{
    test();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值