二叉搜索树(BST树)删除结点操作
原题目是:BST树的建立及动态查找
//如果是理工的学生,请不要直接复制,这也是我的作业
如下,是原题:
生成50个在[200, 1000]之间互不相同的整数保存数组A中,以此数组元素作为关键字,设计实现以下操作的程序:
① 建立对应的BST树,按中序遍历算法输出所建立的BST树的结点;
② 在BST树上的查找指定的关键字(输入要查找的整数),给出操作的结论及相应的操作次数;
③ 在BST树上的删除指定的关键字(输入要删除的整数),给出操作的结论及相应的操作次数,按中序遍历算法输出所建立的BST树的结点;
④ 主函数通过调用函数实现以上操作。
这里我的插入50个数是随机插入,有一个很小的细节就是删除操作的删除根节点处理,
如果用在大型企业的范型数据操作是肯定不当的,但是对于只是int等这种几个字节的作业就不管了。
#include<stdio.h>
#include<stdlib.h>
#define DataType int
//二叉排序树的存储
typedef struct node {
DataType data;
struct node *left;
struct node *right;
}BiTreeNode;
//BST树的插入
int Insert(BiTreeNode **root,DataType item)//树结点的插入
{
BiTreeNode *p,*parent =NULL,*current;
current=*root;
while(current!=NULL)
{
if(current->data==item)
return 0;
parent=current;
if(current->data<item)
current=current->right;
else
current=current->left;
}
p=(BiTreeNode*)malloc(sizeof(BiTreeNode));
p->data=item;
p->left=NULL;
p->right=NULL;
if(parent==NULL)
*root=p;
else if(item<parent->data)
parent->left=p;
else
parent->right=p;
return 1;
}
//随机构建二叉搜索树(BST)
void creatTREE(BiTreeNode **tree)//创建树
{
int a[50],i=1,k;
a[0]=rand()%601+200;
k=Insert(tree,a[0]);
while(i<50){
a[i]=rand()%601+200;
if(Insert(tree,a[i])==0)
continue;
else
i++;
}
}
//中序排序
void Midprint(BiTreeNode *tree)
{
if(tree!=NULL)
{
Midprint(tree->left);
printf("%d ",tree->data);
Midprint(tree->right);
}
}
//查找指定关键字
BiTreeNode *Search(BiTreeNode *root ,DataType item,int *pos,int *times)//pos记录关键字是位于其父母结点的左孩子-1还是有孩子1,若根节点则为0,times为查找次数
{
BiTreeNode *p,*proot;
p=root;
proot=root;
*pos=0;
*times=1;
if(root!=NULL)
{
while(p!=NULL)
{
if(p->data==item)
return proot;
proot=p;
if(item>p->data)
{
p=p->right;
*pos=1;
}
else
{
p=p->left;
*pos=-1;
}
(*times)++;
}
*pos=-2;
}
}
//删除结点操作
void Delete(BiTreeNode* tree ,DataType num)
{
int times,pos;
BiTreeNode *preNode,*preselect,*select,*p;
preNode=Search(tree,num,&pos,×);//返回删除结点的父节点
if(pos!=-2)//若找得到该删除结点
{
if(pos==-1)//定位到该删除结点,指针指向它p
p=preNode->left;
else if(pos==1)//定位到该删除结点,指针指向它p
p=preNode->right;
else
p=preNode;////定位到该删除结点,指针指向它p,此处为根节点,无父节点,故删除结点即为preNode
if(p->left==NULL&&p->right==NULL)//第一中情况,p为叶子结点
{
free(p);
if(pos==-1)
preNode->left=NULL;
else
preNode->right=NULL;
}
else if(p->left==NULL)//第二种情况,p只有右孩子
{
if(pos==-1)
preNode->left=p->right;
else
preNode->right=p->right;
free(p);
}
else if(p->right==NULL)//第三种情况,p只有左孩子
{
if(pos==-1)
preNode->left=p->left;
else
preNode->right=p->left;
free(p);
}
else//第四种情况,有左右孩子(这里其实还有2种情况,是否为根节点)
{
select=preselect=p->right;
while(select->left!=NULL)
{
preselect=select;
select=select->left;
}
if(pos==0)//删除的为树的根结点
{
if(p->right==select)
p->right=select->right;
else{
p->data=select->data;
preselect->left=select->right;
}
free(select);
}
else//不是根节点
{
if(p->right==select)
{
select->left=p->left;
}
else
{
preselect->left=select->right;
select->left=p->left;
select->right=p->right;
}
if(pos==1)
preNode->right=select;
else if(pos==-1)
preNode->left=select;
free(p);
}
}
}
else if(pos==-2)//未找到删除结点的情况
{
printf("树中未找到该结点\n");
}
}
//主函数
int main()
{
BiTreeNode *tree=NULL,*p;
int k,num,index,times;
creatTREE(&tree);
printf("中序排序结构如下:\n");
Midprint(tree);
printf("\n");
while(1){
printf("1、查找整数 2、删除整数 3、遍历BST树\n");
scanf("%d",&k);
switch(k)
{
case 1:
printf("输入要查找的整数:\n");
scanf("%d",&num);
p=Search(tree ,num,&index,×);
if(index==1)
printf("经过%d次查找找到了%d\n",times,p->right->data);
else if(index==-1)
printf("经过%d次查找找到了%d\n",times,p->left->data);
else if(index==0)
printf("经过%d次查找找到了%d\n",times,p->data);
else
printf("不存在此结点!\n");
break;
case 2:
printf("输入要删除的整数:\n");
scanf("%d",&num);
Delete(tree ,num);
break;
case 3:
Midprint(tree);
printf("\n");
break;
default :
printf("输入有误!");
break;
}
}
return 0;
}
运行截图: