北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
获取更多文章 请访问专栏:
北邮22信通_青山如墨雨如画的博客-CSDN博客
目录
讲解
1.构造函数
2.析构函数
3.查询函数
4.删除操作 (重点)
第一种情况:
第二种情况:
第三种情况:
结合实例详解第三种情况
1.删除30:
2.删除20:
代码部分
效果图:
代码:
运行结果:
讲解
1.构造函数
BST树表的一大特点,就是任取一个节点,其左子树中任意一个节点的权值都小于这个结点,右子树中任意一个节点的权值都大于这个节点。根据这种特性,要想实现构造函数的书写,我们就必须考虑这样一个问题:每给出一个权值,我们要将这个权值插入到树表的哪个位置上。
所以首先讲解insert_bst函数:
insert函数传入两个参数,一个是访问的初始位置,用指针指示;另一个参数是待插入的节点。
首先,如果这个树表是空的,那么直接将这个待插入的节点作为根节点插入。
其次,如果树表不是空的,那么就会有两种情况:待插入的节点的权值大于或者小于当前访问节点的权值。应用递归思想,如果大于,调用insert_bst,传入当前位置所在节点的右孩子节点和待插入节点;如果小于,调用insert_bst,传入当前位置所在节点的左孩子节点和待插入节点。
代码部分:
template<class temp>
void BST<temp>::insert_bst(binnode<temp>*& r, binnode<temp>* s)
{
if (r == NULL)
r = s;
else if (s->data < r->data)
insert_bst(r->leftchild, s);
else
insert_bst(r->rightchild, s);
}
通过这样的插入方式,就可以让二叉树成为一颗有顺序的BST树。
insert函数实现之后,构造函数的实现显而易见。
每传入一个数据,新建一个节点,开辟一个堆区空间,为新节点赋值,调用insert函数将赋值过后的节点直接插入到BST树中,从而实现了BST树的构造。
2.析构函数
析构函数的实现方法和二叉树析构函数的实现方法相同,核心思路是递归函数,这里不做赘述。
代码部分:
template<class temp>
void BST<temp>::release(binnode<temp>* r)
{
if (r != NULL)
{
release(r->leftchild);
release(r->rightchild);
delete r;
}
}
template<class temp>
BST<temp>::~BST()
{
release(this->root);
}
3.查询函数
查询函数也是应用递归思想和BST树的特性。根据BST左子树任一结点小于当前节点右子树任一节点大于当前节点的特性,传入两个参数,一个是开始访问的位置,一个是待查询的数据。
如果当前位置不存在,返回空指针;
如果当前位置的权值正好等于待查询数据,返回指向这个位置的指针;
如果数据小于访问位置的权值,递归调用本函数,查询访问位置的左子树;
如果查询数据大于访问位置的权值,递归调用本函数,查询访问位置的右子树。
代码部分:
template<class temp>
binnode<temp>* BST<temp>::search
(binnode<temp>*& r, temp k)
{
if (r == NULL)
return NULL;
if (k == r->data)
return r;
else if (k < r->data)
return search(r->leftchild, k);
else
return search(r->rightchild, k);
}
4.删除操作 (重点)
核心算法是删除关键字所在节点。
在一颗有顺序的二叉树中删除一个结点,确实不容易实现。我们不仅要考虑如何删除节点,还需哟考虑删除节点之后,这个节点的子树怎么重新连接回原来的BST树中。
删除一个节点,无非有3种情况,从易到难依次是:
删除的节点是叶子结点;
删除的节点只有左子树或只有右子树;
删除的节点左右子树都存在。
第一种情况:
直接删除即可;
第二种情况:
删除的节点只有左子树或者只有右子树:
现在设要删除的节点是小明。小明只有左孩子们或只有右孩子们。
如果小明是他爸爸的左孩子,那么小明的孩子们都比小明爸爸的权值小,那么删除小明之后,小明的孩子们都接在小明爸爸的左孩子位置上;如果小明是爸爸的右孩子,那么小明的孩子们都比小明爸爸的权值大,那么删除小明之后,小明的孩子们都接在小明爸爸的右孩子位置上。
第三种情况:
第三种情况也是最复杂的一种情况:如果待删除的节点既有左孩子又有右孩子:
旧帝驾崩需要从王室中选出一个符合条件的世子继承王位。旧帝留下两个分支,左边是等待继位的世子们,右边是朝廷重臣。挑选的世子必须是嫡长子,也就是比所有待继位的世子年龄大,同时要比群臣年龄小。
找到之后,新帝登基,原先所在御殿拆除。
代码部分:
template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
binnode<temp>* q, * s;
if (r->leftchild == NULL)
{
q = r;
r = r->rightchild;
delete q;
}
else if (r->rightchild == NULL)
{
q = r;
r = r->leftchild;
delete q;
}
else
{
q = r;
s = r->leftchild;
while (s->rightchild != NULL)
{
q = s;
s = s->rightchild;
}
r->data = s->data;
if (q != r)
q->rightchild = s->leftchild;
else
r->leftchild = s->leftchild;
delete s;
}
}
结合实例详解第三种情况
BST树:
1.删除30:
2.删除20:
删除操作总体代码:
template<class temp>
bool BST<temp>::delete_key(binnode<temp>*&r,temp k)
{
if (r == NULL)
return false;
else
{
if (k == r->data)
{
delete_node(r);
return true;
}
else if (k < r->data)
return delete_key(r->leftchild, k);
else
return delete_key(r->rightchild, k);
}
}
template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
binnode<temp>* q, * s;
if (r->leftchild == NULL)
{
q = r;
r = r->rightchild;
delete q;
}
else if (r->rightchild == NULL)
{
q = r;
r = r->leftchild;
delete q;
}
else
{
q = r;
s = r->leftchild;
while (s->rightchild != NULL)
{
q = s;
s = s->rightchild;
}
r->data = s->data;
if (q != r)
q->rightchild = s->leftchild;
else
r->leftchild = s->leftchild;
delete s;
}
}
代码部分
效果图:
代码:
#include<iostream>
using namespace std;
class student
{
private:
int ID;
string name;
public:
int existence;
student()
{
this->ID = 0;
this->name = "unknown name";
this->existence = 0;
}
student(int ID, string name)
{
this->ID = ID;
this->name = name;
this->existence = 1;
}
friend ostream& operator<<(ostream& output, student& s)
{
output << s.ID << " " << s.name << endl;
return output;
}
void print()
{
cout << this->name << " " << this->ID << endl;
}
bool operator <(student& s)
{
return (this->ID < s.ID) ? true : false;
}
bool operator>(student& s)
{
return (this->ID > s.ID) ? true : false;
}
bool operator==(student& s)
{
return (this->ID == s.ID)
&& (this->name == s.name) ? true : false;
}
bool operator !=(student& s)
{
return (this->ID != s.ID)
|| (this->name != s.name) ? true : false;
}
};
template<class temp>
struct binnode
{
temp data;
binnode<temp>* leftchild;
binnode<temp>* rightchild;
};
template<class temp>
class BST
{
public:
BST(temp r[], int n);
void insert_bst(binnode<temp>*& r, binnode<temp>* s);
//调用顺序:构造函数调用insert函数。
binnode<temp>* search(binnode<temp>*& r, temp key);
void is_found(binnode<temp>*& r, temp k)
{
binnode<temp>* p = search(r, k);
if (p != NULL)
cout << "is_found:" << p->data;
else
cout << "un_found";
}
binnode<temp>* get_root()
{
return this->root;
}
void release(binnode<temp>* r);
~BST();
//调用顺序:析构函数调用release函数。
void delete_node(binnode<temp>*& r);
bool delete_key(binnode<temp>*& r, temp key);
//调用顺序:delete_key函数调用delete_node函数。
void inorder_print(binnode<temp>*p);
private:
binnode<temp>* root;
};
template<class temp>
BST<temp>::BST(temp r[], int n)
{
this->root = NULL;
for (int i = 0; i < n; i++)
{
binnode<temp>* s = new binnode<temp>;
s->data = r[i];
s->leftchild = s->rightchild = NULL;
insert_bst(this->root, s);
}
}
template<class temp>
void BST<temp>::insert_bst(binnode<temp>*& r, binnode<temp>* s)
{
if (r == NULL)
r = s;
else if (s->data < r->data)
insert_bst(r->leftchild, s);
else
insert_bst(r->rightchild, s);
}
template<class temp>
binnode<temp>* BST<temp>::search
(binnode<temp>*& r, temp k)
{
if (r == NULL)
return NULL;
if (k == r->data)
return r;
else if (k < r->data)
return search(r->leftchild, k);
else
return search(r->rightchild, k);
}
template<class temp>
void BST<temp>::release(binnode<temp>* r)
{
if (r != NULL)
{
release(r->leftchild);
release(r->rightchild);
delete r;
}
}
template<class temp>
BST<temp>::~BST()
{
release(this->root);
}
template<class temp>
bool BST<temp>::delete_key(binnode<temp>*&r,temp k)
{
if (r == NULL)
return false;
else
{
if (k == r->data)
{
delete_node(r);
return true;
}
else if (k < r->data)
return delete_key(r->leftchild, k);
else
return delete_key(r->rightchild, k);
}
}
template<class temp>
void BST<temp>::delete_node(binnode<temp>*& r)
{
binnode<temp>* q, * s;
if (r->leftchild == NULL)
{
q = r;
r = r->rightchild;
delete q;
}
else if (r->rightchild == NULL)
{
q = r;
r = r->leftchild;
delete q;
}
else
{
q = r;
s = r->leftchild;
while (s->rightchild != NULL)
{
q = s;
s = s->rightchild;
}
r->data = s->data;
if (q != r)
q->rightchild = s->leftchild;
else
r->leftchild = s->leftchild;
delete s;
}
}
template<class temp>
void BST<temp>::inorder_print(binnode<temp>* p)
{
if(p != NULL)
{
inorder_print(p->leftchild);
cout << p->data;
inorder_print(p->rightchild);
}
}
int main()
{
system("color 0A");
student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
BST<student>bst(stu, 5);
binnode<student>* p = bst.get_root();
bst.inorder_print(p);
student s(2, "wang");
bst.is_found(p, s);
bst.delete_key(p, s);
bst.inorder_print(p);
bst.is_found(p, s);
return 0;
}