二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树
本文用来保存二叉搜索树的查找,插入,删除以及二叉树搜索树的建立等基本操作实现的完整代码:
直接上代码!详细算法介绍请参考此文:
二叉搜索树的查找/插入/删除以及二叉树搜索树的建立等基本操作的详细介绍
#include <iostream>
using namespace std;
const int flag = -1;
template<typename T>
struct BiTree {
T data;
BiTree<T>* left,//左子树
* right;//右子树
//构造函数
BiTree() {
left = right = NULL; }
BiTree(const T& theData) {
data = theData; left = right = NULL; }
BiTree(const T theData, BiTree* theLeft, BiTree* theRight)
{
data = theData; left = theLeft; right = theRight;
}
};
//创建一颗二叉树搜索树
template<typename T>BiTree<T>* create_bst();
//在二叉树搜索树bst中插入一个元素data
template<typename T>BiTree<T>* insert_bst(T data, BiTree<T>* &bst);
//在二叉搜索树中查找值为data的点,并放回该结点的地址
template<typename T> BiTree<T>* find_bst(T data, BiTree<T>* bst);
//递归中序遍历二叉树
template<typename T> void inOrder(BiTree<T>* bt);
//在二叉树搜索树中递归查找值最大的结点,并返回地址
template<typename T>BiTree<T>* find_max(BiTree<T>* bst);
//在二叉树搜索树中迭代查找值最小的结点,并返回地址
template<typename T>BiTree<T>* find_min(BiTree<T>* bst);
//在二叉搜索树bst中删除值为data的节点,并返回结果
template<typename T>BiTree<T>* delete_bst(T data, BiTree<T>*& bst);
int main()
{
//测试数据:15 30 35 36 50 33 41 -1
BiTree<int>* bst = create_bst<int>();
cout << "中序遍历结果为:"; inOrder(bst);cout << endl;
cout << "最大元素的值为:" << find_max(bst)->data << endl;
cout << "最小元素的值为:" << find_min(bst)->data << endl;
int x;
cout << "输入查找的元素的值:";
cin >> x;
if (find_bst(x, bst)->data == x) {
cout << "查找成功!" << endl;
}
else
cout << "查找失败";
cout << "输入要删除的元素的值:";
cin >> x;
cout << "删除该元素后,该二叉搜索树的中序遍历结果为:";
delete_bst(x, bst);
inOrder(bst); cout << endl;
}
//在二叉树搜索树bst中插入一个元素data
template<typename T>BiTree<T>* insert_bst(T data, BiTree<T>* &bst) {
if (!bst) {
//若原树为空,生成并返回一个结点的二叉搜索树
bst = new BiTree<T>;
bst->data = data;
bst->right = bst->left = NULL;
}
else //开始找要插入元素的位置
{
if (data < bst->data) //递归插入左子树
bst->left = insert_bst(data, bst->left);
else if (data > bst->data)//递归插入右子树
bst->right = insert_bst(data, bst->right);
}
return bst;
}
//创建一颗二叉树搜索树
template<typename T>BiTree<T>* create_bst() {
T data;
BiTree<T>* bst = NULL;
cin >> data;
while (data != flag)
{
insert_bst(data, bst);
cin >> data;
}
return bst;
}
//递归中序遍历二叉树
template<typename T> void inOrder(BiTree<T>* bt)
{
if (bt == NULL) //递归调用的结束条件
return;
inOrder(bt->left); //中序遍历递归左子树
//visit(bt); //访问树根
cout << bt->data << " " ;
inOrder(bt->right); // 中序遍历递归右子树
}
//在二叉搜索树中查找值为data的点,并放回该结点的地址
template<typename T> BiTree<T>* find_bst(T data,BiTree<T> *bst) {
BiTree<T>* temp = bst;
while (temp) {
if (temp->data == data) //查找成功,返回结点的找到结点的地址
return temp;
else if (temp->data < data)//向右子树中移动,继续查找
temp = temp->right;
else if (temp->data > data)//向左子树中移动,继续查找
temp = temp->left;
}
return NULL; //查找失败,bst为空或者bst中没有data
}
//在二叉树搜索树中迭代查找值最小的结点,并返回地址
template<typename T>BiTree<T>* find_min(BiTree<T>* bst)
{
if(bst)
while(bst->left != NULL)
bst = bst->left;
return bst;
}
//在二叉树搜索树中递归查找值最大的结点,并返回地址
template<typename T>BiTree<T>* find_max(BiTree<T>* bst)
{
if (!bst)return NULL;//如果二叉树为空,直接返回NULl
if (bst->right == NULL)//如果没有右儿子了,那么它就是最大的值
return bst;
else
return find_max(bst->right);//继续递归查找
}
//在二叉搜索树bst中删除值为data的节点
template<typename T>BiTree<T>* delete_bst(T data, BiTree<T>* &bst) {
BiTree<T> * target,* pre_target, * target_next,* pre_target_next,*temp;
//target是要删除的目标节点,pre_target是待删结点target的双亲节点
//target_next待删结点target的直接后继(target右子树的的最大元素)也就是我们要找的target的替代品
//pre_target_next是结点target_next的双亲节点
//temp临时指针
pre_target = NULL;//这个细节用来出力要删结点就是bst的根节点的情况
target = bst;
/*查找到target*/
while (target != NULL && target->data != data)
{
pre_target = target; //pre_target始终指向target的双亲
if (target->data < data)
target = target->right;
else if (target->data > data)
target = target->left;
}
if (target == NULL)//查找失败
{
cout << "查找失败";
return bst;
}
if (target->left && target->right)//如果目标节点的左右子树都不为空
{
pre_target_next = target;
target_next = target;
while (target_next->left != NULL)//给target_next定位
{
pre_target_next = target_next; //pre_target_next始终指向target_next的双亲
target_next = target->left;
}
target->data = target_next->data;
//targetd_next已经补上去了,所以将其右子树接到其父亲节点上
temp = target_next->right;
//这也要分两种情况
if(pre_target_next == target)
pre_target_next->right = temp;
else
pre_target_next->left = temp;
delete temp;
return bst;
}
else {
//第二种情况,待删结点是单支结点
//(第一种情况即待删结点是叶节点也包含在这里)
if (target->left != NULL)
temp = target->left;
else
temp = target->right;
if (pre_target == NULL)//如果要删除的节点就是根节点
{
delete temp;//直接释放掉待删结点的空间就可以了
}
else if(pre_target->right == target)//待删结点是其双亲节点的右孩子
{
pre_target->right = temp; //则把待删结点的孩子接上去就行
}
else if(pre_target->left == target)
{
pre_target->left = temp;
}
delete target;
return bst;
}
}