查找和插入的实现
伪代码
查找和插入的实现都用了递归的思想遍历左右子树。
/*查找*/
SearchBST(bt,k){
if(bt是空||bt.key等于k)
return bt;
if(bt.key大于k)
return SearchBST(bt.lchild,k) //遍历左子树
else
return SearchBST(bt.rchild,k) //遍历右子树
}
/*插入*/
insertBST(bt,k){
if(bt是空)
{
初始化bt; //创建bt新节点,并将bt的左右孩子都置为NULL
bt->key=k;
}
else if(k等于bt.key) return 0; //表明bt树已存在k这个结点
else if(k小于bt.key) return insertBST(bt->lchild, k); //遍历左子树
else return insertBST(bt->lchild, k); //遍历右子树
}
/*创建BST树*/
CreateBST(bt)
{
cin>>n>>a; //控制台获取树结点的个数n,和n个数存入数组a
while(i小于n) //i=0,从a[0]开始创建树bt
{
insertBST(bt,a[i]); //调用插入函数创建结点
i++;
}
return bt; //创建完成返回树bt
}
代码实现
/*查找*/
BSTNode* SearchBST(BSTNode* bt, Keytype k)
{
if (bt == NULL || bt->key == k)
return bt;
if (k < bt->key)
return SearchBST(bt->lchild, k);
else
return SearchBST(bt->rchild, k);
}
/*创建*/
int insertBST(BSTNode*& bt, Keytype k)
{
if (bt == NULL)
{
bt = new BSTNode;
bt->key = k;
bt->lchild = bt->rchild = NULL;
return 1;
}
else if (k == bt->key)
return 0;
else if (k < bt->key)
return insertBST(bt->lchild, k);
else
return insertBST(bt->rchild, k);
}
BSTNode* CreateBST(Keytype a[], int n)
{
BSTNode* bt = NULL;
int i = 0;
while (i < n)
{
insertBST(bt,a[i]);
i++;
}
return bt;
}
创建BST树并中序输出结果
运行演示
待生成的二叉排序树的结点为:50 30 80 20 40 90 10 25 35 85 23 88,个数为12,中序排序结果为:10 20 23 25 30 35 40 50 80 85 88 90。
运行结果正确。
完整代码代码
#include<iostream>
using namespace std;
typedef int Keytype;
typedef int InfoType;
typedef struct node
{
Keytype key;
InfoType data;
struct node* lchild, * rchild;
}BSTNode;
/*创建*/
int insertBST(BSTNode*& bt, Keytype k)
{
if (bt == NULL)
{
bt = new BSTNode;
bt->key = k;
bt->lchild = bt->rchild = NULL;
return 1;
}
else if (k == bt->key)
return 0;
else if (k < bt->key)
return insertBST(bt->lchild, k);
else
return insertBST(bt->rchild, k);
}
BSTNode* CreateBST(Keytype a[], int n)
{
BSTNode* bt = NULL;
int i = 0;
while (i < n)
{
insertBST(bt,a[i]);
i++;
}
return bt;
}
/*中序输出*/
void InOrder(BSTNode *b)
{
if (b != NULL)
{
InOrder(b->lchild);
cout << b->key
<< ' ';
InOrder(b->rchild);
}
else return;
}
int main()
{
BSTNode* bt;
int len,i=0;
Keytype a[50];
Keytype k;
memset(a, '0', sizeof(a)); //初始化数组
cout << "输入待生成的二叉排序树的结点个数:" << endl;
cin >> len;
cout << "输入二叉排序树结点:" << endl;
while (i<len)
{
cin >> a[i];
i++;
}
cout << "中序遍历二叉排序树的结果为:" << endl;
bt = CreateBST(a, len);
InOrder(bt);
return 0;
}
删除结点的实现
思路
删除的结点的情况分为两种:
- 待删除的结点只有左子树或只有右子树
- 待删除的结点既有左子树也有右子树
针对情况一,若结点只有左子树,只需将待删除的结点的左子树代替待删除结点的位置;若结点只有右子树,只需将待删除的结点的右子树代替待删除结点的位置。并释放删除结点的内存空间。
针对情况二,待删除的结点既有左子树又有右子树,找到起中序遍历结果的前驱结点的key值替代待删除的结点的key值,并释放删除前驱结点的内存空间。(所提到的前驱结点即为待删除结点的左子树的最右结点)
伪代码
/*删除*/
DeleteBST(bt,k)
{
if(bt为空) return 0;//bt为空树,删除结点失败
else{
if(k小于bt.key) return DeleteBST(bt->lchild,k);//递归遍历左子树,找到待删除的结点
else if(k大于bt.key) return DeleteBST(bt->rchild,k);//递归遍历右子树,找到待删除的结点
else //找到该结点了,进行删除操作
{
if(bt.lchild为空)
{
q=bt; //q指向待删除结点
bt=bt->rhild;
free(q); //释放结点内存
}
else if(bt.rchild为空)
{
q=bt; //q指向待删除结点
bt=bt->lhild;
free(q); //释放结点内存
}
else //该节点左右孩子都有
{
DeleteBST_LR(bt, bt->lchild); //调用函数
}
}
}
}
/*结点有左右子树的删除*/
DeleteBST_LR(p,r) //p为删除的结点,r为p的左结点
{
if (r->rchild不为空)
DeleteBST_LR(p, r->rchild); //递归遍历找到p结点左子树的最右结点
else //找到左子树的最右结点,即前驱结点
{
p->key = r->key; //将待删除结点的key值换为前驱结点的key值
q = r;
r = r->lchild;
free(q); //释放前驱结点的内存空间
}
}
具体代码
/*结点有左右子树的删除*/
void DeleteBST_LR(BSTNode* p, BSTNode*& r) //p为删除的结点,r为p的左结点
{
BSTNode* q;
if (r->rchild != NULL)
DeleteBST_LR(p, r->rchild); //找到p结点左子树的最右下结点
else
{
p->key = r->key;
q = r;
r = r->lchild;
free(q);
}
}
/*删除*/
int DeleteBST(BSTNode*& bt, Keytype k)
{
if (bt == NULL) return 0;//bt为空树,删除失败返回0
else {
if (k < bt->key)return DeleteBST(bt->lchild, k);
else if (k > bt->key)return DeleteBST(bt->rchild, k);
else {
BSTNode* q;
if (bt->lchild == NULL) {
q = bt;
bt = bt->rchild;
free(q);
}
else if (bt->rchild == NULL)
{
q = bt;
bt = bt->lchild;
free(q);
}
else {
DeleteBST_LR(bt, bt->lchild);
}
return 1;
}
}
}
运行结果展示
创建二叉排序树“50 30 80 20 40 90 10 25 35 85 23 88”后,删除前中序遍历结果为:10 20 23 25 30 35 40 50 80 85 88 90,删除结点80后,中序遍历结果为10 20 23 25 30 35 40 50 85 88 90。
运行结果正确。