创建、查找、删除
codeblocks 17 通过
#include <iostream>
#define KeyType int
#define InfoType char
using namespace std;
typedef struct
{
KeyType key; // 关键字项
InfoType otherinfo; // 其他数据项
}ElemType; // 每个节点的数据类型
typedef struct BSTNode
{
ElemType data; // 节点的数据项
struct BSTNode *lchild, *rchild;
}BSTNode,*BSTree;
void InsertBST(BSTree &T, ElemType e)
{
if(!T) // T根节点为空
{
BSTree S = new BSTNode;
S->data = e;
S->lchild = S->rchild = NULL;
T=S;
}
else if(e.key < T->data.key)
InsertBST(T->lchild,e);
else if(e.key > T->data.key)
InsertBST(T->rchild,e);
}
void CreateBSTree(BSTree &T)
{
T = NULL; // 初始化为空树
int n=15;
//cin>>n:
while(n>0)
{
ElemType value;
cin>>value.key;
InsertBST(T,value);
n--;
}
//cout<<"Create Done !"<<endl;
}
BSTree SearchBST(BSTree &T, KeyType key)
{
if((!T)||key==T->data.key)
return T; // 查找结束 返回目标节点或者空指针
else if(key<T->data.key)
return SearchBST(T->lchild,key); // 在左子树中继续查找
else
return SearchBST(T->rchild,key); // 在右子树中继续查找
}
void InOrderTraverse(BSTree T)
{// 中序递归遍历
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data.key<<" ";
InOrderTraverse(T->rchild);
}
}
void DeleteBST(BSTree &T, KeyType key)
{// 从二叉排序树T中删除关键字等于key的节点
BSTree p = T, f=NULL, q; // 初始化
/*------下面的while循环从根开始查找关键字等于key的节点--------*/
while(p)
{
if(p->data.key == key)
break;
f = p;
if(p->data.key > key)
p = p->lchild;
else
p = p->rchild;
}
/*--------分别考虑三种情况,p所指的子树内部:左右子树都不为空,无左子树,无右子树---------*/
q = p;
if((p->lchild)&&(p->rchild)) // 左右子树都不为空
{
BSTree s = p->lchild;
while(s->rchild) // 查找p的左子树的最右节点,即p的直接前驱
{
q=s;s=s->rchild;
}
p->data=s->data; // 将s的data 赋值给要删除的节点p,p不能直接delete,需要保持p的左右子树关系
if(q!=p) // 如果pq不相同,说明s有右子树
q->rchild=s->lchild;
else // qp相同,说明s没有右子树
q->lchild=s->lchild;
delete s;
return; // 删除结束!!!
}
else if(!p->rchild) // 无右子树,只需要重接左子树
{
p = p->lchild;
}
else if(!p->lchild) // 无左子树,只需要重接右子树
{
p = p->rchild;
}
/*-------将p所指的子树挂接到其双亲节点*f相应位置-----------*/
if(!f) T=p; // 如果删除的是根节点
else if(q==f->lchild) // q是f的左子树,p接到f的左子树位置
f->lchild=p;
else // q是f的右子树,p接到f的右子树位置
f->rchild=p;
delete q;
}
int main()
{
BSTree T;
CreateBSTree(T);
InOrderTraverse(T);
cout<<"\n";
BSTree p;
KeyType key;
cin>>key;
p = SearchBST(T,key);
if(p)
cout<<"查找成功!"<<endl;
else
cout<<"not find it!"<<endl;
cin>>key;
DeleteBST(T,key);
InOrderTraverse(T);
}
/*
test data:
输入:
1 5 4 2 3 6 8 7 9 11 14 13 12 16 19
输出:
1 2 3 4 5 6 7 8 9 11 12 13 14 16 19
输入:
19
输出:
查找成功!
输入:
14
输出:
1 2 3 4 5 6 7 8 9 11 12 13 19 16
*/
附图便于思考删除算法
小甲鱼老师的代码,我加了注释:
int Delete(BSTree &p)
{
BSTree q, s;
/*-----待删除的节点只有左或右子树----*/
if(p->rchild == NULL)
{
q = p;
p = p->lchild;
delete q;
}
else if(p->lchild == NULL)
{
q = p;
p = p->rchild;
delete q;
}
/*-----待删除的节点有左和右子树-------*/
else
{
q = p;
s = p->lchild;
while(s->rchild)
{// 查找p的直接前驱,s记录,q是s的双亲
q = s;
s = s->rchild;
}
p->data.key = s->data.key; // 数据替换
if(q != p) // qp不想同,说明p的左子树有右子树
q->rchild = s->lchild;
else // qp相同,说明p的左子树没有右子树
q->lchild = s->lchild;
delete s;
}
return 1;
}
int DeleteBST_JiaYu(BSTree &T, KeyType key)
{// 返回删除结果,该函数也可通过调用search函数进行查找,再删除。
if(!T)
return -1;
else
{
if(key == T->data.key)
return Delete(T);
else if(key>T->data.key)
return DeleteBST_JiaYu(T->rchild,key);
else
return DeleteBST_JiaYu(T->lchild,key);
}
}
另附图:
完整代码code
// 二叉排序树 @ChenYe 2018/12/02
#include <iostream>
#define KeyType int
#define InfoType char
using namespace std;
typedef struct
{
KeyType key; // 关键字项
InfoType otherinfo; // 其他数据项
}ElemType; // 每个节点的数据类型
typedef struct BSTNode
{
ElemType data; // 节点的数据项
struct BSTNode *lchild, *rchild;
}BSTNode,*BSTree;
void InsertBST(BSTree &T, ElemType e)
{
if(!T) // T根节点为空
{
BSTree S = new BSTNode;
S->data = e;
S->lchild = S->rchild = NULL;
T=S;
}
else if(e.key < T->data.key)
InsertBST(T->lchild,e);
else if(e.key > T->data.key)
InsertBST(T->rchild,e);
}
void CreateBSTree(BSTree &T)
{
T = NULL; // 初始化为空树
int n=15;
//cin>>n:
while(n>0)
{
ElemType value;
cin>>value.key;
InsertBST(T,value);
n--;
}
//cout<<"Create Done !"<<endl;
}
BSTree SearchBST(BSTree &T, KeyType key)
{
if((!T)||key==T->data.key)
return T; // 查找结束 返回目标节点或者空指针
else if(key<T->data.key)
return SearchBST(T->lchild,key); // 在左子树中继续查找
else
return SearchBST(T->rchild,key); // 在右子树中继续查找
}
void InOrderTraverse(BSTree T)
{// 中序递归遍历
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data.key<<" ";
InOrderTraverse(T->rchild);
}
}
void DeleteBST(BSTree &T, KeyType key)
{// 从二叉排序树T中删除关键字等于key的节点
BSTree p = T, f=NULL, q; // 初始化
/*------下面的while循环从根开始查找关键字等于key的节点--------*/
while(p)
{
if(p->data.key == key)
break;
f = p;
if(p->data.key > key)
p = p->lchild;
else
p = p->rchild;
}
/*--------分别考虑三种情况,p所指的子树内部:左右子树都不为空,无左子树,无右子树---------*/
q = p;
if((p->lchild)&&(p->rchild)) // 左右子树都不为空
{
BSTree s = p->lchild;
while(s->rchild) // 查找p的左子树的最右节点,即p的直接前驱
{
q=s;s=s->rchild;
}
p->data=s->data; // 将s的data 赋值给要删除的节点p,p不能直接delete,需要保持p的左右子树关系
if(q!=p) // 如果pq不相同,说明s有右子树
q->rchild=s->lchild;
else // qp相同,说明s没有右子树
q->lchild=s->lchild;
delete s;
return; // 删除结束!!!
}
else if(!p->rchild) // 无右子树,只需要重接左子树
{
p = p->lchild;
}
else if(!p->lchild) // 无左子树,只需要重接右子树
{
p = p->rchild;
}
/*-------将p所指的子树挂接到其双亲节点*f相应位置-----------*/
if(!f) T=p; // 如果删除的是根节点
else if(q==f->lchild) // q是f的左子树,p接到f的左子树位置
f->lchild=p;
else // q是f的右子树,p接到f的右子树位置
f->rchild=p;
delete q;
}
int Delete(BSTree &p)
{
BSTree q, s;
/*-----待删除的节点只有左或右子树----*/
if(p->rchild == NULL)
{
q = p;
p = p->lchild;
delete q;
}
else if(p->lchild == NULL)
{
q = p;
p = p->rchild;
delete q;
}
/*-----待删除的节点有左和右子树-------*/
else
{
q = p;
s = p->lchild;
while(s->rchild)
{// 查找p的直接前驱,s记录,q是s的双亲
q = s;
s = s->rchild;
}
p->data.key = s->data.key; // 数据替换
if(q != p) // qp不想同,说明p的左子树有右子树
q->rchild = s->lchild;
else // qp相同,说明p的左子树没有右子树
q->lchild = s->lchild;
delete s;
}
return 1;
}
int DeleteBST_JiaYu(BSTree &T, KeyType key)
{// 返回删除结果,该函数也可通过调用search函数进行查找,再删除。
if(!T)
return -1;
else
{
if(key == T->data.key)
return Delete(T);
else if(key>T->data.key)
return DeleteBST_JiaYu(T->rchild,key);
else
return DeleteBST_JiaYu(T->lchild,key);
}
}
int main()
{
BSTree T;
CreateBSTree(T);
InOrderTraverse(T);
cout<<"\n";
BSTree p;
KeyType key;
cin>>key;
p = SearchBST(T,key);
if(p)
cout<<"查找成功!"<<endl;
else
cout<<"not find it!"<<endl;
cin>>key;
DeleteBST(T,key);
InOrderTraverse(T);
cout<<"\n新增测试,请输入要删除的数据:\n";
cin>>key;
DeleteBST_JiaYu(T,key);
InOrderTraverse(T);
}
/*
test data:
输入:
1 5 4 2 3 6 8 7 9 11 14 13 12 16 19
输出:
1 2 3 4 5 6 7 8 9 11 12 13 14 16 19
输入:
19
输出:
查找成功!
输入:
14
输出:
1 2 3 4 5 6 7 8 9 11 12 13 19 16
*/
测试