0x01数据结构——C语言实现(二叉树)
二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子。
二叉树的一个性质是平均二叉树的深度要比N小得多,这个性质有时很重要。分析表明,这个平均深度为,而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值是。
二叉树的C语言实现如下:
binary_tree.h
/*
二叉树(binary Btree):
二叉树是一颗树,其中每个节点都不能有多余两个的儿子。
root
/
left right
二叉树的一个性质是平均二叉树的深度要比N小得多。这个平均深度为O(sqrt(n)),最大深度为N-1。
而对于特殊类型的二叉树,即二叉查找树(binary search Btree),其深度的平均值是O(log n)。
*/
#ifndef BINARY_Btree_H
#define BINARY_Btree_H
/*
二叉树的节点用左右孩子表示法来存储。
*/
typedef enum {
false = 0,
true
} BOOL;
struct node;
typedef struct node node;
typedef node *Btree;
typedef node *pos;
//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Btree create_Btree_preorder(int v[], int begin, int end);
Btree create_Btree(int v[], int *begin, int end);
//将一颗树置空
Btree make_empty(Btree T);
//判断树是不是空的
BOOL is_empty(Btree T);
//为节点p添加孩子节点x
BOOL add_child(node *p, int x);
//合并两棵树T1和T2
Btree union_btree(Btree T1, Btree T2);
//先序遍历树
void preorder_traversal(Btree T);
//以数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Btree T);
//中序遍历
void inorder_traversal(Btree T);
//后序遍历
void postorder_traversal(Btree T);
//寻找节点x的位置
pos search(int x, Btree T);
//输出二叉树的高度
int Btree_height(Btree T);
//输出二叉树总结点数目
int node_sum(Btree T);
//叶子结点数目
int leaves_sum(Btree T);
//取出节点p的值
int retrieve_p(pos p);
//以层次方式打印输出
void print_Btree(Btree T);
void output(Btree T, int i);
#endif
binary_tree.c
#include "binary_tree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int val;
struct node *left;//left child
struct node *right;//right child
};
struct node;
typedef struct node node;
typedef node *Btree;
typedef node *pos;
//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
Btree create_Btree_preorder(int v[], int begin, int end)
{
return create_Btree(v, &begin, end);
}
Btree create_Btree(int v[], int *begin, int end)
{
if((*begin)>end || v==NULL)
return NULL;
Btree T = NULL;
if(v[*begin]!='#') {
T=(node *)malloc(sizeof(node));
T->val = v[*begin];
(*begin)++;
if(v[*begin] == '#') {
T->left = NULL;
(*begin)++;
T->right = create_Btree(v, begin, end);
} else {
T->left = create_Btree(v, begin, end);
(*begin)++;
T->right = create_Btree(v, begin, end);
}
}
return T;
}
//将一颗树置空
Btree make_empty(Btree T)
{
if(T!=NULL) {
make_empty(T->left);
make_empty(T->right);
printf("free node with value %d
", T->val);
free(T);
T = NULL;
}
return T;
}
//判断树是不是空的
BOOL is_empty(Btree T)
{
return (T == NULL);
}
//为节点p添加孩子节点x
BOOL add_child(node *p, int x)
{
if(p->left == NULL) {
p->left = (node*)malloc(sizeof(node));
p->left->val = x;
p->left->left = p->left->right = NULL;
return true;
} else if(p->right == NULL) {
p->right = (node*)malloc(sizeof(node));
p->right->val = x;
p->right->left = p->right->right = NULL;
return true;
} else {
return false;
}
}
//合并两棵树T1和T2
Btree union_btree(Btree T1, Btree T2)
{
Btree T;
if(T1!=NULL && T2!=NULL) {
/*
* 先假设合并后的树根节点是原来两棵树根节点之和
*/
T = (Btree)malloc(sizeof(node));
T->val = T1->val+T2->val;
T->left = T1;
T->right = T2;
} else if(T1 == NULL) {
T = T2;
} else {
T = T1;
}
return T;
}
//先序遍历树
void preorder_traversal(Btree T)
{
if(T!=NULL) {
printf("%d", T->val);
preorder_traversal(T->left);
preorder_traversal(T->right);
}
}
//以先序遍历数组形式打印
//数组规定如下:用'#'来表示空节点
void preorder_traversal1(Btree T)
{
if(T!=NULL) {
printf("%d", T->val);
if(T->left == NULL) {
printf("#");
if(T->right == NULL) {
printf("#");
} else {
preorder_traversal1(T->right);
}
} else {
preorder_traversal1(T->left);
if(T->right == NULL) {
printf("#");
} else {
preorder_traversal1(T->right);
}
}
}
}
//中序遍历
void inorder_traversal(Btree T)
{
if(T!=NULL) {
inorder_traversal(T->left);
printf("%d", T->val);
inorder_traversal(T->right);
}
}
//后序遍历
void postorder_traversal(Btree T)
{
if(T!=NULL) {
postorder_traversal(T->left);
postorder_traversal(T->right);
printf("%d", T->val);
}
}
//寻找节点x的位置
pos search(int x, Btree T)
{
if(T!=NULL) {
if(T->val == x) {
return T;
} else {
pos tmp = NULL;
if(search(x,T->left)==NULL) {
search(x,T->right);
}
return tmp;
}
} else {
return NULL;
}
}
//输出二叉树中某个节点的高度
//对任意节点n_i,n_i的深度(depth)为从根到n_i的唯一路径的长。因此,根的深度为0。
//n_i的高(height)是从n_i到一片树叶的最长路径的长。
//因此所有树叶的高度都是0。一棵树的高等于它的根的高。
//一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。
int Btree_height(Btree T)
{
static int h = -1;
if(T!=NULL) {
if(T->left==NULL && T->right==NULL) {
h=0;
}else {
int h1, h2;
h1 = Btree_height(T->left)+1;
h2 = Btree_height(T->right)+1;
h = (h1>h2?h1:h2);
}
}
return h;
}
//输出二叉树总结点数目
int node_sum(Btree T)
{
int sum = 0;
if(T!=NULL) {
if(T->left==NULL && T->right==NULL) {
sum = 1;
}else {
int sum1, sum2;
sum1 = node_sum(T->left);
sum2 = node_sum(T->right);
sum = sum1+sum2+1;
}
}
return sum;
}
//叶子结点数目
int leaves_sum(Btree T)
{
int sum = 0;
if(T!=NULL) {
if(T->left==NULL && T->right==NULL) {
sum = 1;
}else {
int sum1, sum2;
sum1 = leaves_sum(T->left);
sum2 = leaves_sum(T->right);
sum = sum1+sum2;
}
}
return sum;
}
//取出节点p的值
int retrieve_p(pos p)
{
return p->val;
}
//以层次方式打印输出
void print_Btree(Btree T)
{
output(T,0);
}
void output(Btree T, int i)
{
if(T != NULL) {
for(int j = 0; j<i; j++) {
printf(" ");
}
printf("%d
", T->val);
i++;
if(!(T->left == NULL && T->right == NULL)) {
if(T->left == NULL) {
printf("
");
output(T->right,i);//输出右子树
} else if(T->right == NULL) {
output(T->left,i);//输出左子树
printf("
");
} else {
output(T->left,i);//输出左子树
output(T->right,i);//输出右子树
}
}
}
}
main.c
#include "binary_tree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int A[15]={1,2,4,'#','#',5,'#','#',3,6,'#','#',7,'#','#'};
int B[9] = {1,2,4,'#','#','#',3,'#','#'};
int C[7] = {5,6,'#','#',7,'#','#'};
int h = 0, sum = 0, leaves = 0;
int x = 2;
pos tmp = NULL;
Btree T = create_Btree_preorder(A,0,14);
Btree T1 = create_Btree_preorder(B,0,8);
Btree T2 = create_Btree_preorder(C,0,6);
print_Btree(T);
preorder_traversal(T);
printf("
");
inorder_traversal(T);
printf("
");
postorder_traversal(T);
printf("
");
preorder_traversal1(T);
printf("
");
Btree pos = search(x,T);
h = Btree_height(pos);
printf("height of the node %d: %d
", x,h);
sum = node_sum(T);
printf("this tree has %d node(s)
", sum);
leaves = leaves_sum(T);
printf("this tree has %d leaves
", leaves);
tmp = make_empty(T);
printf("%d
", is_empty(tmp));
print_Btree(T1);
print_Btree(T2);
T = union_btree(T1,T2);
print_Btree(T);
return 0;
}