二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分。
下面我们来看看二叉树的抽象数据类型实现
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef char TElemType;
typedef int Status;
typedef struct BiTNode {
TElemType data; //数据域
struct BiTNode *lChild, *rChild; //左右孩子指针域
} BiTNode, *BiTree; //二叉链表
其中每个结点都含有一个数据域还有两个指针域,用来抽象的表示左右孩子的地址。
下面我们来看看二叉树的几个基本操作。
Status InitBiTree(BiTree &T) { //创建一棵空的二叉树
T = (BiTree) malloc(sizeof(BiTree));
if (NULL == T) return OVERFLOW;
T->data = NULL;
T->lChild = NULL;
T->rChild = NULL;
return OK;
}
BiTree CreateBiTree(char *defBT, int &i) { //先序创建一个二叉树
BiTree T;
TElemType c;
c = defBT[i++];
if ('#' == c)
InitBiTree(T);
else {
T = MakeBiTree(c, NULL, NULL); //构造结点e
T->lChild = CreateBiTree(defBT, i); //构造左子树
T->rChild = CreateBiTree(defBT, i); //构造右子树
}
return T;
}
BiTree MakeBiTree(TElemType e, BiTree L, BiTree R) { //创建一棵二叉树T,其中根节点的值为e,L和R分别作为左子树和右子树
BiTree T = (BiTree) malloc(sizeof(BiTree));
if (NULL == T)
return NULL;
T->data = e;
T->lChild = L;
T->rChild = R;
return T;
}
void DestroyBiTree(BiTree &T) { //销毁二叉树
if (NULL == T)
return;
DestroyBiTree(T->lChild);
DestroyBiTree(T->rChild);
free(T);
}
int Depth(BiTree T) { //树的深度
if (T == NULL)
return 0;
else {
int m = Depth(T->lChild);
int n = Depth(T->rChild);
if (m > n)
return m + 1;
else
return n + 1;
}
}
Status BiTreeEmpty(BiTree T) { //对二叉树判空,若为空返回TRUE,否则返回False
if (NULL == T) return TRUE;
return FALSE;
}
int NodeCount(BiTree T) {//统计二叉树中结点的个数
if (T == NULL)
return 0;
else
return NodeCount(T->lChild) + NodeCount(T->rChild) + 1;
}
Status BreakBiTree(BiTree &T, BiTree &L, BiTree &R) { //将一棵二叉树T分解为成根,左子树和右子树3个部分
L->rChild = T->lChild;
R->rChild = T->rChild;
T->rChild = NULL;
T->lChild = NULL;
return OK;
}
Status ReplaceLeft(BiTree &T, BiTree <) { //替换左子树 若T非空,则用RT替换T的左子树,并用LT返回T的原有左子树
BiTree temp;
if (NULL == T) return ERROR;
temp = T->lChild;;
T->lChild = LT;
LT = temp;
return OK;
}
int LeafCount(BiTree T) {//统计二叉树中叶子结点的个数
if (!T) return 0;
if (!T->lChild && !T->rChild) { //如果二叉树左子树和右子树皆为空,说明该二叉树根节点为叶子节点,加1.
return 1;
} else {
return LeafCount(T->lChild) + LeafCount(T->rChild);
}
}
Status ReplaceRight(BiTree &T, BiTree &RT) { //替换右子树 若T非空,则用RT替换T的右子树,并用LT返回T的原有右子树
BiTree temp;
if (NULL == T) return ERROR;
temp = T->rChild;;
T->rChild = RT;
RT = temp;
return OK;
}
下面是需要重点掌握的使用递归算法的先序,中序,后序遍历二叉树。
Status visit(TElemType e) { //遍历二叉树打印便利的值的函数
printf("%d", e);
return OK;
}
Status InorderTraverse(BiTree T, Status(*visit)(TElemType e)) { //中序遍历二叉树T,visit是对数据元素操作的应用函数
if (NULL == T) return OK;
if (ERROR == InorderTraverse(T->lChild, visit))
return ERROR; //递归遍历T的左子树
if (ERROR == visit(T->data))
return ERROR; //访问结点的数据域
return InorderTraverse(T->rChild, visit); //递归遍历T的右子树
}
Status PreOrderTraverse(BiTree T, Status(*visit)(TElemType e)) { //前序遍历二叉树T,visit是对数据元素操作的应用函数
if (NULL == T) return OK;
if (ERROR == visit(T->data))
return ERROR; //访问结点的数据域
if (ERROR == PreOrderTraverse(T->lChild, visit))
return ERROR; //递归遍历T的左子树
return PreOrderTraverse(T->rChild, visit); //递归遍历T的右子树
}
Status PostOrderTraverse(BiTree T, Status(*visit)(TElemType e)) { //后序遍历二叉树T,visit是对数据元素操作的应用函数
if (NULL == T) return OK;
if (ERROR == PostOrderTraverse(T->lChild, visit))
return ERROR; //访问结点的数据域
if (ERROR == PostOrderTraverse(T->rChild, visit))
return ERROR; //递归遍历T的左子树
return visit(T->data); //递归遍历T的右子树
}