#include<stdio.h>
#include<stdlib.h>
#define NULL_DATA -1
typedef struct node
{
int data;
struct node*lchild;
struct node*rchild;
}NODE;
//注:平均深度 O(log N)
NODE *create()
{
NODE *t = (NODE*)malloc(sizeof(NODE));
int x;
if (t != NULL)
{
scanf("%d", &x);
if (x == NULL_DATA)
{
t = NULL;
}
else
{
t->data = x;
t->lchild = create();
t->rchild = create();
}
}
return t;
}
NODE* find(int x, NODE *t)
{
if (t == NULL)
return NULL;
if (x<t->data) //如果要查找的值小于根节点,那就递归查找左子树
return(find(x, t->lchild));
if (x>t->data)
return(find(x, t->rchild));
else
return t;
}
NODE * findMin(NODE *t)//递归查找最小的节点
{
if (t == NULL)
return NULL;
else if (t->lchild == NULL)
return t;
else //由于左子树永远小于右子树,所以只需要遍历左边的
return findMin(t->lchild);
}
NODE *insert(int x, NODE *t)
{
if (t == NULL)//如果树本身就不存在,那就建立一颗新树,并把它的左右节点置为空
{
t = (NODE*)malloc(sizeof(NODE));
t->data = x;
t->lchild = t->rchild = NULL;
}
else
{
if (x<t->data)
t->lchild = insert(x, t->lchild);
if (x>t->data)
t->rchild = insert(x, t->rchild);
}
return t;//最后返回的还是根节点
}
NODE* del(int x, NODE *t)
//删除有三种情况:1)没有子节点 2)有一个子节点 3)有两个子节点
{
if (t == NULL)
{
printf("该树不存在!\n");
return NULL;
}
else
{
if (x < t->data)
t->lchild = del(x, t->lchild);
else if (x > t->data)
t->rchild = del(x, t->rchild);
else if (x == t->data)
{
//如果左右节点均不存在,则直接删除
NODE *temp = t;
if (t->lchild == NULL)//若存在一个子节点,则把子节点的地址赋值给删除的那块节点
{
t= t->rchild;
free(temp);
}
else if (t->rchild == NULL)
{
t = t->lchild;
free(temp);
}
else if (t->lchild&&t->rchild)
{//如果左右节点都存在,则找到右子树中最小的节点并代替它
temp = findMin(t->rchild);
t->data = temp->data;
t->rchild = del(t->data, t->rchild);//找到之后再删除那个最小的节点
}
}
}
return t;
}
void print(NODE *t)
{
if (t != NULL)
{
printf("%d ", t->data);
print(t->lchild);
print(t->rchild);
}
}
int main()
{
//建立
NODE *p,*e,*f,*g;
int d;
printf("先序输入ADT(查找二叉树)各节点的值,空值以-1替代。\n");
p = create();
e = f = p;
//输出
printf("二叉树的先序序列为:");
print(p);
//查找
printf("\n输入要查找的值:");
scanf("%d", &d);
p = find(d, p);
if (p != NULL)
printf("存在节点: %d\n", p->data);
else
printf("不存在该节点!\n");
//插入
printf("输入需要插入的值:");
scanf("%d", &d);
f = insert(d, f);
printf("插入后的二叉树为:");
print(f);
//删除
printf("\n输入需要删除的值:");
scanf("%d", &d);
e = del(d, e);//此处传递的指针会变,所以不用p
if (e != NULL)
{
printf("删除后的二叉树为:");
print(f);
}
else
printf("不存在该节点,删除失败!\n");
system("pause");
return 0;
}
二叉查找树(Binary Search Tree, BST),也有称作二叉排序树,二叉检索树,二叉搜索树,检索树 等等。其数据结构表示和二叉树相同,在此基础之上还有其特殊的性质,递归定义为:
一颗非空的二叉查找树(Binary Search Tree, BST),满足如下特性:
- 若根节点的左子树非空,则左子树所有节点数值小于根节点;
- 若根节点的右子树非空,则右子树所有节点数值大于根节点;
- 左右子树分别为一颗二叉查找树.
删除说明:如果没有子节点,那最简单直接删除,如果有一个子节点,就把子节点代替删除的那个节点的位置,如果有两个子节点,就需要遍历右子树,找出最小的,代替它。
由于左边肯定小一些,所以只需要遍历以待删除的节点为根节点的树的左子树。