搜索
首页 电脑/网络 程序设计 C/C++

程序报错:二叉树的创建和输出

  递归先序建立二叉树,然后非递归中序遍历输出。
  在完成creatBiTree的输入后程序报错自动关闭,麻烦各位帮找下原因? #include #include #define NULL 0 #define OK 1 #define MAXSIZE 20 typedef struct BiNode { int data; struct BiNode *lchild,*rchild; }BiNode,*BiTree; BiTree creatBiTree(BiTree T) { int elem; printf("Input the elem of Tree:"); scanf("%d",&elem); if(elem==-1) { T=NULL; return(T); } else { T=(BiTree)malloc(sizeof(BiNode)); T->data=elem; creatBiTree(T->lchild); creatBiTree(T->rchild); return(T); } } void printBiTree(BiTree T) { BiTree stack[MAXSIZE],p; int top=0; p=T; while(p!=NULL||top>0) { if(p!=NULL) { stack[++top]=p; p=p->lchild; } else { p=stack[top--]; printf(" %d",p->data); p=p->rchild; } } } void main() { BiTree T=NULL; T=creatBiTree(T); printf("The struct of BiTree:"); printBiTree(T); } 。

全部回答

2012-05-14

0 0
    (1)createBiTree建树的过程,你采用的是递归,那么你怎么确定,输入的下一个数据应该是建立在左子树中还是右子树? 分析你的过程,如果输入数据不是-1,那么就会建立一个树节点,并将输入赋给节点的数据,然后递归建立左子树,可以推断,你的树最终肯定只有左子树,而右子树成为未知,访问右子树时肯定要出问题,这就是程序出现异常的原因之一。
     (2)creatBiTree函数你设想是自己建立节点,然后将节点返回,因此你会发现,creatBiTree(T->lchild); 并没有将左子树赋值,这说明你没有理解函数参数的意义。
  你认为creatBiTree(T->lchild)会赋值T->lchild,实际上是不会的。  因为T的值是个指针,但是编译器在处理时,建立一个临时变量,将T->lchild的值传递给了该变量,作为creatBiTree的参数传入,因此你如果使用*T,那么编译器将数据保存给T的值作为地址的存储区,但是如果你使用T,那么编译器就将指针保存给了T,而不是保存到了T->lchild之中,因此函数返回后,T->lchild保持着原来的值;因为你没有给T->lchild赋值,因此函数结束后T->lchild是不确定的,很有可能是空指针,这也是程序异常的原因之一。
     (3)由于二叉树建立时需要判断建立左子树还是右子树,你必须根除明确的方案,因此建立树时一般不使用你使用的递归方法,而是首先获取数据,然后分析数据,根据当前数据,将数据递归插入左子树或者是右子树(后面给你实例)。
   (4)你的非递归中根遍历二叉树的算法不正确,没有实现你的要求,建议你好好看看树(后面给你有例子你可以看看)。   (5)看出你是初学者,对c语言的基本语法和概念理解并不深刻,建议你首先认真理解一下指针和数据的区别,栈和队列的使用等等基本算法。
     下面给你实例: #include #include #define OK 1 #define MAXSIZE 20 typedef struct BiNode { int data; struct BiNode *lchild, *rchild; } BiNode, *BiTree; /** * 将节点node插入到以root为根的子树中, * 如果node 的数据大于root的数据,插入右子树,否则插入左子树 * @param root 子树的根 * @param data 数据 */ void addNode(BiTree root, BiTree node) { if (root == NULL) { //如果子树根为空,空子树不能进行插入,直接返回 return; } //判断插入位置 if (root->data >= node->data) { //需要插入左子树 if (root->lchild == NULL) { //目前左子树为空,直接赋值就行了 root->lchild = node; } else { //不为空,递归插入左子树 addNode(root->lchild, node); } } else { //需要插入右子树 if (root->rchild == NULL) { //目前右子树为空,直接赋值就行了 root->rchild = node; } else { //不为空,递归插入右子树 addNode(root->rchild, node); } } //插入完成,返回 return; } /** * 建立二叉树,返回二叉树的根 * @return 建立的二叉树的根 */ BiTree buildTree() { int elem; BiTree root = NULL; BiTree node = NULL; //根节点 while (1) { //循环建立二叉树 printf("Input the elem of Tree:"); scanf("%d", &elem); if (elem == -1) { //树建立结束 break; } //生成节点 node = (BiTree) malloc(sizeof (BiNode)); node ->data = elem; //判断是不是第一个节点,如果是,直接赋给根 if (root == NULL) { root = node; } else { //不是,插入根的子树 addNode(root, node); } } return root; //返回树根 } /** * 递归释放以root为根树所有子树占有的空间 * 记住,通过malloc申请的内存一定要释放,否则会出现内存泄漏 */ void freeTree(BiTree root) { if (root == NULL) { //空树,直接返回 return; } //递归释放左右子树 if (root->lchild != NULL) { freeTree(root->lchild); root->lchild = NULL; //由于指针的特殊性,释放后一定要赋空值,以便编译器检查异常,否则编译不会出现问题, //但是会带来运行的隐患 } if (root->rchild != NULL) { freeTree(root->rchild); root->rchild = NULL; } //释放根占用的空间 free(root); root = NULL; } /** * 非递归中根遍历二叉树 * 由于是中根遍历二叉树,首先是应该中根遍历左子树,然后打印根,然后中根遍历右子树 * 本质上,非递归遍历就是模拟栈的操作来进行处理 * @param T */ void printBiTree(BiTree T) { BiTree stack[MAXSIZE], p, ps; //为了处理方便,将有左子树的根的数据保存在这个栈中 int top; top = 0; ps = NULL; p = T; while ((p != NULL) || (top > 0)) { while (p != NULL) { //首先遍历左子树,压栈 stack[top++] = p; p = p->lchild; } //获取栈顶元素 ps = stack[--top]; if (ps != NULL) { //打印根数据 printf("%d\t", ps->data); //处理右子树 p = ps->rchild; } } } /* * */ int main(int argc, char**argv) { BiTree T = NULL; //建树 T = buildTree(); printf("The struct of BiTree:\n"); //打印树 printBiTree(T); //释放空间 freeTree(T); return 0; }。
  

2012-05-14

63 0
两个问题: 1) BiNode 加一构造函数以初始化 *lchild,*rchild 指针 BiNode() : data(0), lchild(NULL), rchild(NULL) {} 2)creatBiTree 函数声明改为:(注意: 加了一个 &) BiTree creatBiTree(BiTree & T)

类似问题换一批

热点推荐

热度TOP

相关推荐
加载中...

热点搜索 换一换

电脑/网络
C/C++
程序设计
电脑装机
操作系统/系统故障
硬件
笔记本电脑
百度
互联网
反病毒
软件
程序设计
C/C++
数据库
VB
JAVA相关
C#/.NET
VC++
汇编语言
其他编程语言
C/C++
C/C++
举报
举报原因(必选):
取消确定举报