【数据结构】二叉树

1. 目录结构

├── binary_tree.c
├── Include
│   ├── binary_tree.h
│   ├── Queue
│   │   └── queue.h
│   └── Stack
│       └── stack.h
├── Makefile
├── queue.c
├── stack.c
└── test_binary_tree.c

2. Makefile

.PHONY: clean

CC = gcc
CFLAGS = -g -Wall -DDEBUG -std=c99
C_INCLUDE_PATH = -I ./Include/ -I ./Include/Queue/ -I ./Include/Stack/
#EXTRA_FLAGS = -DUSE_RECURSION

SOURCE = $(wildcard ./*.c)
BIN = test_binary_tree

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

clean:
	rm -rf $(BIN)

3. Include/

3.1 Queue/queue.h

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

#ifndef __QUEUE_H__
#define __QUEUE_H__

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

#ifdef __cplusplus
extern "C" {
#endif

typedef void * queue_data_t;
typedef struct node_s {
    queue_data_t data;
    struct node_s *next;
} node_t;

typedef struct queue_s {
    node_t *front;
    node_t *rear;
    int size;
} queue_t;

void init_queue(queue_t *queue);

int get_queue_size(const queue_t *queue);

int is_queue_empty(const queue_t *queue);

void queue_push(queue_t *queue, queue_data_t data);

void queue_pop(queue_t *queue);

queue_data_t get_front(const queue_t *queue);

queue_data_t get_back(const queue_t *queue);

void destroy_queue(queue_t *queue);

#ifdef __cplusplus
}
#endif

#endif // __QUEUE_H__

3.2 Stack/stack.h

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

#ifndef __STACK_H__
#define __STACK_H__

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_STACK_SIZE 10

typedef void * stack_data_t;
typedef struct stack_s {
    stack_data_t data[MAX_STACK_SIZE];
    int top; /* stack top pointer  */
} stack_t;

void init_stack(stack_t *stack);

int get_stack_size(const stack_t *stack);

int is_stack_empty(const stack_t *stack);

int is_stack_full(const stack_t *stack);

stack_data_t get_stack_top(const stack_t *stack);

void stack_push(stack_t *stack, stack_data_t data);

void stack_pop(stack_t *stack);

void clear_stack(stack_t *stack);

void destroy_stack(stack_t *stack);

#ifdef __cplusplus
}
#endif

#endif // __STACK_H__

3.3 binary_tree.h

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

#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

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

#ifdef __cplusplus
extern "C" {
#endif

typedef char binary_tree_data_t;
typedef struct binary_tree_s {
    binary_tree_data_t data;
    struct binary_tree_s *left;
    struct binary_tree_s *right;
} binary_tree_t;

binary_tree_t *build_binary_tree(binary_tree_data_t array[],
                                 int size,
                                 int *index);

void pre_order(const binary_tree_t *root);

void in_order(const binary_tree_t *root);

void post_order(const binary_tree_t *root);

void level_order(const binary_tree_t *root);

int get_binary_tree_size(const binary_tree_t *root);

int get_binary_tree_leaf_size(const binary_tree_t *root);

int get_binary_tree_k_layer_size(const binary_tree_t *root, int k);

int get_binary_tree_height(const binary_tree_t *root);

binary_tree_t *binary_tree_find_by_data(const binary_tree_t *root,
                                        binary_tree_data_t data);

bool is_complete_binary_tree(const binary_tree_t *root);

void destroy_binary_tree(binary_tree_t *root);

#ifdef __cplusplus
}
#endif

#endif // __BINARY_TREE_H__

4. queue.c

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

#include "queue.h"

void init_queue(queue_t *queue)
{
    queue->front = queue->rear = NULL;
    queue->size = 0;
}

int get_queue_size(const queue_t *queue)
{
    return queue->size;
}

int is_queue_empty(const queue_t *queue)
{
    return 0 == get_queue_size(queue);
}

void queue_push(queue_t *queue, queue_data_t data)
{
    node_t *new_node = (node_t *)calloc(1, sizeof(node_t));
    if (NULL == new_node) {
        perror("calloc new_node fail");
        return;
    }

    new_node->next = NULL;
    new_node->data = data;
    ++queue->size;

    if (NULL == queue->rear) {
        queue->front = queue->rear = new_node;
    } else {
        queue->rear->next = new_node;
        queue->rear = new_node;
    }
}

void queue_pop(queue_t *queue)
{
    if (is_queue_empty(queue)) {
        return;
    }

    node_t *pop_node = queue->front;
    queue->front = pop_node->next;
    free(pop_node);

    --queue->size;

    if (NULL == queue->front) {
        queue->rear = queue->front;
    }
}

queue_data_t get_front(const queue_t *queue)
{
    if (!is_queue_empty(queue) && queue->front) {
        return queue->front->data;
    }

    return NULL;
}

queue_data_t get_back(const queue_t *queue)
{
    if (!is_queue_empty(queue) && queue->rear) {
        return queue->rear->data;
    }

    return NULL;
}

void destroy_queue(queue_t *queue)
{
    node_t *cur = queue->front;
    node_t *next_node = NULL;

    for (; NULL != cur; cur = next_node) {
        next_node = cur->next;
        free(cur);
    }

    queue->front = queue->rear = NULL;
    queue->size = 0;
}

5. stack.c

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

#include "stack.h"

void init_stack(stack_t *stack)
{
    stack->top = 0;
}

int get_stack_size(const stack_t *stack)
{
    return stack->top;
}

int is_stack_empty(const stack_t *stack)
{
    return 0 == get_stack_size(stack);
}

int is_stack_full(const stack_t *stack)
{
    return MAX_STACK_SIZE == get_stack_size(stack);
}

stack_data_t get_stack_top(const stack_t *stack)
{
    return stack->data[stack->top - 1];
}

void stack_push(stack_t *stack, stack_data_t data)
{
    if (is_stack_full(stack)) {
        return;
    }

    stack->data[stack->top++] = data;
}

void stack_pop(stack_t *stack)
{
    if (is_stack_empty(stack)) {
        return;
    }

    --stack->top;
}

void clear_stack(stack_t *stack)
{
    stack->top = 0;
}

void destroy_stack(stack_t *stack)
{
    clear_stack(stack);
}

6. binary_tree.c

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

#include "binary_tree.h"

#include "queue.h"
#include "stack.h"

binary_tree_t *build_binary_tree(binary_tree_data_t array[],
                                 int size,
                                 int *index)
{
    binary_tree_t *root = NULL;

    do {
        if (*index >= size) {
            break;
        }

        // '#' 代表叶子节点
        if ('#' == array[*index]) {
            ++(*index);
            break;
        }

        root = (binary_tree_t *)calloc(1, sizeof(binary_tree_t));
        if (NULL == root) {
            perror("calloc root fail");
            break;
        }

        root->data = array[*index];
        ++(*index);
        root->left = build_binary_tree(array, size, index);
        root->right = build_binary_tree(array, size, index);
    } while (0);

    return root;
}

void pre_order(const binary_tree_t *root)
{
#ifdef USE_RECURSION
    if (NULL != root) {
        printf("%c ", root->data);
        pre_order(root->left);
        pre_order(root->right);
    }
#else
    stack_t stack;
    binary_tree_t *cur = (binary_tree_t *)root;
    binary_tree_t *top = NULL;
    init_stack(&stack);

    // 当右子树为空时, 栈中可能还有元素, 即 此时 可能只是访问了 左子树
    while (NULL != cur || !is_stack_empty(&stack)) {
        while (NULL != cur) {
            // 1, 访问左路节点,左路节点入栈
            printf("%c ", cur->data);
            stack_push(&stack, cur);
            cur = cur->left;
        }

        // 2, 取出栈顶节点,用于访问它的右子树
        top = get_stack_top(&stack);
        stack_pop(&stack);
        // 3, 访问右子树
        cur = top->right;
    }

    destroy_stack(&stack);
#endif /// USE_RECURSION
}

void in_order(const binary_tree_t *root)
{
#ifdef USE_RECURSION
    if (NULL != root) {
        in_order(root->left);
        printf("%c ", root->data);
        in_order(root->right);
    }
#else
    stack_t stack;
    binary_tree_t *cur = (binary_tree_t *)root;
    binary_tree_t *top = NULL;
    init_stack(&stack);

    while (NULL != cur || !is_stack_empty(&stack)) {
        while (NULL != cur) {
            // 1, 左路节点入栈
            stack_push(&stack, cur);
            cur = cur->left;
        }

        // 2, 取出栈顶节点,先访问该节点
        top = get_stack_top(&stack);
        printf("%c ", top->data);
        stack_pop(&stack);
        // 3, 访问它的右子树
        cur = top->right;
    }

    destroy_stack(&stack);
#endif /// USE_RECURSION
}

void post_order(const binary_tree_t *root)
{
#ifdef USE_RECURSION
    if (NULL != root) {
        post_order(root->left);
        post_order(root->right);
        printf("%c ", root->data);
    }
#else
    stack_t stack;
    binary_tree_t *cur = (binary_tree_t *)root;
    binary_tree_t *prev = NULL;
    init_stack(&stack);

    while (NULL != cur || !is_stack_empty(&stack)) {
        while (NULL != cur) {
            // 1, 左路节点入栈
            stack_push(&stack, cur);
            cur = cur->left;
        }

        // 2, 取出栈顶节点
        binary_tree_t *top = get_stack_top(&stack);

        // 3, 栈顶节点的右子树不为空, 并且右子树还没被访问过
        if (NULL != top->right && prev != top->right) {
            cur = top->right;
        } else {
            // 如果栈顶节点的右子树为空, 那么可以直接访问根节点(左右 根)
            // 判断是不是 栈顶节点的右子树已经被访问过了(左右 根)
            printf("%c ", top->data);
            stack_pop(&stack);
            // 更新上一次访问的节点为 top
            prev = top;
        }
    }

    destroy_stack(&stack);
#endif /// USE_RECURSION
}

void level_order(const binary_tree_t *root)
{
    if (NULL == root) {
        return;
    }

    queue_t queue;
    binary_tree_t *queue_front = NULL;
    init_queue(&queue);
    queue_push(&queue, (queue_data_t)root);

    while (!is_queue_empty(&queue)) {
        queue_front = get_front(&queue);
        printf("%c ", queue_front->data);

        queue_pop(&queue);

        if (NULL != queue_front->left) {
            queue_push(&queue, (queue_data_t)queue_front->left);
        }
        if (NULL != queue_front->right) {
            queue_push(&queue, (queue_data_t)queue_front->right);
        }
    }

    destroy_queue(&queue);
}

int get_binary_tree_size(const binary_tree_t *root)
{
    if (NULL == root) {
        return 0;
    }

    return get_binary_tree_size(root->left) +
            get_binary_tree_size(root->right) + 1;
}

int get_binary_tree_leaf_size(const binary_tree_t *root)
{
    if (NULL == root) {
        return 0;
    }

    if (NULL == root->left && NULL == root->right) {
        return 1;
    }

    return get_binary_tree_leaf_size(root->left) +
            get_binary_tree_leaf_size(root->right);
}

int get_binary_tree_k_layer_size(const binary_tree_t *root, int k)
{
    if (NULL == root || k < 1) {
        return 0;
    }

    if (NULL != root && 1 == k) {
        return 1;
    }

    return get_binary_tree_k_layer_size(root->left, k - 1) +
            get_binary_tree_k_layer_size(root->right, k - 1);
}

int get_binary_tree_height(const binary_tree_t *root)
{
    if (NULL == root) {
        return 0;
    }

    int left_height = get_binary_tree_height(root->left);
    int right_height = get_binary_tree_height(root->right);

    return left_height > right_height ?
            left_height + 1 : right_height + 1;
}

binary_tree_t *binary_tree_find_by_data(const binary_tree_t *root,
                                        binary_tree_data_t data)
{
    if (NULL == root || data == root->data) {
        return (binary_tree_t *)root;
    }

    binary_tree_t *found = binary_tree_find_by_data(root->left, data);
    if (NULL != found) {
        return found;
    }

    return binary_tree_find_by_data(root->right, data);
}

bool is_complete_binary_tree(const binary_tree_t *root)
{
    if (NULL == root) {
        return true;
    }

    queue_t queue;
    binary_tree_t *queue_front = NULL;
    init_queue(&queue);
    queue_push(&queue, (queue_data_t)root);

    while (NULL != (queue_front = get_front(&queue))) {
        queue_push(&queue, queue_front->left);
        queue_push(&queue, queue_front->right);
        queue_pop(&queue);
    }

    /* 第一次出现 NULL 后, 后边还会出现其他非 NULL 的节点,
       这时候只需要去判断 队列中的元素是否全为 NULL 即可 */
    while (!is_queue_empty(&queue)) {
        queue_front = get_front(&queue);
        if (NULL != queue_front) {
            destroy_queue(&queue);
            return false;
        }

        queue_pop(&queue);
    }

    destroy_queue(&queue);

    return true;
}

void destroy_binary_tree(binary_tree_t *root)
{
    if (NULL == root) {
        return;
    }

    destroy_binary_tree(root->left);
    destroy_binary_tree(root->right);

    free(root);
    root = NULL;
}

7. test_binary_tree.c

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

#include "binary_tree.h"

void test()
{
    binary_tree_t *root = NULL, *found = NULL;
    int index = 0;

    /* 这里用 # 表示叶子节点,即不再有子节点 */
    /* 先构建 左子树,再构建 右子树 */

    /* Not a complete binary tree */
    /*
             ----------A----------
             +                   +
        -----B              -----C-----
        +                   +         +
        D                   E         F

        pre_order:
            A B D C E F
        in_order:
            D B A E C F
        post_order:
            D B E F C A
        level_order:
            A B C D E F
    */
    char array[] = {
        'A', 'B', 'D', '#', '#', '#', 'C', 'E', '#', '#', 'F'
    };

    /* A complete binary tree */
    // char array[] = {'#'};
    // char array[] = {'A', '#', '#'};
    // char array[] = {'A', 'B', '#', '#', '#', '#'};
    // char array[] = {'A', 'B', '#', '#', 'C', '#', '#'};

    /*
             ----------A----------
             +                   +
        -----B-----         -----C-----
        +         +         +         +
        D         G         E         F

        pre_order:
            A B D G C E F
        in_order:
            D B G A E C F
        post_order:
            D G B E F C A
        level_order:
            A B C D G E F
    */
    // char array[] = {
    //     'A', 'B', 'D', '#', '#', 'G', '#', '#', 'C', 'E', '#', '#', 'F'
    // };

    root = build_binary_tree(array, sizeof(array) / sizeof(char), &index);
    printf("pre_order: \n\t");
    pre_order(root);
    printf("\nin_order: \n\t");
    in_order(root);
    printf("\npost_order: \n\t");
    post_order(root);
    printf("\nlevel_order: \n\t");
    level_order(root);

    found = binary_tree_find_by_data(root, 'G');
    if (NULL == found) {
        printf("\n\nNot Found 'G'\n");
    } else {
        printf("\n\nFound %c\n", found->data);
    }

    if (is_complete_binary_tree(root)) {
        printf("It is complete binary tree\n");
    } else {
        printf("It is not complete binary tree\n");
    }

    printf("\nThe number of nodes in the tree: %d\n", get_binary_tree_size(root));
    printf("The number of nodes in the tree leaf: %d\n", get_binary_tree_leaf_size(root));
    printf("The number of nodes in the %d layer: %d\n", 0, get_binary_tree_k_layer_size(root, 0));
    printf("The number of nodes in the %d layer: %d\n", 1, get_binary_tree_k_layer_size(root, 1));
    printf("The number of nodes in the %d layer: %d\n", 2, get_binary_tree_k_layer_size(root, 2));
    printf("The number of nodes in the %d layer: %d\n", 3, get_binary_tree_k_layer_size(root, 3));
    printf("The number of nodes in the %d layer: %d\n", 4, get_binary_tree_k_layer_size(root, 4));
    printf("Tree height: %d\n", get_binary_tree_height(root));

    printf("\ndestroy_binary_tree\n");
    destroy_binary_tree(root);
    root = NULL;
    printf("Tree height: %d\n", get_binary_tree_height(root));
}

int main(void)
{
    test();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值