#include<iostream>
#include<cstdio>
using namespace std;
#include<stdlib.h>
#include<malloc.h>
typedef int Elemtype;
typedef struct BiTreenode
{
Elemtype data;
struct BiTreenode *Lchild;
struct BiTreenode *Rchild;
}*BiT,BiTree;
//1.查找元素,有Find递归方式和Find2非递归方式两种
Elemtype *Find(BiT BST,Elemtype x)
{
if(BST==NULL){return NULL;}
else
{
if(x==BST->data)
{
return &(BST->data);
}
else if(x<BST->data)
{
return Find(BST->Lchild,x);//向左子树进行搜索
}
else
{
return Find(BST->Rchild,x);//向右子树进行搜索
}
}
}
Elemtype *Find1(BiT BST,Elemtype x)
{
while(BST!=NULL)
{
if(x==BST->data){return &(BST->data);}
else if(x<BST->data)
{
BST=BST->Lchild;
}
else{BST=BST->Rchild;}
}
return NULL;
}
//2.数据的更新,与查找算法相同,只需要在返回之前将找到的值替换再返回即可再次省略;
//3.在二叉搜索树中插入元素x;(有递归和非递归两种)
void Insert(BiT *BST,Elemtype x)//用指针的指针是为了改变插入的树的父节点的左/右孩子的指针的值,(因为函数的形参特性)
{
if(*BST==NULL)
{
BiT p=(BiT)malloc(sizeof(BiTree));
p->data=x;
*BST=p;
p->Lchild=NULL;
p->Rchild=NULL;
return;
}
else
{
if(x<(*BST)->data)
{
Insert(&((*BST)->Lchild),x);
}
else
{
Insert(&((*BST)->Rchild),x);
}
}
return;
}
//非递归
void Insert2(BiT *BST,Elemtype x)
{
BiT p;
BiT t=*BST,parent=NULL;
while(t!=NULL)
{
parent=t;
if(x<t->data)
{
t=t->Lchild;
}
else{t=t->Rchild;}
}//循环之后parent存储的是带插入位置的双亲节点;
p=(BiT)malloc(sizeof(BiTree));
p->data=x;
p->Lchild=p->Rchild=NULL;
if(parent==NULL)
{
*BST=p;
}
else
{
if(x<parent->data)
{
parent->Lchild=p;
}
else
{
parent->Rchild=p;
}
}
return;
}
//4.删除
//a.删除叶子节点,只要将其双亲节点链接到它的指针置空即可
//b.删除单支节点,只要将其后继指针链接到它所在的链接位置即可;
//c.删除双支节点,一般采用的方法是首先把它的中序前驱节点的值赋给该节点的值域
//然后再删除它的中序前驱结点,若它的中序前驱节点还是双支节点,继续对其做同样的操作
//若是叶子结点或单支节点则做对应的操作,若是根节点则结束
int Delete(BiT*BST,Elemtype x)
{
BiT temp;
temp=*BST;
if(*BST==NULL)
{
return 0;
}
if( x < (*BST)->data )
{
return Delete( &( (*BST)->Lchild ),x);
}
if(x > (*BST)->data )
{
return Delete( &( (*BST)->Rchild ),x);
}
if( (*BST)->Lchild==NULL )//由于上面的if已经判断了x的大小,因此这里是一定x==(*BST)->data的,此时做字数为空,将右子树作为整个树并返回1
{
*BST=(*BST)->Rchild;
free(temp);
return 1;
}
else if( (*BST)->Rchild==NULL )//右子树为空,将左子树作为整个树返回1
{
*BST=(*BST)->Lchild;
free(temp);
return 1;
}
else
{
if( (*BST)->Lchild->Rchild==NULL )
{
(*BST)->data=(*BST)->Lchild->data;
return Delete( &(*BST)->Lchild,(*BST)->data );
}
else
{
BiT p1=*BST,p2=p1->Lchild;
while(p2->Rchild!=NULL)
{
p1=p2;
p2=p1->Rchild;
}
(*BST)->data=p2->data;
return Delete(&(p1->Rchild),p2->data);
}
}
}
//创建搜索二叉树
void create(BiT *BST,Elemtype a[],int n)
{
int i;
*BST=NULL;
for(i=0;i<n;i++)
{
Insert(BST,a[i]);
}
}
//输出二叉树(即可看出二叉树的表示法则)
void print(BiT PT)
{
if(PT!=NULL)
{
printf("%d ",PT->data);
if(PT->Lchild!=NULL||PT->Rchild!=NULL)
{
printf("(");
print(PT->Lchild);
if(PT->Rchild!=NULL){printf(",");}
print(PT->Rchild);
printf(")");
}
}
}
//中序遍历输出
void midprint(BiT PT)
{
if(PT!=NULL)
{
midprint(PT->Lchild);
printf("%d ",PT->data);
midprint(PT->Rchild);
}
}
//清空二叉树使之变为一颗空树
void BTclear(BiT *BST)//为了不再多开一个临时指针我们采用从叶子节点开始删除,即从尾往上删除提高效率
{
if(*BST!=NULL)
{
BTclear(&((*BST)->Lchild));//删除左子树;
BTclear(&((*BST)->Rchild));//删除右子树;
free(*BST);//释放根节点;
*BST=NULL;//置根节点为空防止成为野指针;
}
}
//主函数
int main()
{
int x,*px;
Elemtype a[10]={30,50,20,40,25,70,54,23,80,92};
BiT BST=NULL;
create(&BST,a,10);
printf("建立的二叉搜索树的按定义表示形式为:\n");
print(BST);
printf("\n");
printf("the mid order:\n");
midprint(BST);
printf("\n");
printf("pleas input the element which is wanted: ");
scanf(" %d",&x);//空格可以忽略前面的其他字符防止出错;
px=Find(BST,x);
if(px!=NULL)
{
printf("succeed in finding and we get the value is %d\n",*px);
}
else
{
printf("FAILED in fingding x!\n");
}
printf("please input the element inserted: ");
scanf(" %d",&x);
Insert(&BST,x);
printf("please input the element inserted: ");
scanf(" %d",&x);
Insert(&BST,x);
printf("please input the element inserted: ");
scanf(" %d",&x);
Insert(&BST,x);
printf("After the operation above and do the midprint:\n");
midprint(BST);
printf("\n");
printf("please input the element which will be deleted: ");
scanf(" %d",&x);
if(Delete(&(BST),x))
{
printf("1\n");
}
else{printf("0\n");}
printf("after the operation:\n");
midprint(BST);
printf("\n");
BTclear(&(BST));
return 0;
}
二叉搜索树的学习笔记(有解释)
最新推荐文章于 2025-03-25 18:34:36 发布