#include <stdio.h>
#include <stdlib.h>
typedef int ElemType; //这里用int 作为树结点的数据
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode, *BiTree;
//这里的 *BiTree和BiTNode是一种东西,也就是代表着结构体中的一个结点,所以BiTree是地址
void createBiTree(BiTree *T); //创建树
int main()
{
BiTree T = NULL;
createBiTree(&T);
preOrderTraverse(T);//先序遍历
printf("\n");
inOrderTraverse(T);//中序遍历
printf("\n");
postOrderTraverse(T);//后序遍历
return 0;
}
void createBiTree(BiTree *T) //这里的BiTree又定义了一个*T,也就是说*T指向的是上面说的那个地址,T是存储地址的地址 ,嘿嘿,明白了吧,双重地址
{
ElemType ch;
scanf ("%d", &ch); //如果是字符型 %c 回车输入 算一个字符,ubutun会一直递归
if (0 == ch)//扩展二叉树,虚结点 == 0
{
*T = NULL;
}
else //这里我要特别强调一下,只有连续输入两个0,才能说明上面的那个结点是叶节点,才能跳转到右子树上去
{
*T = (BiTree)malloc(sizeof(BiTNode)); //!!! stdlib.h 头文件一定要加!!!
if (!*T)
{
exit(1); //错误退出
}
(*T)->data = ch; //生成根结点
createBiTree(&((*T)->lchild)); //构造左子树
createBiTree(&((*T)->rchild)); //构造右子树
}
}
下面我们来说一下这个递归的调用了,网上很多给出人给出了二叉树的创建代码,大同小异,但是没有人愿意认真的说一下二叉树的递归到底是怎么回事。
我们来看一下代码,所有人懵圈的地方都是这里
(*T)->data = ch; //生成根结点
createBiTree(&((*T)->lchild)); //构造左子树
createBiTree(&((*T)->rchild)); //构造右子树
之前学弟问过我这个问题,当时都把我带偏了,如果我们这里一直调用创建左子树,那么不是会一直向左边创建永远没有尽头么?
其实这种情况是因为写代码的人没告诉你怎么样输入才能正确的创建二叉树,比如你想得到一个根结点是1,左孩子是2,右孩子是3的二叉树,你该怎么做呢?
正确方法是输入1 2 0 0 3 0 0.
知道为什么么?
你刚开始输入1 2,
那么你现在会进入2这个左孩子的左子树,这里你会注意到,当你输入0的时候,就会创建一个空树所以当你输入0,2的左子树就是空的,你会进入2这个左孩子的右子树,
你再输入一个0,就会跳转到右孩子,也就是3的位置,
在这里你输入3,然后进入3的左子树,再输入两个0,建立空的左右子树,那么你就成功的建立了这个二叉树了。
是不是这么一分析你就发现清晰多了?