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

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

树(tree):
一棵树是一些节点的集合。这个集合可以是空集;若非空,则一棵树由称为根(root)的节点r以及0个或多个非空的(子)树\(T_1\),\(T_2\),...,\(T_k\)组成,这些子树种每一颗的根都被来自根r的一条有向边(edge)所连接。每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。

从节点\(n_1\)到节点\(n_k\)的路径(path)定义为节点\(n_1\),\(n_2\),...,\(n_k\)的一个序列,使得对于\(1\leq i<k\),节点\(n_i\)是节点\(n_{i+1}\)的父亲。这个路径的长(length)为该路径上的变得条数,即k-1.从每一个节点到它自己有一条长为0的路径。在一颗树中从根到每一个节点恰好存在一条路径。

对任意节点\(n_i\)\(n_i\)的深度(depth)为从根到\(n_i\)的唯一路径的长。因此,根的深度为0。\(n_i\)的高(height)是从\(n_i\)到一片树叶的最长路径的长。因此所有树叶的高度都是0。一棵树的高等于它的根的高。一棵树的深度等于它的最深的树叶的深度,该深度总是等于这棵树的高。

树的C语言实现:

tree.h

/*
树(tree):
一棵树是一些节点的集合。
这个集合可以是空集;若非空,则一棵树由称为根(root)的节点r以及0个或多个非空的(子)
树T1,T2,...,Tk组成,这些子树种每一颗的根都被来自根r的一条有向边(edge)所连接。
每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。

                    root
                    
                /  /   |   \  ...  \
               T1  T2  T3   T4 ... Tk
*/

#ifndef TREE_H
#define TREE_H

/*
树的节点用孩子兄弟表示法来存储。
*/

typedef enum {
	false = 0,
	true
} BOOL;

struct node;
typedef struct node node;
typedef node *tree;
typedef node *pos;


//根据先序遍历创建一棵树
//输入数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
tree create_tree_preorder(int v[], int left, int right);

//将一颗树置空
tree make_empty(tree T);

//判断树是不是空的
BOOL is_empty(tree T);

//为节点p添加孩子节点x
void add_child(node *p, int x);

//根据先序遍历数组来创建树(先序遍历数组中用'#'来表示空节点)
tree create_by_preorder(int n[], int N);

//先序遍历树
void preorder_traversal(tree T);
//以数组形式打印
//数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
void preorder_traversal1(tree T);

//后序遍历
void postorder_traversal(tree T);

//寻找节点x的位置
pos search(int x, tree T);

//取出节点p的值
int retrieve_p(pos p);

//以层次方式打印输出
void print_tree(tree T);
void output(tree T, int i);

#endif

tree.c

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


struct node {
	int val;
	struct node *child;
	struct node *bro;
};

/*
struct node;
typedef struct node node;
typedef node *tree;
typedef node *pos;
*/



//根据先序遍历创建一棵树, 层与层之间
//输入数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
tree create_tree_preorder(int v[], int left, int right)
{
	if(left>right || v==NULL) 
		return NULL;
	tree T = NULL;
	int i = left;
	if(v[i]!='#' && v[i]!='$' && v[i]!='%') {
		T = (node *)malloc(sizeof(node));
		T->val = v[i];
		i++;
		if(v[i] == '#') {
			i++;
			T->child = NULL;
			T->bro = create_tree_preorder(v, i, right);
		} else if(v[i] == '$') {
			i++;
			T->bro = NULL;
			T->child = create_tree_preorder(v, i, right);
		} else if(v[i] == '%') {
			i++;
			T->bro = NULL;
			T->child = NULL;
		} else {
			T->child = create_tree_preorder(v, i, right);
			while(v[i]!='%') {
				i++;
			}
			i++;
			T->bro = create_tree_preorder(v, i, right);
		}
	}
	return T;
}

//将一颗树置空
tree make_empty(tree T)
{
	if(T!=NULL) {
		make_empty(T->child);
		make_empty(T->bro);
		printf("free node with value %d\n", T->val);
		free(T);
		T = NULL;
	}
	return T;
}

//判断树是不是空的
BOOL is_empty(tree T)
{
	return T == NULL;
}

//为节点p添加孩子节点x
void add_child(node *p, int x)
{
	node *tmp = p->child;
	if(tmp == NULL) {
		tmp = (node *)malloc(sizeof(node));
		tmp->val = x;
		tmp->child = NULL;
		tmp->bro = NULL;
	} else {
		while(tmp->bro != NULL) {
			tmp = tmp->bro;
		}
		tmp->bro = (node *)malloc(sizeof(node));
		tmp->bro->val = x;
		tmp->bro->child = NULL;
		tmp->bro->bro = NULL;
	}
}

//先序遍历树
void preorder_traversal(tree T)
{
	if(T != NULL) {
		printf("%d", T->val);
		tree tmp;
		tmp = T->child;
		while(tmp!=NULL) {
			preorder_traversal(tmp);
			tmp = tmp->bro;
		}
	}
}

//输出一种可以回复成原始树的先序遍历数组
//数组规定如下:如果一个节点没有孩子,他后面接‘#’,如果没有兄弟接‘$’,如果两种情况都有接“%”
void preorder_traversal1(tree T)
{
	tree tmp;
	if(T!=NULL) {
		printf("%d",T->val);
		if(T->child == NULL && T->bro != NULL) {
			printf("#");
		}
		if(T->child != NULL && T->bro == NULL) {
			printf("$");
		}
		if(T->child == NULL && T->bro == NULL) {
			printf("%%");
		}
		tmp = T->child;
		while(tmp!=NULL) {
			preorder_traversal1(tmp);
			tmp = tmp->bro;
		}
	}

}


//后序遍历
void postorder_traversal(tree T)
{
	if(T != NULL) {
		tree tmp;
		tmp = T->child;
		while(tmp!=NULL) {
			postorder_traversal(tmp);
			tmp = tmp->bro;
		}
		printf("%d", T->val);
	}
}


//寻找节点x的位置
pos search(int x, tree T)
{
	if(T!=NULL) {
		if(T->val == x) {
			return T;
		} else {
			tree tmp = T->child;
			while(tmp!=NULL) {
				if((T=search(x, tmp)) != NULL) {
					break;
				}
				tmp = tmp->bro;
			}
		}
	}
	return T;

}

//取出节点p的值
int retrieve_p(pos p)
{
	return p->val;
}

//以层次方式打印输出
void print_tree(tree T)
{
	output(T,0);
}

void output(tree T, int i)//i用来记录节点的深度
{
	if(T != NULL) {
		for(int j = 0; j<i; j++) {
			printf("\t");
		}
		printf("%d\n", T->val);
		tree tmp;
		tmp = T->child;
		i++;
		while(tmp!=NULL) {
			output(tmp,i);//输出各个子树
			tmp = tmp->bro;
		}
	}
}

main.c

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

struct node {
	int val;
	struct node *child;
	struct node *bro;
};

int main()
{
	tree T, T1;
	pos tmp;
	int A[16] = {1,'$',2,8,'#',9,'%',3,5,'%',4,'$',6,'#',7,'%'};
	
	//print_tree(T);
	//preorder_traversal1(T);
	//printf("\n");
	//postorder_traversal(T);
	//printf("\n");
	//pos t = search(2,T);
	//printf("%d\n", t->val);
	T1 = create_tree_preorder(A, 0, 15);
	print_tree(T1);
	preorder_traversal(T1);
	printf("\n");
	tmp = make_empty(T1);
	printf("%d\n", is_empty(tmp));
	print_tree(tmp);
	postorder_traversal(tmp);
	
	return 0;
}
posted @ 2018-07-01 14:38  main_c  阅读(624)  评论(0)    收藏  举报