树结构
树是一种非线性数据结构,它是由数据元素(结点)按分支关系组织起来的结构。
相关术语
- 每个元素称为结点;
- 有一个特定的结点,称为根结点;
- 其余结点被分成
m(m>=0)
个互不相交的有限集合,而每个子集又都是一棵树,称为子树; - 结点的分支数,以组成该树各结点中最大的度, 称为为该树的度,也叫宽度;
- 组成该树各结点的最大层次,称为树的深度;
- 树的根节点为第1层,其他结点的层次等于它的父结点的层次数加1;
- 树中度为零的结点,称为叶结点或终端结点;
- 树中度不为零的结点,称为分枝结点或非终端结点;
- 除根结点外的分枝结点统,称为内部结点;
- 结点的上一级,称为父结点;
- 同一双亲结点的子结点之间互为兄弟结点;
- 树中任意节点的子结点之间有顺序关系,这种树称为有序树;
- 树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树,
二叉树
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”。
相关术语
- 一棵深度为 k,且有 个结点的二叉树,称为满二叉树;
- 在一棵二叉树中,除最后一层外,若其余层都是满的,并且或者最后一层是满的,或者是在右边缺少连续若干结点,则此二叉树为完全二叉树;
- 所有节点都只有左子树,称为左斜树;
- 所有节点都只有右子树,称为右斜树;
性质
- 在二叉树的第 i 层上最多有 个结点
- 深度为 K 的二叉树最多有 个结点
- 对于任何一颗二叉树 T,如果其终端结点数为 ,度为 2 的结点数为,则 = + 1;
- 具有 n 个结点的完全二叉树的深度为
顺序结构
初始化
BOOL InitBiTree(SqBiTree T){
for (int i = 0; i < MAXSIZE;i++)
{
T[i] = Nil;
}
return true;
}
创建二叉树
BOOL createBiTree(SqBiTree T) {
int i = 0;
while (i < 10) {
T[i] = i+1;
printf("%d ",T[i]);
//结点不为空,且无双亲结点
if (i != 0 && T[(i+1)/2-1] == Nil && T[i] != Nil) {
printf("出现无双亲的非根结点%d\n",T[i]);
exit(0);
}
i++;
}
//将空赋值给T的后面的结点
while (i < MAXSIZE) {
T[i] = Nil;
i++;
}
return true;
}
是否空树
//是否空树
BOOL isEmpty(SqBiTree T){
return T[0] == Nil;
}
获取深度
int BiTreeDepth(SqBiTree T) {
int j = -1;
int i;
for (i = MAXSIZE - 1; i >= 0; i--) {
if (T[i] != Nil) {
break;
}
}
do {
j++;
} while (pow(2, j) <= i);
return j;
}
获取E点的值
//获取E点的结点值
CElemType getValue(SqBiTree T,Position e){
return T[pow(2,e.level - 1) + e.order - 2];
}
//插入值至位置e
BOOL Assign(SqBiTree T,Position e ,CElemType value){
int i = pow(2,e.level - 1) + e.order - 2;
if (T[(i + 1) / 2 - 1] == Nil ){
return false;
}
T[i] = value;
return true;
}
插入结点
//插入值至位置e
BOOL Assign(SqBiTree T,Position e ,CElemType value){
int i = pow(2,e.level - 1) + e.order - 2;
if (T[(i + 1) / 2 - 1] == Nil ){
return false;
}
T[i] = value;
return true;
}
左子结点
int leftChild(SqBiTree T,Position e){
return T[(int)(pow(2, e.level-1)+e.order-2) * 2 + 1 ];
}
右子结点
int rightChild(SqBiTree T,Position e){
return T[(int)(pow(2, e.level-1)+e.order-2) * 2 + 2 ];
}
双亲结点
int fatherNode(SqBiTree T, Position e) {
if (e.level != 1) {
return T[(int)(pow(2, e.level - 1) + e.order - 2) / 2 - 1];
}
return -1;
}
前序遍历(中左右)
/*
前序遍历二叉树 中左右
*/
void PreTraverse(SqBiTree T, int e) {
//打印结点数据
printf("%d ", T[e]);
//先序遍历左子树
if (T[2 * e + 1] != Nil) {
PreTraverse(T, 2 * e + 1);
}
//最后先序遍历右子树
if (T[2 * e + 2] != Nil) {
PreTraverse(T, 2 * e + 2);
}
}
BOOL PreOrderTraverse(SqBiTree T) {
//树不为空
if (!isEmpty(T)) {
PreTraverse(T, 0);
}
printf("\n");
return true;
}
中序遍历(左中右)
void InTraverse(SqBiTree T, int e){
/* 左子树不空 */
if (T[2*e+1] != Nil)
InTraverse(T, 2*e+1);
printf("%d ",T[e]);
/* 右子树不空 */
if (T[2*e+2] != Nil)
InTraverse(T, 2*e+2);
}
BOOL InOrderTraverse(SqBiTree T){
/* 树不空 */
if (!isEmpty(T)) {
InTraverse(T, 0);
}
printf("\n");
return true;
}
后序遍历
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);
printf("%d ",T[e]);
}
BOOL PostOrderTraverse(SqBiTree T){
if(!isEmpty(T)) /* 树不空 */
PostTraverse(T,0);
printf("\n");
return true;
}
链式存储
结构
typedef char CElemType;
CElemType Nil=' '; /* 字符型以空格符为空 */
typedef struct BiTNode /* 结点结构 */
{
CElemType data; /* 结点数据 */
struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode,*BiTree;
初始化
BOOL InitBiTree(BiTree *T)
{
*T=NULL;
return true;
}
销毁二叉树
void DestroyBiTree(BiTree *T)
{
if(*T)
{
/* 有左孩子 */
if((*T)->lchild)
DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
/* 有右孩子 */
if((*T)->rchild)
DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
free(*T); /* 释放根结点 */
*T=NULL; /* 空指针赋0 */
}
}
创建二叉树
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);
}
}
判断二叉树是否为空
BOOL BiTreeEmpty(BiTree T)
{
if(T)
return false;
else
return true;
}
二叉树的深度
int BiTreeDepth(BiTree T){
int i,j;
if(!T)
return 0;
//计算左孩子的深度
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;
}
根结点
CElemType getRoot(BiTree T){
if (BiTreeEmpty(T))
return Nil;
return T->data;
}
获取结点的值
CElemType getValue(BiTree p){
return p->data;
}
给结点赋值
void Assign(BiTree p,CElemType value)
{
p->data=value;
}
前序遍历
void PreOrderTraverse(BiTree T)
{
if(T==NULL)
return;
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
}
中序遍历
void InOrderTraverse(BiTree T)
{
if(T==NULL)
return ;
InOrderTraverse(T->lchild); /* 中序遍历左子树 */
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
}
后序遍历
void PostOrderTraverse(BiTree T)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild); /* 先后序遍历左子树 */
PostOrderTraverse(T->rchild); /* 再后序遍历右子树 */
printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
}