#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. Killer Problem(暴力)

    题意: 给定一个序列,每次询问l到r之间两个数差的绝对值的最小值. 分析: 开始以为是线段树离线处理,实际暴力就好! #include <map> #include <set> ...

  2. 如何装载Storyboard中的ViewController?

      如上图所示,如何装载Storyboard中指定的ViewController? 首先,需要指定ViewController的ID,如上图右上方红色方框内的Storyboard ID.然后使用下面的 ...

  3. HTML5牛刀小试

    第一周的HTML5苦逼之路,就这么简单,充实,忙碌的开始了,丝毫不敢有一丢丢懈怠,压力是有的,但更多的是对自己的信心,更是对自己的踏上苦逼之路的意志的肯定. 简单回顾了下这周所学内容.从认识HTML基 ...

  4. git 详细部署及其应用

    第1章 版本控制系统 自动生成备份.随时回滚.知道改动的地方. 1.1 svn和git的区别 1.1.1 svn 集中式的版本控制系统,只有一个中央数据仓库,如果中央数据库仓库挂了或者不可访问,所有的 ...

  5. [SQL必知必会] 读书笔记

    第1课 数据库 这一课介绍SQL究竟是什么,它能做什么事情.   1.1 数据库基础 下面是一些数据库概念的简要介绍,如果你刚开始接触数据库,可以由此了解必需的基本知识.   1.1.1 数据库 数据 ...

  6. 最大流增广路(KM算法) HDOJ 1853 Cyclic Tour

    题目传送门 /* KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 */ #include <cstdio> #include <cmath> #incl ...

  7. ACM_求f(n)

    求f(n) Time Limit: 2000/1000ms (Java/Others) Problem Description: 设函数f(n)=1*1*1+2*2*2+3*3*3+...+n*n*n ...

  8. JavaScript 把函数作为参数进行传值

    JavaScript 响应式编程模式有点类似 WebForm 中的事件驱动模式(传相应的处理函数给委托,通过事件来触发来进行相关的处理),在 AngularJs 2.x 框架中,应用了 RxJS AP ...

  9. [译]libcurl错误码

    CURLcode Almost all "easy" interface functions return a CURLcode error code. No matter wha ...

  10. lua_protobuf

    http://www.cocoachina.com/bbs/read.php?tid-227404.html