程序报错:二叉树的创建和输出递归先序建
(1)createBiTree建树的过程,你采用的是递归,那么你怎么确定,输入的下一个数据应该是建立在左子树中还是右子树?
分析你的过程,如果输入数据不是-1,那么就会建立一个树节点,并将输入赋给节点的数据,然后递归建立左子树,可以推断,你的树最终肯定只有左子树,而右子树成为未知,访问右子树时肯定要出问题,这就是程序出现异常的原因之一。
(2)creatBiTree函数你设想是自己建立节点,然后将节点返回,因此你会发现,creatBiTree(T->lchild); 并没有将左子树赋值,这说明你没有理解函数参数的意义。你认为creatBiTree(T->lchild)会赋值T->lch...全部
(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;
}。
收起