删除二叉树数值为x的节点及其子树
解释都在代码里面,做题时的一点思考
#include<stdlib.h>
typedef int datatype;
typedef struct node
{
datatype data;
struct node *lchild,*rchild;
}bitree;
bitree *creattree()
{
int ch;
bitree *q[maxsize];//使用指针类型数组来构成队列用以存放节点指针
int front,rear;
bitree *root,*s;//定义根节点指针和中间变量指针
root = NULL;
//队列指针初始化
front = 1;
rear = 0;
while((ch = getchar())!='#')
{
s = NULL;
if(ch!='@')//设立新节点
{
s = (bitree*)malloc(sizeof(bitree));
s->data = ch;
s->lchild = NULL;
s->rchild = NULL;
}
rear++; //队尾指针增加,指向新增的节点
q[rear]=s; //将新节点的指针入队或虚节点NULL入队
if(rear==1) //如果是第一个节点,那么作为根节点
{
root = s;
}
else
{
//子节点,若孩子和双亲节点都不是虚节点,
if(s&&q[front])
{
if(rear%2==0) //如果是偶数的话,新节点是左孩子
{
q[front]->lchild = s;
}else //如果是右节点,新节点是右孩子
{
q[front]->rchild = s;
}
}
//处理完了子节点之后出队
if(rear%2==1)
{
front++;
}
}
}
return root;
}
void preorder(bitree *p)//p是二叉树的根节点
{
if(p!=NULL)
{
printf("%d ",p->data-48);//访问根节点的数据域
preorder(p->lchild); //先序遍历左子树
preorder(p->rchild); //先序遍历右子树
}
}
void fre(bitree *&p)//为了直接对原数组进行操作,使用&引用符 (只有这里用了c++的操作)
{
if(p==NULL)
{
return ;
}
//直接将这个节点的左右子树置空,如果不用&的话父亲节点的左右子树无法置空
p->lchild = NULL;
p->rchild = NULL;
free(p);
p = NULL;//free表示的是这块空间不可用,指向时会报错,因此需要对其进行手动置空
}
//递归遍历 正常操作了
void deletnumber(bitree *&p,int x)
{
if(p==NULL)
{
return ;
}
if(p->data-48==x)
{
fre(p);
}
//这里的判断条件有待优化
if(p!=NULL)
{
deletnumber(p->lchild,x);
deletnumber(p->rchild,x);
}
}
/*
删除函数的笨办法就是这样,进一步优化是在删除函数中直接对左右节点区分对待进行处理
*/
int main()
{
/*
主函数暂时以int作为测试类型,可以自行更改,要是想要手
动输入要删除的变量的就改一下代码吧
*/
printf("请输入一组数字,以#结尾,空节点为@\n");
bitree *root;
root = creattree();
deletnumber(root,2);
preorder(root);
return 0;
}
`