#include<stdlib.h>
#include<stdio.h> #define True 1
#define False 0 typedef char TElemType;
typedef struct TNode {
TElemType data;
struct TNode *lchild, *rchild;
}TNode,*BinTree; int CreateBinTree(BinTree T)
{
TElemType ch;
scanf("%c",&ch);
if (ch == '#')
T = NULL;
else
{
T = (TNode *)malloc(sizeof(TNode));
T->data = ch;
CreateBinTree(T->lchild);//创建左子树
CreateBinTree(T->rchild);//创建右子树
}
return ;
} void PreOrderTraverse(BinTree T) //先序遍历
{
if (T!=NULL)
{
// Visit(T->data);
printf("%c", T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
} void InOrderTraverse(BinTree T) //中序遍历
{
if (T != NULL)
{
InOrderTraverse(T->lchild);
// Visit(T->data);
printf("%c", T->data);
InOrderTraverse(T->rchild);
}
} void PostOrderTraverse(BinTree T) //后序遍历
{
if (T != NULL)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%c", T->data);
}
} int main()
{
BinTree a;
CreateBinTree(a);
PreOrderTraverse(a);
return ;
}

满怀憧憬写完了代码,让我绝望的是,一运行就出现了问题:能够输入树的信息,但是无法输出,因此,我认为是二叉树的遍历函数出了问题,但是又无法单单从代码看出

于是,我就写了如下代码,自行构建了一个二叉树:

         BinTree a=NULL;
BinTree b = NULL;
BinTree c = NULL;
a = (BinTree)malloc(sizeof(TNode));
b = (BinTree)malloc(sizeof(TNode));
c = (BinTree)malloc(sizeof(TNode));
a->rchild = b;
b->lchild = c;
a->lchild = NULL;
b->rchild = NULL;
c->lchild = NULL;
c->rchild = NULL;
a->data = 'A';
b->data = 'B';
c->data = 'C'; PreOrderTraverse(a);
printf("\n");
InOrderTraverse(a);
printf("\n");
PostOrderTraverse(a);

结果却成功地输出了自行构造的二叉树。由此可见我的遍历函数并没有问题,因此必定是二叉树的create函数出了问题,但是为何我却能够输入呢?

我在网上查了查相关的代码,发现一个采用引用值传递的算法,将create函数修改如下:

int CreateBinTree(BinTree &T)  //引用值传递
{
TElemType ch;
scanf_s("%c",&ch,sizeof(ch));
if (ch == '#')
T = NULL;
else
{
T = (TNode *)malloc(sizeof(TNode));
T->data = ch;
CreateBinTree(T->lchild);//构造左子树
CreateBinTree(T->rchild);//构造右子树
}
return ;
}

尝试着运行,成功了!

???这时我感到很奇怪。

为啥之前的不行呢?

这时,又看到使用BinTree作返回值的算法,修改后如下:

 BinTree creatBTree()   //以BinTree为返回值
{
TElemType ch;
BinTree T;
scanf_s("%c", &ch, sizeof(ch));
if (ch == '#')
T = NULL;
else
{
T = (TNode *)malloc(sizeof(TNode));
T->data = ch;
T->lchild=creatBTree();//构造左子树
T->rchild=creatBTree();//构造右子树
}
return T;
}

毫无疑问,同样能成功实现需求。

那么问题来了?为什么之前的不行呢?

因为我之前用的int CreateBinTree(BinTree T);是单纯的值传递,就像swap(a,b)无法交换两值那样,虽然的确通过动态内存分配和链表构造了一个二叉树,但是在主函数中定义的a的值并没有任何改变,因此在遍历a时会毫无反应。

而引用作函数参数传递,能够直接对a的值进行改变,以a为根节点构建二叉树。

以BinTree为返回值就更不用说了,直接将新构建的二叉树赋值给a。

为了尝试地址为参数传递是否可行,写了如下函数

int CreateRoot(BinTree *T),细节如下:

 int CreateBinTree(BinTree *T)
{
TElemType ch;
scanf("%c",&ch);
*T=(BinTree)malloc(sizeof(TNode));
(*T)->data=ch;
(*T)->lchild=NULL;
(*T)->rchild=NULL;//设置左右孩子为NULL,以防陷入无限循环
}

能够成功插入根节点!

看到这里,便可以轻松完成递归构造函数:

 int CreateBinTree(BinTree *T)
{
TElemType ch;
scanf("%c",&ch);
if (ch == '#')
*T = NULL; //若写成T=NULL ,可能会陷入无限循环
else
{
*T = (BinTree)malloc(sizeof(TNode));
(*T)->data = ch;
CreateBinTree(&(*T)->lchild);//left child
CreateBinTree(&(*T)->rchild);//right child
}
return ;
}
//在本函数中最需要注意的就是,所有地方都必须以(*T)的形式出现

写完这个随笔,对二叉树的理解增进了不少,今天的学习给我带来了不小的回报,继续努力~

C语言二叉树的创建、(先中后序)遍历以及存在的问题的更多相关文章

  1. [C++] 非递归实现前中后序遍历二叉树

    目录 前置技能 需求描述 binarytree.h 具体实现 binarytree.cpp main.cpp 网上代码一搜一大片,大同小异咯. 书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问 ...

  2. C语言实现链式二叉树静态创建,(先序遍历),(中序遍历),(后续遍历)

    #include <stdio.h>#include <stdlib.h> struct BTNode{ char data ; struct BTNode * pLchild ...

  3. 数据结构-C语言递归实现树的前中后序遍历

    #include <stdio.h> #include <stdlib.h> typedef struct tree { int number ; struct tree *l ...

  4. Binary Tree Traversal 二叉树的前中后序遍历

    [抄题]:二叉树前序遍历 [思维问题]: 不会递归.三要素:下定义.拆分问题(eg root-root.left).终止条件 [一句话思路]: 节点非空时往左移,否则新取一个点 再往右移. [输入量] ...

  5. POJ 2255 Tree Recovery && Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)

    链接:poj.org/problem?id=2255 本文链接:http://www.cnblogs.com/Ash-ly/p/5463375.html 题意: 分别给你一个二叉树的前序遍历序列和中序 ...

  6. C++二叉树前中后序遍历(递归&非递归)统一代码格式

    统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ...

  7. C++实现对树的创建和前中后序遍历

    #include<iostream>#include<stdio.h> using namespace std; class BitNode{ public: char dat ...

  8. 剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历

    二叉树的先序,中序,后序如何遍历,不在此多说了.直接看题目描述吧(题目摘自九度oj剑指offer面试题6): 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结 ...

  9. 【遍历二叉树】03二叉树的后序遍历【Binary Tree Postorder Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的后序遍历的 ...

随机推荐

  1. HDU 1394 线段树or 树状数组~

    Minimum Inversion Number Description The inversion number of a given number sequence a1, a2, ..., an ...

  2. [翻译]NUnit---Exception && Utility Methods (六)

    网址:http://www.cnblogs.com/kim01/archive/2013/04/01/2994378.html Exception Asserts (NUnit 2.5) Assert ...

  3. tyvj 1013 找啊找啊找GF

    题目大意: 有一个背包,里面的东西需要满足两个条件,不只是体积 求最多能装多少东西,这些东西的东西最小价值 思路: 双重背包 开两个数组,记录装的东西数量和价值 #include<iostrea ...

  4. POJ 3294 UVA 11107 Life Forms 后缀数组

    相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...

  5. ZOJ1081 Points Within 点和多边形的位置关系

    ZOJ1081 给一个点和一个多边形 判断点在多边形内(边上)还是在多边形外 在多边形外的点引一条射线必然穿过多边形的两条边 而在多边形内的点则不一定. 当然凹多边形有特殊情况 但是总能找到对应位置关 ...

  6. LA3704

    https://vjudge.net/problem/UVALive-3704 参考:http://www.cnblogs.com/iwtwiioi/p/3946211.html 循环矩阵... 我们 ...

  7. Asp.Net 文件下载1——流下载(适用于大文件且防盗链)(转)

    使用流防盗链下载大文件 直接上 Asp.net 后置代码好了 using System; using System.Data; using System.Configuration; using Sy ...

  8. 【转载】存储的一些基本概念(HBA,LUN)

     1.关于HBA HBA的全称为Host Bus Adapter,即主机总线适配器. a.总线适配器是个什么东西呢? 我们首先要了解一下主机的结构,一台计算机内部多半由两条总线串在起来(当然实际情况会 ...

  9. Ruby实例方法和类方法的简写

    创建: 2017/12/12   类方法 Sample.func 实例方法 Sample#func

  10. hdu4738(边双连通分量,桥)

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...