摘要
一、定义和数据结构
1. 定义
二叉树(Binary Tree)是一种树形结构,它的特点是每个结点至多有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能随意颠倒。
2. 数据结构
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
该结点是二叉树中最基本的元素,包括数据域和指针域。
二、初始化和赋值
1. 初始化
BiTree myBiTree; // 定义一个指向二叉树根结点的指针
InitTree(&myBiTree); // 初始化二叉树
我们使用一个指向二叉树根结点的指针表示一颗二叉树。
需要注意的是,二叉树的初始化InitTree改变的是根结点指针本身的内容,而不是指针指向的内容,所以在传递参数时,使用指针传递,传递根结点指针的指针,即根结点指针的地址。
Status InitTree(BiTree *T)
{
// *T 即为指向二叉树根结点的指针.
if (*T == NULL) // 若已经指向空, 操作失败, 报错.
{
return ERROR;
}
*T = NULL; // 使得指针指向 NULL.
return OK;
} // InitTree
2. 赋值
按照先序次序为二叉树结点赋值。
// ! *T是二叉树指针的指针, **T才是二叉树本体.
void CreateTree(BiTree *T, FILE *fp)
{
char ch = 0;
ch = fgetc(fp); // 从输入文件中读取一个字符.
if (ch == '^') // 使用'^'表示空结点.
{
*T = NULL;
}
else
{
// 为根结点指针分配要指向要内存空间.
*T = (BiTNode *)malloc(sizeof(BiTNode));
if (!*T)
{
exit(OVERFLOW);
}
(*T)->data = ch;
CreateTree(&((*T)->lchild), fp); // 递归创建左右子树.
CreateTree(&((*T)->rchild), fp); // 依旧传递指针的指针.
}
} // CreateTree
在定义CreateTree时也可以不使用两层套娃, 但之所以仍像InitTree一样是因为:
1. 保持一致性,凡是涉及到修改二叉树的操作,都传递指针的指针。
2. 若以后修改二叉树的操作涉及对二叉树指针本身的修改,这么做可以减少麻烦。实际上CreateTree中的*T = NULL
理解起来比&T = NULL
方便.
三、遍历方式
遍历不修改二叉树,直接传递指针。
1. 前序
Status PreOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
{
if (T)
{
if (Visit(T->data))
{
if (PreOrderTraverse(T->lchild, Visit))
{
if (PreOrderTraverse(T->rchild, Visit))
{
return OK;
}
}
}
return ERROR;
}
else
{
return OK;
}
} // PreOrderTraverse
2. 中序
Status InOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
{
if (T)
{
if (InOrderTraverse(T->lchild, Visit))
{
if (Visit(T->data))
{
if (InOrderTraverse(T->rchild, Visit))
{
return OK;
}
}
}
return ERROR;
}
else
{
return OK;
}
} // InOrderTraverse
3. 后序
Status PostOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
{
if (T)
{
if (PostOrderTraverse(T->lchild, Visit))
{
if (PostOrderTraverse(T->rchild, Visit))
{
if (Visit(T->data))
{
return OK;
}
}
}
return ERROR;
}
else
{
return OK;
}
} // PostOrderTraverse
参考文献
- 数据结构:C语言版/严蔚敏,吴伟民编著. ——北京:清华大学出版社,2007
代码仓库