1.树
树结构是一种非线性存储结构,存储的是具有“一对多”关系的数据元素的集合。

将具有“一对多”关系的集合中的数据元素按照左图的形式进行存储,整个存储形状在逻辑结构上看,类似于实际生活中倒着的树(右图),所以称这种存储结构为“树型”存储结构。
结点:使用树结构存储的每一个数据元素都被称为“结点”。例如,上图中元素 A 就是一个结点;
父结点(双亲结点)、子结点和兄弟结点:对于上图中的结点 A、B、C、D 来说,A 是 B、C、D 结点的父结点(也称为“双亲结点”),而 B、C、D 都是 A 结点的子结点(也称“孩子结点”)。对于 B、C、D 来说,它们都有相同的父结点,所以它们互为兄弟结点。
树根结点(简称“根结点”):每一个非空树都有且只有一个被称为根的结点。上图中,结点 A 就是整棵树的根结点。 树根的判断依据为:如果一个结点没有父结点,那么这个结点就是整棵树的根结点。 叶子结点:如果结点没有任何子结点,那么此结点称为叶子结点(叶结点)。例如上图中,结点 K、L、F、G、M、I、J 都是这棵树的叶子结点。
子树:如上图,整棵树的根结点为结点 A,而如果单看结点 B、E、F、K、L 组成的部分来说,也是棵树,而且节点 B 为这棵树的根结点。所以称 B、E、F、K、L 这几个结点组成的树为整棵树的子树;同样,结点 E、K、L 构成的也是一棵子树,根结点为 E。 注意:单个结点也是一棵树,只不过根结点就是它本身。上图中,结点 K、L、F 等都是树,且都是整棵树的子树。
知道了子树的概念后,树也可以这样定义:树是由根结点和若干棵子树构成的。
空树:如果集合本身为空,那么构成的树就被称为空树。空树中没有结点。 补充:在树结构中,对于具有同一个根结点的各个子树,相互之间不能有交集。例如,图 1(A)中,除了根结点 A,其余元素又各自构成了三个子树,根结点分别为 B、C、D,这三个子树相互之间没有相同的结点。如果有,就破坏了树的结构,不能算做是一棵树。
对于一个结点,拥有的子树数(结点有多少分支)称为结点的度(Degree)。例如,上图中,根结点 A 下分出了 3 个子树,所以,结点 A 的度为 3。 一棵树的度是树内各结点的度的最大值。上图表示的树中,各个结点的度的最大值为 3,所以,整棵树的度的值是 3。
结点的层次:从一棵树的树根开始,树根所在层为第一层,根的孩子结点所在的层为第二层,依次类推。对于上图来说,A 结点在第一层,B、C、D 为第二层,E、F、G、H、I、J 在第三层,K、L、M 在第四层。
2.二叉树
简单地理解,满足以下两个条件的树就是二叉树:
1.本身是有序树;
2.树中包含的各个节点的度不能超过 2,即只能是 0、1 或者 2;

二叉树具有以下几个性质:
1.二叉树中,第 i 层最多有 2i-1 个结点。
2.如果二叉树的深度为 K,那么此二叉树最多有 2K-1 个结点。
3.二叉树中,终端结点数(叶子结点数)为 n0,度为 2 的结点数为 n2,则 n0=n2+1。
2.1满二叉树
如果二叉树中除了叶子结点,每个结点的度都为 2,则此二叉树称为满二叉树。

2.满二叉树中第 i 层的节点数为 2n-1 个。
3.深度为 k 的满二叉树必有 2k-1 个节点 ,叶子数为 2k-1。
4.满二叉树中不存在度为1的节点,每一个分支点中都两棵深度相同的子树,且叶子节点都在最底层。
5.具有 n 个节点的满二叉树的深度为 log2(n+1)。
2.2完全二叉树
如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。

⌊log2n⌋ 表示取小于 log2n 的最大整数。例如,⌊log24⌋ = 2,而 ⌊log25⌋ 结果也是 2。
对具有n个结点的完全二叉树,如果按照从上至下和从左至右的顺序对二 叉树的所有结点从1开始编号,则对于任意的序号为i的结点有:
A.如果i>1,那么序号为i的结点的双亲结点序号为i/2;
B.如果i=1,那么序号为i的结点为根节点,无双亲结点;
C.如果2i<=n,那么序号为i的结点的左孩子结点序号为2i;
D.如果2i>n,那么序号为i的结点无左孩子;
E.如果2i+1<=n,那么序号为i的结点右孩子序号为2i+1;
F.如果2i+1>n,那么序号为i的结点无右孩子。
3.二叉树的顺序存储
基础类型定义
#define MAXSIZE 100 /* 存储空间初始分配量 */
#define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int CElemType;/* 树结点的数据类型,目前暂定为整型 */
typedef CElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点 */
CElemType Nil = 0; /*设整型以0为空 或者以 INT_MAX(65535)*/
typedef struct {
int level; //结点层
int order; //本层的序号(按照满二叉树给定序号规则)
} Position;
3.1 visit数据访问
Status visit(CElemType c){
printf("%d ",c);
return OK;
}
3.2 构造空二叉树T,因为T是固定数组,不会改变.
Status InitBiTree(SqBiTree T){
for (int i=0; i<MAX_TREE_SIZE; i++) {
T[i] = Nil;
}
return OK;
}
3.3 按层序次序输⼊入二叉树中的结点值(字符型或整型),构造顺序存储的二叉树T
Status CreateBiTree(SqBiTree T){
int i = 0;
while (i<10) {
T[i] = i+1;
if (i!=0 && T[(i+1)/2-1] == Nil && T[i] !=Nil) {
printf("出现无双亲的非根结点%d\n",T[i]);
exit(ERROR);
}
i++;
}
//将空赋值给T的后面的结点
while (i<MAX_TREE_SIZE) {
T[i] = Nil;
i++;
}
return OK;
}
3.4 判断⼆叉树是否为空
Status BiTreeEmpty(SqBiTree T){
if (T[0]==Nil) {
return TRUE;
}
return FALSE;
}
3.5 获取⼆叉树的深度
int BiTreeDepth(SqBiTree T){
int j = -1;
int i;
for (i=MAX_TREE_SIZE; i>=0; i--) {
if (T[i]!=Nil) {
break;
}
}
do {
j++;
} while (pow(2, j)<=i);
return j;
}
3.6 返回处于位置e(层,本层序号)的结点值
CElemType Value(SqBiTree T,Position e){
/*
Position.level -> 结点层.表示第几层;
Position.order -> 本层的序号(按照满二叉树给定序号规则)
*/
//第level层 在数组中的起始下标
int i = (int)pow(2, e.level-1) - 1;
printf("%d\n",(int)pow(2,e.level-1));
int j = e.order - 1;
//e.order
printf("%d\n",e.order);
return T[i+j];
}
3.7 获取⼆叉树跟结点的值
Status Root(SqBiTree T,CElemType *e){
if (BiTreeEmpty(T)) {
return ERROR;
}
*e = T[0];
return OK;
}
3.8 给处于位置e的结点赋值
Status Assign(SqBiTree T,Position e,CElemType value){
//找到当前e在数组中的具体位置索引
int i = (int)powl(2, e.level-1)+e.order -2;
//叶子结点的双亲为空
if (value != Nil && T[(i+1)/2-1] == Nil) {
return ERROR;
}
//给双亲赋空值但是有叶子结点
if (value == Nil && (T[i*2+1] != Nil || T[i*2+2] != Nil)) {
return ERROR;
}
T[i] = value;
return OK;
}
3.9 获取e的双亲;
CElemType Parent(SqBiTree T, CElemType e){
//空树
if (T[0]==Nil) {
return Nil;
}
for (int i=0; i<MAX_TREE_SIZE; i++) {
//找到e
if (T[i] == e) {
return T[(i+1)/2-1];
}
}
//没有找到
return Nil;
}
3.10 获取某个结点的左孩⼦;
CElemType LeftChild(SqBiTree T,CElemType e){
//空树
if (T[0]==Nil) {
return Nil;
}
for (int i=0; i<MAX_TREE_SIZE; i++) {
//找到e
if (T[i] == e) {
return T[i*2+1];
}
}
//没有找到
return Nil;
}
3.11 获取某个结点的右孩子;
CElemType RightChild(SqBiTree T,CElemType e){
//空树
if (T[0]==Nil) {
return Nil;
}
for (int i=0; i<MAX_TREE_SIZE; i++) {
//找到e
if (T[i] == e) {
return T[i*2+2];
}
}
//没有找到
return Nil;
}
3.12 获取结点的左兄弟
CElemType LeftSibling(SqBiTree T,CElemType e){
//空树
if (T[0]==Nil) {
return Nil;
}
for (int i=0; i<MAX_TREE_SIZE; i++) {
//找到e且其序号为偶数(是右孩子)
if (T[i] == e && i%2 == 0) {
return T[i-1];
}
}
//没有找到
return Nil;
}
3.13 获取结点的右兄弟
CElemType RightSibling(SqBiTree T,CElemType e){
//空树
if (T[0]==Nil) {
return Nil;
}
for (int i=0; i<MAX_TREE_SIZE; i++) {
//找到e且其序号为奇数(是左孩子)
if (T[i] == e && i%2 == 1) {
return T[i+1];
}
}
//没有找到
return Nil;
}
3.14 层序遍历二叉树
void LevelOrderTraverse(SqBiTree T){
int i = MAX_TREE_SIZE - 1;
while (T[i]==Nil) {
i--;
}
for (int j = 0; j<=i; j++) {
//只遍历非空结点
if (T[j] != Nil)
visit(T[j]);
}
}
3.15 前序遍历二叉树
void PreTraverse(SqBiTree T,int e){
//打印结点数据
visit(T[e]);
//先序遍历左子树
if (T[2*e + 1] != Nil) {
PreTraverse(T, 2*e+1);
}
//最后先序遍历右子树
if (T[2 * e + 2] != Nil) {
PreTraverse(T, 2*e+2);
}
}
Status PreOrderTraverse(SqBiTree T){
//树不为空
if (!BiTreeEmpty(T)) {
PreTraverse(T, 0);
}
printf("\n");
return OK;
}
3.16 中序遍历
void InTraverse(SqBiTree T, int e){
/* 左子树不空 */
if (T[2*e+1] != Nil)
InTraverse(T, 2*e+1);
visit(T[e]);
/* 右子树不空 */
if (T[2*e+2] != Nil)
InTraverse(T, 2*e+2);
}
Status InOrderTraverse(SqBiTree T){
/* 树不空 */
if (!BiTreeEmpty(T)) {
InTraverse(T, 0);
}
printf("\n");
return OK;
}
3.17 后序遍历
void PostTraverse(SqBiTree T,int e)
{ /* 左子树不空 */
if(T[2*e+1]!=Nil)
PostTraverse(T,2*e+1);
/* 右子树不空 */
if(T[2*e+2]!=Nil)
PostTraverse(T,2*e+2);
visit(T[e]);
}
Status PostOrderTraverse(SqBiTree T)
{
if(!BiTreeEmpty(T)) /* 树不空 */
PostTraverse(T,0);
printf("\n");
return OK;
}
4. 二叉树的链式存储
基础类型定义
typedef char CElemType;
CElemType Nil=' '; /* 字符型以空格符为空 */
typedef struct BiTNode /* 结点结构 */
{
CElemType data; /* 结点数据 */
struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode,*BiTree;
4.1 打印数据
Status visit(CElemType e) {
printf("%c ",e);
return OK;
}
4.2 构造空二叉树T
Status InitBiTree(BiTree *T) {
*T=NULL;
return OK;
}
4.3 销毁二叉树
void DestroyBiTree(BiTree *T) {
if (*T) {
//如果有左孩子
if ((*T)->lchild) {
//销毁左孩子
DestroyBiTree(&(*T)->lchild);
}
if ((*T)->rchild) {
DestroyBiTree(&(*T)->rchild);
}
//释放根结点
free(*T);
//赋值为空
*T=NULL;
}
}
4.4 创建二叉树
//按前序输入二叉树中的结点值(字符),#表示空树;
void CreateBiTree(BiTree *T) {
CElemType ch;
//获取字符
ch = str[indexs++];
//判断当前字符是否为'#'
if (ch == '#') {
*T = NULL;
} else {
//创建新的结点
*T = (BiTree)malloc(sizeof(BiTNode));
//是否创建成功
if (!*T) {
exit(OVERFLOW);
}
/* 生成根结点 */
(*T)->data = ch;
/* 构造左子树 */
CreateBiTree(&(*T)->lchild);
/* 构造右子树 */
CreateBiTree(&(*T)->rchild);
}
}
4.5 二叉树T是否为空
Status BiTreeEmpty(BiTree T)
{
if(T) {
return FALSE;
}
else {
return TRUE;
}
}
4.6 二叉树T的深度
int BiTreeDepth(BiTree T){
if (!T) {
return 0;
}
int i,j;
//计算左孩子的深度
if (T->lchild) {
i = BiTreeDepth(T->lchild);
} else {
i = 0;
}
//计算右孩子的深度
if (T->rchild) {
j = BiTreeDepth(T->rchild);
} else {
j = 0;
}
//比较i和j
return i>j ? i+1 : j+1;
}
4.7 二叉树T的根
CElemType Root(BiTree T){
if (BiTreeEmpty(T))
return Nil;
return T->data;
}
4.8 返回p所指向的结点值
CElemType Value(BiTree p){
return p->data;
}
4.9 给p所指结点赋值为value
void Assign(BiTree p,CElemType value)
{
p->data=value;
}
4.10 前序递归遍历T
void PreOrderTraverse(BiTree T)
{
if(T==NULL)
return;
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
}
4.11 中序递归遍历T
void InOrderTraverse(BiTree T)
{
if(T==NULL)
return ;
InOrderTraverse(T->lchild); /* 中序遍历左子树 */
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
}
4.12 后序递归遍历T
void PostOrderTraverse(BiTree T)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild); /* 先后序遍历左子树 */
PostOrderTraverse(T->rchild); /* 再后序遍历右子树 */
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
}