0x01数据结构——C语言实现(二叉树)

0x01数据结构——C语言实现(二叉树)

二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子。

二叉树的一个性质是平均二叉树的深度要比N小得多,这个性质有时很重要。分析表明,这个平均深度为\(O(\sqrt{N})\),而对于特殊类型的二叉树,即二叉查找树(binary search tree),其深度的平均值是\(O(\log N)\)

二叉树的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\n", 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("\t");
		}
		printf("%d\n", T->val);
		i++;
		if(!(T->left == NULL && T->right == NULL)) {
			if(T->left == NULL) {
				printf("\n");
				output(T->right,i);//输出右子树
			} else if(T->right == NULL) {
				output(T->left,i);//输出左子树
				printf("\n");
			} 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("\n");
	inorder_traversal(T);
	printf("\n");
	postorder_traversal(T);
	printf("\n");
	
	preorder_traversal1(T);
	printf("\n");
	
	Btree pos = search(x,T);
	h = Btree_height(pos);
	printf("height of the node %d: %d\n", x,h);
	
	
	sum = node_sum(T);
	printf("this tree has %d node(s)\n", sum);
	
	leaves = leaves_sum(T);
	printf("this tree has %d leaves\n", leaves);
	
	tmp = make_empty(T);
	printf("%d\n", is_empty(tmp));
	
	print_Btree(T1);
	print_Btree(T2);
	T = union_btree(T1,T2);
	print_Btree(T);
	
	return 0;
}
posted @ 2018-07-01 14:39  main_c  阅读(429)  评论(0)    收藏  举报