#include <stdio.h>
typedef struct tree {
int val;
struct tree* left, *right;
}Btree,*BT_point;
//int creat_tree(BT_point* L)
//{
// char ch;
// scanf("%c", &ch);
// if (ch == '#')
// (*L) = NULL;
// else
// {
// (*L) = (BT_point)malloc(sizeof(Btree));
// if (!(*L))
// return - 1;
// (*L)->val = ch;
// creat_tree(&((*L)->left));
// creat_tree(&((*L)->right));
// }
// return 1;
//}
int insert_tree(BT_point* L,int elem)
{
if (!(*L))//如果到达根节点,就需要新建立一个结点,之后再将结点创立的指针与树的末尾指针相连
{
BT_point s= (BT_point) malloc(sizeof(Btree));
s->val = elem;
s->right = s->left = NULL;
(*L) = s;
}
else if (elem < (*L)->val)
{
insert_tree(&((*L)->left),elem);
}
else if (elem > (*L)->val)
{
insert_tree(&((*L)->right),elem);
}
}
int create_tree(BT_point* L)
{
(*L) = NULL;
int elem = 0;
scanf("%d", &elem);
while (elem != -1) {
insert_tree(&(*L), elem);
scanf("%d", &elem);
}
}
int delete_tree(BT_point* L, int num)
{
BT_point p = (*L), f = NULL;//从根节点开始遍历
BT_point q = NULL;
while (p)
{
if (p->val == num) break;//找到这个数,立刻退出
f = p;//待删结点的双亲结点
if (p->val >num)
{
p = p->left;
}
else
{
p = p->right;
}
}
if (!p) return -1;//遍历结束,任然没有找到,就返回-1
if ((p->left) && (p->right))
{
BT_point q = p, s = p->left;//s进入待删除结点的左子树中查找最大值,q:从待删除结点开始记录
while (s)
{
q=s;
s = s->right;
}
p->val = s->val;//替换删除结点的值,之后删除子树的右边结点
if (q != p)
q->right = s->left;
else
q->left = s->left;//在删除结点的左子树中,所有的结点均只含左子树
free(s);
return 1;
}
//上面的两种只有左子树 / 右子树,(还包括叶子结点,即左右孩子指针为NULL,这样他就会进入第一个条件判断,之后就会将右孩子(NULL)赋值给待删除结点)
else if (!(p->left))
{
q = p;
p=p->right;
}
else if (!(p->right))
{
q = p;
p = p->left;
}
if (!f) (*L) = p;//此处针对的是删除的根节点(只有左子树或者自由右子树,单边的那种)
else if (f->left == q)//此处针对的是删除的根节点(只有左子树或者自由右子树)的左孩子下面的两种情况就是针对的是上面的两种只有左子树/右子树,\
还包括叶子结点(,即左右孩子指针为NULL,此时由于p==NULL)
{
f->left = p;
}
else
{
f->right = p;
}//此处针对的是删除的根节点(只有左子树或者自由右子树)的右孩子
free(q);
return 1;
}
int traverse(BT_point L)
{
if (!L)
{
return -1;
}
else
{
printf("%5d", L->val);
traverse(L->left);
traverse(L->right);
}
return 1;
}
int main()
{
BT_point L;
create_tree(&L);
delete_tree(&L, 12);
traverse(L);
return 0;
}
双指针思想:在删除的过程中,由于树的实现是采用链表(两个子指针)实现,所以在删除的时候,需要使用一个指针记录待删除结点,还有使用一个指针记录其父节点。