递归创建二叉树程序步骤详解

首先上代码后面对代码经行分析。

代码

#include <stdio.h>
#include <stdlib.h>
typedef struct tree
{
    char date;
    struct tree *left_leaf;
    struct tree *right_leaf;
}tree,*BiTree;

void creat_tree(BiTree *T)//创建树
{
    char val;
    scanf("%c",&val);
    //getchar();
    if(val=='#')
    {
        *T=NULL;
    }
    else
    {
        *T=(BiTree)malloc(sizeof(tree));
        (*T)->date=val;
        creat_tree(&(*T)->left_leaf);
        creat_tree(&(*T)->right_leaf);
    }
}
void preorder_traversal(BiTree T)//先序遍历
{
    if(T==NULL)
    {
        return;
    }
    printf("%c ",T->date);
    preorder_traversal(T->left_leaf);
    preorder_traversal(T->right_leaf);

}

void inorder_traversal(BiTree T)//中序遍历
{
    if(T==NULL)
    {
        return;
    }
    inorder_traversal(T->left_leaf);
    printf("%c ",T->date);
    inorder_traversal(T->right_leaf);
}
void epilogue_traversal(BiTree T)
{
    if(T==NULL)
    {
        return;
    }
    epilogue_traversal(T->left_leaf);
    epilogue_traversal(T->right_leaf);
    printf("%c ",T->date);
}
int main(void)
{
  BiTree T;
  T=(BiTree)malloc(sizeof(tree));
  printf("请输入先序排列的二叉树,空节点为#\n");
  creat_tree(&T);
  printf("先序输出\n");
  preorder_traversal(T);
  printf("\n");
  printf("中序输出\n");
  inorder_traversal(T);
  printf("\n");
  printf("后序输出\n");
  epilogue_traversal(T);
  printf("\n");
}

运行结果:
在这里插入图片描述
在这里插入图片描述
可以看到程序运行没有问题的。下面我们经行代码刨析!

代码解析

先简单说一下递归思想
比如有这样一个函数。

void fun(int x)
{
    x++;--------------s
    printf("%d \n",x);
    if(x==10)
    {
        return;
    }
    fun(x);-----------p
    printf("i= %d\n",i++);
}

假设x初始值为0,当程序第一次运行到p的时候,此时x=1,然后递归再从s处运行,跑到p处后再次递归,又从s处接着运行。一直到x等于10时候遇到return停止递归。虽然遇到return但是这时候程序并没有停止,因为最后一次fun函数运行,上一次的fun函数还没有运行结束,因为printf还没有运行过。一个函数没有结束是不可以被调用的。上一次函数运行还需要上上次函数运行结束。说起来可能有点抽象画个图来说明吧!
在这里插入图片描述

1函数函数体:

void 1 (void)
{
 2();
 printf("1\n");
}

2函数函数体:

void 2 (void)
{
 3();
 printf("2\n");
}

3函数函数体:

void 3 (void)
{
 4();
 printf("3\n");
}

4函数函数体:

void 4 (void)
{
 return;
}

如果我调用1函数,输出为:3-2-1。
1函数执行需要依赖2函数运行完,2函数运行完需要3函数,3函数运行完需要4函数。只有4函数执行完成3函数才能执行完,3函数执行完2函数才能执行完,2函数执行完1函数才能结束。所以输出为3-2-1.
这就是递归。下面我们会接着分析二叉树。
先序遍历
二叉树图如图。
在这里插入图片描述

先序遍历顺序为,根左右。我们看一下先序遍历的代码。

void preorder_traversal(BiTree T)//先序遍历
{
    if(T==NULL)
    {
        return;
    }
    printf("%c ",T->date);
    preorder_traversal(T->left_leaf);----------1
    preorder_traversal(T->right_leaf);---------2

}

先序遍历结果是

A B D G # # H # # # C E # I # # F # #
首先程序运行到1位置时候,开始递归。
在这里插入图片描述
一直遍历左子树到G,然后再左为空进入return,此时1函数最内层的递归已近结束了。然后开始回溯执行D节点的未执行的2函数,D节点的右子树为H不为空,运行完printf又遇到1函数,然后H节点左右子树都是空,H节点处于的函数执行完成然后D节点处于的函数才能执行完成,接着回溯到B节点的2函数,B节点右子树为空,B节点处于的函数运行结束,到A函数,然后A函数执行2函数,到C函数。到现在A节点的左子树遍历完成。开始右边遍历。到C节点后,C节点运行到1函数时候,有子节点E,节点E左子树为空右子树为I然后I左右子树为空.这里可能有点绕了,我们给E节点单独拿出来。
在这里插入图片描述

    if(T==NULL)
        return;
    printf("1%c ",T->data);---------------a
    PreOrderTravel(T->left);-------------1
    printf("\n");
    printf("2%c ",T->data);--------------b
    PreOrderTravel(T->right);--------------2

在这里插入图片描述
当遍历到E节点时候,运行到a函数,打出E节点的数值1E,然后再执行1函数,E左子树为空,再次执行的1函数运行结束,但是E节点在再次执行1函数时候下面函数没有运行,在1函数截止后,E节点1函数下面开始运行,所以打出了2E,然后开始2函数,遍历到I节点,再printf打印出I节点数值后,再次遇到1函数,调用后左子树为空。结束,此时1函数运行结束,接着下面运行b函数打印出2I。然后在调用2函数,右子树为空函数结束。这时候刚遍历到E节点才完全执行完成,C节点的整个左子树遍历完成,然后C节点那个阶段的函数执行到b函数,打印出2C,接着执行2函数,C的右子树为F不为空,打印出1F,执行的2函数执行到1函数时候,左子树为空。调用的1函数执行完成。然后接着运行到b函数,打印出2F,然后运行2函数。F右子树为空。整个遍历结束。

在这里插入图片描述
递归确实很难,但是真的很迷人。
上面将先序遍历将完了,然后创建二叉树的过程分析不就简单了嘛!虽然确实很难理解比较抽象,但是抽丝剥茧慢慢来还是可以理解的。
老脸一红(我也是看了一天才整明白的)。
总结一下递归的注意事项:

A函数调用B函数,B函数调用C函数,A函数要想调用B函数,B函数必须运行完成,B函数运行完成需要C函数运行完成。也就是说要想A函数运行完成,必须C函数执行完成,然后让 B函数执行完成,最后A函数才能执行完成。

粗言寡语,表达有限。见谅。
如有错误欢迎指正。thanks^ _ ^

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值