一 二叉树的定义
树(tree)是包含n(n>0)个结点的有穷集,其中:
(1)每个元素称为结点(node);
(2)有一个特定的结点被称为根结点或树根(root)。
(3)除根结点之外的其余数据元素被分为m(m≥0)个互不相交的集合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树(subtree)。
二叉树是另外一种数据结构,他的贴点是每个结点至多只有两颗字数(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。
a为空二叉树,b为仅有根节点的二叉树,c为右子树为空的二叉树,d为左、右子树均为非空的二叉树,e左子树为空的二叉树。
二 二叉树的递归遍历
在二叉树的一些应用中,常常要求在树中查找具有某种特征的结点,或者对书中全部结点注意惊醒某种处理。这就提出了一个遍历二叉树的问题,即如何按某条搜索路径寻访树中每个结点,使的每个结点均被访问一次,而且仅被访问一次。
二叉树有三种递归遍历方式:
1先序遍历
访问根节点; 先序遍历左子树; 先序遍历右子树
2中序遍历
中序遍历左子树; 访问根节点; 中序遍历右子树
3 后序遍历
后序遍历左子树; 后序遍历右子树; 访问根节点
举个例子:
三种方式遍历上图二叉树:
1先序遍历 ABdAec 2中序遍历 AdBeAc 3后序遍历 AdeBcA
三 代码实现
树节点结构体定义
typedef struct node{
char data; //存放字符
struct node * lchild; //指针指向左孩子
struct node * rchild; //指针指向右孩子
}bitTree,*BitTree;
构造一个二叉树
void init(BitTree & t) {
char ch;
scanf("%c", &ch);
if('#' == ch) { //如果读到#字符,代表此节点为空
t = NULL;
} else
{
t = (BitTree)malloc(sizeof(bitTree));
if(NULL == t)
{
printf("动态分配内存失败");
exit(-1);
}
else
{
t->data = ch;
init(t->lchild);
init(t->rchild);
}
}
}
将每一个结点看作根节点,使用递归构造二叉树。
全部代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct node{
char data;
struct node * lchild;
struct node * rchild;
}bitTree,*BitTree;
void init(BitTree &);
void visit(BitTree);
void preOrderTraverse(BitTree);
void inOrderTraverse(BitTree);
void postOrderTraverse(BitTree);
int main(){
BitTree t = NULL;
init(t);
preOrderTraverse(t);
printf("\n");
inOrderTraverse(t);
printf("\n");
postOrderTraverse(t);
return 0;
}
void init(BitTree & t) {
char ch;
scanf("%c", &ch);
if('#' == ch){
t = NULL;
} else
{
t = (BitTree)malloc(sizeof(bitTree));
if(NULL == t)
{
printf("动态分配内存失败");
exit(-1);
}
else
{
t->data = ch;
init(t->lchild);
init(t->rchild);
}
}
}
void visit(BitTree t) {
printf("%c", t->data);
}
//先序遍历
void preOrderTraverse(BitTree t){
if(NULL != t){
visit(t);
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
}
}
//中序遍历
void inOrderTraverse(BitTree t){
if(NULL != t){
preOrderTraverse(t->lchild);
visit(t);
preOrderTraverse(t->rchild);
}
}
//后序遍历
void postOrderTraverse(BitTree t){
if(NULL != t){
preOrderTraverse(t->lchild);
preOrderTraverse(t->rchild);
visit(t);
}
}