树的定义用到了递归的思想,即一颗非空的树,其每个子节点也是一棵树的根节点
树的节点
节点的子树个数为度
除叶子节点和根节点的节点是内部节点
节点间的关系
- parent
- child
- sibling
树的其他概念
- level:根节点为第一层,子节点为第二层,以此递推
- depth:树的最大层次
- forest:不相交的树的集合,某个节点的n颗子树就是一个forest
- 有序树:子树是有次序的
树的存储结构
双亲表示法(顺序实现)
每个节点:一个data域,一个parent域
#define MaxSize 100
typedef int DataType
typedef struct treenode_{
DataType data;
int parent; //双亲下标
}TreeNode;
typedef struct tree{
TreeNode nodes[MaxSize];
int r; //根节点下标
int n; //节点个数
}Tree;
扩展:根据==实际需要==增加更多的指针域:firstchild,rightsibling
#define MaxSize 100
typedef int DataType
typedef struct treenode_{
DataType data;
int parent; //双亲下标
int firstchild;
int rihgtsibling;
}TreeNode;
typedef struct tree{
TreeNode nodes[MaxSize];
int r; //根节点下标
int n; //节点个数
}Tree;
孩子表示法
方案一:每个节点存储data域和MaxDegree个child域,其中MaxChild为树的度
#define MaxDegree 10
typedef int DataType
typedef struct treenode_{
DataType Data;
struct treenode_* child[MaxDegree];
}TreeNode;
缺点:对于度比较少或没有度的节点,浪费了空间
方案二:每个节点储存data域和degree属性,以及degree个child域
#define MaxDegree 10
typedef int DataType
typedef struct treenode_{
DataType sata;
int degree;
struct treenode_** child; //child=malloc(sizeof(struct treenode_*)*degree);
}TreeNode;
缺点:每个节点数据结构不同,维护degree也需要时间成本
方案三:把节点存在数组里面,每个节点含data域,firstchild域(指向第一个儿子节点的指针),firstchild域指向的是一个包含该节点所有儿子的链表,每个链表含一个child域(该儿子在数组中的下标),一个next域(下个儿子节点)
#define MaxSize 100
typedef int DataType
typedef struct childnode_{
int Child;
struct childnode_* next;
}ChildNode;
typedef struct treenode_{
DataType data;
ChildNode* firstchild;
}TreeNode;
typedef struct tree_{
TreeNode* nodes[MaxSize];
int r; //根节点下标
int n; //节点数
}Tree;
扩展:根据需要在TreeNode节点中再加个parent域
孩子兄弟表示法
节点包含一个data域,一个firstchild域,一个rightsibling域
typedef int DataType
typedef struct treenode_{
DataType data;
struct treenode_* firstchild,rightsibling;
}TreeNode;
拓展:增加parent域