简介
二叉树(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