代码中所用到的结构体
typedef struct Node
{
int elem;//存放数据
struct Node *lchild, *rchild;
struct Node *prev;
} TreeNode, *BiTree; //定义树节点的结构体
typedef struct tree
{
BiTree root;
}Tree,*pTree;
构造二叉排序树
- 以第一个输入的数据作为排序二叉树的根。
- 对数数据的输入分为6种情况:
- 1.当树不存在的时候,当前数据作为树的根;
- 2.当树中存在此数据时,打印“此数据已存在”;
- 3.输入数据小于当前结点且当前结点无左儿子,则输入数据作为当前结点的左儿子;
- 4.输入数据小于当前结点且当前结点有左儿子,则将当前结点指针移动到左儿子,继续比较;
- 5.输入数据大于当前结点且当前结点无右儿子,则输入数据作为当前结点的右儿子;
- 6.输入数据大于当前结点且当前结点有右儿子,则将当前结点指针移动到右儿子,继续比较;
- 结束条件为输入 -1
void CreateBST(pTree T)//构造二叉排序树
{
int e=0;//初始化
while(1)//while循环建立二叉排序树
{
printf("Please input the child of BST:");
printf("(input will over when you input -1.)\n");
scanf("%d",&e);//插入的数据
getchar();
if(e==-1)//非法判断
{
break;
}
BiTree n1=(BiTree)malloc(sizeof(TreeNode));//申请空间
BiTree n2=T->root;//初始化
n1->elem=e;
n1->lchild=NULL;
n1->rchild=NULL;
n1->prev=NULL;
if(T->root==NULL)//当树不存在时
{
T->root=n1;
}
else//当树存在时
{
while(1)//实现二叉树插入
{
if(e==n2->elem)//若树中存在此元素
{
printf("this elem has existed!\n");
break;
}
if(e>n2->elem&&n2->rchild==NULL)
{
n2->rchild=n1;
n1->prev=n2;
break;
}
else if(e>n2->elem)
{
n2=n2->rchild;
}
else if(e<n2->elem&&n2->lchild==NULL)
{
n2->lchild=n1;
n1->prev=n2;
break;
}
else if(e<n2->elem)
{
n2=n2->lchild;
}
}
}
}
}
删除二叉排序树的结点
删除可能出现的几种情况
- 二叉排序树不存在。
- 二叉排序树中无将删除的结点。
- 二叉排序树中存在要删除的结点,并执行删除。
这里,我对第三种查找到了二叉排序树中存在该节点并删除进行展开讨论。
二叉排序树中的删除节点的三种情况
1.即将删除的节点为叶结点。
- 执行方法,将该叶结点删除,且将原本指向该叶结点的指针指向NULL;
2.即将删除的节点仅存在左子树或者仅存在右子树。(这里以仅存在左子树为例)
- 寻找即将删除节点的左子树的最右下节点(即左子树中的最大结点),将其赋值给即将删除的结点,赋值完成后再对该最右下结点进行处理。
- 这里要注意的是,这里删除节点的值被左子树中最大结点覆盖的同时,左子树中的最大结点也要随之删除,这里也要对其讨论是否存在左子树进行讨论。
3.即将删除的结点即存在右子树,也存在左字数。
- 这里有两种选择,以左子树中的最右下结点(即左子树中的最大结点)进行替换,或是以右子树中的最左下节点(即右子树中的最小结点)进行替换。
- 同样要注意的是,在替换的时候,要对被拿去替换的点进行讨论,看其是否存在左子树,或右子树。
void DeleteNode(pTree T)//删除二叉排序树的结点
{
int e;
BiTree n=T->root;
BiTree n1=NULL;
BiTree n2=NULL;
printf("Please input the elem you want to delete:\n");
scanf("%d",&e);
while(1)
{
if(n==NULL)//当树为空时
{
printf("the Tree is NULL!\n");
break;
}
if(e>n->elem&&n->rchild==NULL)//当元素不存在时
{
printf("The elem is not exist!\n");
break;
}
else if(e>n->elem)//当素大于当前结点的数字时
{
n=n->rchild;
}
else if(e<n->elem&&n->lchild==NULL)//当元素不存在时
{
printf("The elem is not exist!\n");
break;
}
else if(e<n->elem)//当元素小于当前结点的数字时
{
n=n->lchild;
}
else if(e==n->elem)//找到删除的结点
{
if(n->lchild==NULL&&n->rchild==NULL)//删除节点为叶子结点
{
n1=n->prev;//回溯双亲结点
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=NULL;
}
else
{
n1->rchild=NULL;
}
free(n);
}
else if(n->lchild==NULL&&n->rchild!=NULL)//删除结点右子树不为空,左子树为空
{
n1=n->prev;//回溯双亲
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=n->rchild;
}
else
{
n1->rchild=n->rchild;
}
free(n);
}
else if(n->rchild==NULL&&n->lchild!=NULL)//删除结点左子树不为空,右子树为空
{
n1=n->prev;//回溯双亲
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=n->lchild;
}
else
{
n1->rchild=n->lchild;
}
free(n);
}
else
{
n1=n;
n1=n->lchild;//走到左子树
while(n1->rchild!=NULL)//寻找左子树下最右边的结点
{
n1=n1->rchild;
}
n->elem=n1->elem;
if(n->lchild->elem==n1->elem)
{
n->lchild=n1->lchild;
free(n1);
}
else if(n1->lchild!=NULL)
{
n2=n1->prev;
n2->rchild=n1->lchild;
free(n1);
}
else
{
n2=n1->prev;
n2->rchild=NULL;
free(n1);
}
}
printf("Delete success!");
break;
}
}
中序遍历
- 这里以中序遍历排序二叉树。
void inOrderTraverse(BiTree p)//中序遍历
{
if(p->lchild!=NULL)//判断是否存在左儿子
{
inOrderTraverse(p->lchild);//向左儿子走一步
}
printf("%d ",p->elem);
if(p->rchild!=NULL)//判断是否存在右儿子
{
inOrderTraverse(p->rchild);
return;
}
else if(p->rchild==NULL)
{
return;
}
}
源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct Node
{
int elem;//存放数据
struct Node *lchild, *rchild;
struct Node *prev;
} TreeNode, *BiTree; //定义树节点的结构体
typedef struct tree
{
BiTree root;
}Tree,*pTree;
void CreateBST(pTree T)//构造二叉排序树
{
int e=0;//初始化
while(1)//while循环建立二叉排序树
{
printf("Please input the child of BST:");
printf("(input will over when you input -1.)\n");
scanf("%d",&e);//插入的数据
getchar();
if(e==-1)//非法判断
{
break;
}
BiTree n1=(BiTree)malloc(sizeof(TreeNode));//申请空间
BiTree n2=T->root;//初始化
n1->elem=e;
n1->lchild=NULL;
n1->rchild=NULL;
n1->prev=NULL;
if(T->root==NULL)//当树不存在时
{
T->root=n1;
}
else//当树存在时
{
while(1)//实现二叉树插入
{
if(e==n2->elem)//若树中存在此元素
{
printf("this elem has existed!\n");
break;
}
if(e>n2->elem&&n2->rchild==NULL)
{
n2->rchild=n1;
n1->prev=n2;
break;
}
else if(e>n2->elem)
{
n2=n2->rchild;
}
else if(e<n2->elem&&n2->lchild==NULL)
{
n2->lchild=n1;
n1->prev=n2;
break;
}
else if(e<n2->elem)
{
n2=n2->lchild;
}
}
}
}
}
void DeleteNode(pTree T)//删除二叉排序树的结点
{
int e;
BiTree n=T->root;
BiTree n1=NULL;
BiTree n2=NULL;
printf("Please input the elem you want to delete:\n");
scanf("%d",&e);
while(1)
{
if(n==NULL)//当树为空时
{
printf("the Tree is NULL!\n");
break;
}
if(e>n->elem&&n->rchild==NULL)//当元素不存在时
{
printf("The elem is not exist!\n");
break;
}
else if(e>n->elem)//当素大于当前结点的数字时
{
n=n->rchild;
}
else if(e<n->elem&&n->lchild==NULL)//当元素不存在时
{
printf("The elem is not exist!\n");
break;
}
else if(e<n->elem)//当元素小于当前结点的数字时
{
n=n->lchild;
}
else if(e==n->elem)//找到删除的结点
{
if(n->lchild==NULL&&n->rchild==NULL)//删除节点为叶子结点
{
n1=n->prev;//回溯双亲结点
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=NULL;
}
else
{
n1->rchild=NULL;
}
free(n);
}
else if(n->lchild==NULL&&n->rchild!=NULL)//删除结点右子树不为空,左子树为空
{
n1=n->prev;//回溯双亲
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=n->rchild;
}
else
{
n1->rchild=n->rchild;
}
free(n);
}
else if(n->rchild==NULL&&n->lchild!=NULL)//删除结点左子树不为空,右子树为空
{
n1=n->prev;//回溯双亲
if(n1->lchild!=NULL&&n1->lchild->elem==e)//判断当前节点为双亲的左儿子还是右儿子
{
n1->lchild=n->lchild;
}
else
{
n1->rchild=n->lchild;
}
free(n);
}
else
{
n1=n;
n1=n->lchild;//走到左子树
while(n1->rchild!=NULL)//寻找左子树下最右边的结点
{
n1=n1->rchild;
}
n->elem=n1->elem;
if(n->lchild->elem==n1->elem)
{
n->lchild=n1->lchild;
free(n1);
}
else if(n1->lchild!=NULL)
{
n2=n1->prev;
n2->rchild=n1->lchild;
free(n1);
}
else
{
n2=n1->prev;
n2->rchild=NULL;
free(n1);
}
}
printf("Delete success!");
break;
}
}
}
void inOrderTraverse(BiTree p)//中序遍历
{
if(p->lchild!=NULL)//判断是否存在左儿子
{
inOrderTraverse(p->lchild);//向左儿子走一步
}
printf("%d ",p->elem);
if(p->rchild!=NULL)//判断是否存在右儿子
{
inOrderTraverse(p->rchild);
return;
}
else if(p->rchild==NULL)
{
return;
}
}
int main()
{
pTree T=(pTree)malloc(sizeof(Tree));
BiTree n;
T->root=NULL;
CreateBST(T);
n=T->root;
inOrderTraverse(n);
printf("\n");
DeleteNode(T);
printf("\n");
inOrderTraverse(n);
return 0;
}
测试样例
45
12
53
3
37
100
24
61
90
78
-1
12
样例结果