数据结构(四) -- 二叉树

简介

二叉树(Binary Tree)的特点时每个父节点最多只能有两个子节点,通常子树被称作“左子树”(Left Subtree)和“右子树”(Right Subtree)。

二叉树的实现详解

树结构

二叉树结点(树结点)包括: 左孩子结点(左子树),右孩子结点(右子树)以及父节点。
每一个结点包含一个存储的数据和一个key属性。
key用于实现结点的查找,其特性如下:
根节点key = 0
左孩子key = 父节点key * 2 + 1
右孩子key = 父节点key * 2 + 2

C语言代码表示

typedef struct node {
    int data;               /*数据*/
    int key;                /*key*/
    struct node *parent;    /*父节点*/
    struct node *left;      /*左孩子*/
    struct node *right;     /*右孩子*/
} Node;

有了结点之后呢,就要实现树的数据结构了,其实很简单,树中只需要有一个根节点就可以了。

C语言代码表示

typedef struct tree {
    Node *root;             /*根节点*/
}Tree;

函数接口

最简单的实现要包括一下几个操作:
1. 创建树
2. 销毁树
3. 插入结点
4. 删除结点
5. 前序遍历
6. 中序遍历
7. 后续遍历

C语言代码表示

Tree *createTree(int data); /*创建树*/
void destoryTree(Tree *tree); /*销毁树*/
int insertNode(Tree *tree, int key, int direction, int data); /*插入结点*/
int deleteNode(Tree *tree, int key); /*删除结点*/
void inorderTraversal(Tree *tree); /*前序遍历*/
void preorderTraversal(Tree *tree); /*中序遍历*/
void postorderTraversal(Tree *tree); /*后序遍历*/

注:创建树时向根节点中加入数据,插入时需要区分方向。

完整实现

tree.h

#ifndef __TREE_H__
#define __TREE_H__

#define LEFT 0
#define RIGHT 1 

typedef struct node {
    int data;               /*数据*/
    int key;                /*key*/
    struct node *parent;    /*父节点*/
    struct node *left;      /*左孩子*/
    struct node *right;     /*右孩子*/
} Node;

typedef struct tree {
    Node *root;             /*根节点*/
}Tree;

Tree *createTree(int data); /*创建树*/
void destoryTree(Tree *tree); /*销毁树*/
int insertNode(Tree *tree, int key, int direction, int data); /*插入结点*/
int deleteNode(Tree *tree, int key); /*删除结点*/
void inorderTraversal(Tree *tree); /*前序遍历*/
void preorderTraversal(Tree *tree); /*中序遍历*/
void postorderTraversal(Tree *tree); /*后序遍历*/

#endif

tree.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tree.h"

static void _deleteNode(Tree *tree, Node *node);
static void _inorderTraversal(Node *node);
static void _preorderTraversal(Node *node);
static void _postorderTraversal(Node *node);

Tree *createTree(int data)
{
    Tree *tree;

    tree = (Tree *)malloc(sizeof(Tree));
    if(NULL == tree) {
        return NULL;
    }
    memset(tree, 0, sizeof(Tree));

    tree->root = (Node *)malloc(sizeof(Node));
    if(NULL == tree->root) {
        free(tree);
        tree = NULL;
        return NULL;
    }
    memset(tree->root, 0, sizeof(Node));

    tree->root->data = data;
    tree->root->key = 0;
    tree->root->parent = NULL;
    tree->root->left = NULL;
    tree->root->right = NULL;

    return tree;
}

void destoryTree(Tree *tree)
{
    _deleteNode(tree, tree->root);
    free(tree);
    tree = NULL;
}

static Node *searchNode(Node *node, int key)
{
    Node *tmpNode;

    if (NULL == node) {
        return NULL;
    }

    if(node->key == key) {
        return node;
    }

    if(node->left) {
        tmpNode = searchNode(node->left, key);
        if(tmpNode) {
            return tmpNode;
        }
    }

    if(node->right) {
        tmpNode = searchNode(node->right, key);
        if(tmpNode) {
            return tmpNode;
        }
    }

    return NULL;
}

int insertNode(Tree *tree, int key, int direction, int data)
{
    Node *newNode;
    Node *tmpNode;

    tmpNode = searchNode(tree->root, key);
    if(NULL == tmpNode) {
        printf("Could not find the node which key is %d\n", key);
        return -1;
    }

    if(LEFT == direction) {
        if(tmpNode->left) {
            printf("Left node is exist, could't insert.\n");
            return -1;
        }

        newNode = (Node *)malloc(sizeof(Node));
        if(NULL == newNode) {
            return -1;
        }
        memset(newNode, 0, sizeof(Node));
        newNode->data = data;
        newNode->key = key * 2 + 1;
        newNode->parent = tmpNode;
        newNode->right = NULL;
        tmpNode->left = newNode;

    } else if(RIGHT == direction) {
        if(tmpNode->right) {
            printf("Left node is exist, could't insert.\n");
            return -1;
        }

        newNode = (Node *)malloc(sizeof(Node));
        if(NULL == newNode) {
            return -1;
        }
        memset(newNode, 0, sizeof(Node));
        newNode->data = data;
        newNode->key = key * 2 + 2;
        newNode->parent = tmpNode;
        newNode->left = NULL;
        tmpNode->right = newNode;

    } else {
        printf("direction[%d] is invalid.\n", direction);
        return -1;
    }

    return 0;
}

int deleteNode(Tree *tree, int key)
{
    Node *tmpNode;

    tmpNode = searchNode(tree->root, key);
    if(NULL == tmpNode) {
        printf("Could not find the node which key is %d\n", key);
        return -1;
    }

    _deleteNode(tree, tmpNode);

    return 0;
}

void preorderTraversal(Tree *tree)
{
    _preorderTraversal(tree->root);
    printf("\n");
}

void inorderTraversal(Tree *tree)
{
    _inorderTraversal(tree->root);
    printf("\n");
}

void postorderTraversal(Tree *tree)
{
    _postorderTraversal(tree->root);
    printf("\n");
}

static void _deleteNode(Tree *tree, Node *node)
{
    if(node->left) {
        _deleteNode(tree, node->left);
    }

    if(node->right) {
        _deleteNode(tree, node->right);
    }

    if(node->parent) {
        if(node->parent->right == node) {
            node->parent->right = NULL;
        } else if(node->parent->left == node) {
            node->parent->left = NULL;
        }
    } else {
        tree->root = NULL;
    }

    free(node);
    node = NULL;
}

static void _preorderTraversal(Node *node)
{
    printf("%d ", node->data);

    if(node->left) {
        _preorderTraversal(node->left);
    }

    if(node->right) {
        _preorderTraversal(node->right);
    }
}

static void _inorderTraversal(Node *node)
{
    if(node->left) {
        _inorderTraversal(node->left);
    }

    printf("%d ", node->data);

    if(node->right) {
        _inorderTraversal(node->right);
    }
}

static void _postorderTraversal(Node *node)
{
    if(node->left) {
        _postorderTraversal(node->left);
    }

    if(node->right) {
        _postorderTraversal(node->right);
    }

    printf("%d ", node->data);
}

测试代码
test.c

#include <stdio.h>
#include <stdlib.h>
#include "tree.h"

/*******************************************
 *              0
 *
 *            /   \
 *
 *          1       2
 *        /   \
 *
 *      3      4  
 *
 * preorder:  0 1 3 4 2 
 * inorder:   3 1 4 0 2
 * postorder: 3 4 1 2 0
 *
 *******************************************/

int main(int argc, char *argv[])
{
    Tree *tree;

    tree = createTree(0);

    insertNode(tree, 0, LEFT, 1);
    insertNode(tree, 0, RIGHT, 2);
    insertNode(tree, 1, LEFT, 3);
    insertNode(tree, 1, RIGHT, 4);

    preorderTraversal(tree);
    inorderTraversal(tree);
    postorderTraversal(tree);

    printf("delete 3\n");
    deleteNode(tree, 3);
    preorderTraversal(tree);

    printf("add 3\n");
    insertNode(tree, 1, LEFT, 3);
    preorderTraversal(tree);

    printf("delete 1 3 4\n");
    deleteNode(tree, 1);
    preorderTraversal(tree);

    destoryTree(tree);

    return 0;
}

Makefile

CC = gcc
CGLAGS = 
PROG = test_tree

all: $(PROG)

$(PROG): tree.o test.o
    $(CC) $(CFLAGS) -o $@ $^

clean:
    rm *.o $(PROG) -rf

测试结果

这里写图片描述

完整代码地址

https://github.com/zsirkg/myWorks/tree/master/algorithms_and_data_structures/tree/binary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值