#include<stdio.h>
#include<stdlib.h>
typedef struct BiNode
{
char data;
struct BiNode *lchild;
struct BiNode *rchild;
}BiNode, *BiTree;
int CreatBiTree(BiTree &T)
{
int m;
scanf("%d", &m);
if (m == -1)
T=NULL;
else
{
T = (BiTree)malloc(sizeof(BiNode));
T->data = m;
printf("请输入%d的左孩子", m);
CreatBiTree(T->lchild);
printf("请输入%d的右孩子", m);
CreatBiTree(T->rchild);
}
return 0;
}
void PrintfBiTree(BiTree T)
{
if (T == NULL)
return;
printf("%d", T->data);
PrintfBiTree(T->lchild);
PrintfBiTree(T->rchild);
}
int main()
{
BiTree T;
BiTree *p = (BiTree*)malloc(sizeof(BiNode));
printf("请输入根节点的值,当任何节点为-1时代表为空节点\n");
CreatBiTree(T);
PrintfBiTree(T);
system("pause");
}
昨天发了博客说最近会写二叉树的创建和遍历,今天正好下雨外边很冷,在宿舍看了学长的视频,从网上查资料。三个半小时,终于是写出来了一个二叉树的递归创建和递归先序遍历。现在迫不及待的写一篇博客来展示一下自己一晚上的成果。
我来以一个小白的角度一点一点给大家说一下如果用递归算法创建和遍历一个二叉树。
typedef struct BiNode
{
char data;
struct BiNode *lchild;
struct BiNode *rchild;
}BiNode, *BiTree;
这个结构大家学了数据结构之后肯定都不会很陌生,这里需要注意的就是在定义指针的时候前边用的是自己所定义的结构体类型,指针定义的时候前边并不是咱们常见的int型,char型等等 应该是 struct +你的结构体类型。另一个问题就是我刚开始的时候困惑了很久的,为什么要在花括号后边加上两个BiNode, *BiTree;这里可能我说的不对,我现在所理解的就是,你前边这个就是你的结构体类型所以你写的和你上边typedef后边写的一样就行,甚至可以你上边不写只在花括号后边来写上,之后带星号的那个就是你的结构体指针类型。目前对这个的作用我还不是很清楚,但是不影响写程序,记住那个固定的写程序模式就没有问题,在之后我一定会对这两个东西做更加详细的解释和探讨。下边先说今天的成果二叉树的建立和遍历。
首先说二叉树的创建。
int CreatBiTree(BiTree &T)
{
int m;
scanf("%d", &m);
if (m == -1)
T=NULL;
else
{
T = (BiTree)malloc(sizeof(BiNode));
T->data = m;
printf("请输入%d的左孩子", m);
CreatBiTree(T->lchild);
printf("请输入%d的右孩子", m);
CreatBiTree(T->rchild);
}
return 0;
}
二叉树的创建有很多种,因为我在写这个程序的时候在网上百度了许多的格式,许多的程序,各自有各自的写法,对于我这个小白来说我认为这种写法最简单,最容易理解所以我模仿了网上的这种写法。
int CreatBiTree(BiTree &T)
先看这句话,这个函数开始既可以是int也可以是其他的,后边括号的是你需要对这个函数引入一个参数,这个参数的类型要是你的结构体指针类型,T前边的取地址符可以要可以不要,对程序并不影响。
int m;
scanf("%d", &m);
这句话是你创建一个int类型的数字,然后从键盘中获得。
if (m == -1)
然后你需要写一个判断的调节,这个是递归终结的判断条件,昨天在上一篇博客也说了,如果你是递归算法你的程序中对于递归算法, 就必须要有一个递归的终结边界值,在这里这个-1就是递归的终结值。
if (m == -1)
T=NULL;
也就是说如果你的二叉树的结点值是-1的话,那么这个结点就是一个空的结点,就不再会创建这个结点。
else
{
T = (BiTree)malloc(sizeof(BiNode));
T->data = m;
printf("请输入%d的左孩子", m);
CreatBiTree(T->lchild);
printf("请输入%d的右孩子", m);
CreatBiTree(T->rchild);
}
如果输入的值不是-1的话,那么就会进行else中的步骤。
T = (BiTree)malloc(sizeof(BiNode));
先给这个T开辟一个内存空间用来存储它。这个malloc函数前边后边的两个东西也是有区别的,前边就是这个结构体的指针类型,后边sizeof就是这个结构体的类型,应该不难理解,sizeof肯定是分配类型的大小,不同类型分配的大小肯定是不一样的,所以结构体类型是在sizeof后边然后指针类型相应的就在前边了。
T->data = m;
printf("请输入%d的左孩子", m);
CreatBiTree(T->lchild);
printf("请输入%d的右孩子", m);
CreatBiTree(T->rchild);
后边的就相对来说比较好理解了,将m的值给了T中的data域,之后再不断的调用这个函数来给他的左右孩子往下赋值,一直到结点的值是-1的时候就不再给这个结点开辟空间了,也就没有之后的操作,程序也就终止了。
void PrintfBiTree(BiTree T)
{
if (T == NULL)
return;
printf("%d", T->data);
PrintfBiTree(T->lchild);
PrintfBiTree(T->rchild);
}
对于输出的函数也是运用递归的算法,如果能够理解创建的时候的递归算法的话,输出的就很简单的理解了。
int main()
{
BiTree T;
BiTree *p = (BiTree*)malloc(sizeof(BiNode));
printf("请输入根节点的值,当任何节点为-1时代表为空节点\n");
CreatBiTree(T);
PrintfBiTree(T);
system("pause");
}
主函数中需要先创建这个T之后,先开辟第一个根节点,因为在创建函数中上来是要对结点的data域进行判断的。之后直接调用两个函数就可以了。
这是我对二叉树的创建和遍历自己的理解,可能有些不准确或者是错误的,希望读者看到之后能给我纠正,给我一些建议。
虽然程序十分的简单但是对于我一个新手来说我写了三个半小时,对于二叉树的其他遍历方法我会之后更新。