0x01数据结构——C语言实现(树)
0x01数据结构——C语言实现(树)
树(tree):
一棵树是一些节点的集合。这个集合可以是空集;若非空,则一棵树由称为根(root)的节点r以及0个或多个非空的(子)树,,…,组成,这些子树种每一颗的根都被来自根r的一条有向边(edge)所连接。每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。
从节点到节点的路径(path)定义为节点,,…,的一个序列,使得对于,节点是节点的父亲。这个路径的长(length)为该路径上的变得条数,即k-1.从每一个节点到它自己有一条长为0的路径。在一颗树中从根到每一个节点恰好存在一条路径。
对任意节点,的深度(depth)为从根到的唯一路径的长。因此,根的深度为0。的高(height)是从到一片树叶的最长路径的长。因此所有树叶的高度都是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;
}