主要包含删除、插入和搜索三个操作,关于操作的解释,可以看这里:
直接贴代码,参考:【二叉搜索树】的详细实现(C++)
重点需要注意的是,插入和删除操作传入的节点参数一定得是节点指针的引用,单单传入节点的指针是错误的,其实原因就是值传递和引用传递中形参初始化的区别,这两个操作设计到原节点的修改。
而遍历和查找操作则不强制要求必须传入节点指针的引用,直接传入节点的指针也是可以的,因为这两个操作并不会修改数据。
其他的都在注释里了。
//二叉搜索树结点类型
template<class T> struct BSTNode
{
T data; //数据域
BSTNode<T> *left, *right;
BSTNode() :left(NULL), right(NULL){}
BSTNode(const T d, BSTNode<T>* L = NULL, BSTNode<T>* R = NULL) : data(d), left(L), right(R){}
};
//二叉搜索树
template<class T> class BST{
public:
BST() : root(NULL){
T x;
// 新的一行ctrl+z结束读取
cout << "请输入待创建二叉树的节点值(回车后ctrl+z结束输入):" << endl;
while (cin >> x)
Insert(x, root);
}
// 析构
~BST(){ Destroy(root); }
// 插入
bool insert(T x){
return Insert(x, root);
}
// 删除
bool remove(T x){
return Remove(x, root);
}
// 搜索
bool search(T x){
return (Search(x, root) != NULL) ? true : false;
}
// 中序遍历
void inorder(){
cout << "中序遍历:";
Inorder(root);
cout << endl;
}
protected:
// 析构函数
void Destroy(BSTNode<T>* &root){
if (root == NULL)
return;
if (root->left != NULL)
Destroy(root->left);
if (root->right != NULL)
Destroy(root->right);
delete root;root = nullptr;
}
// ptr为根的二叉搜索树中插入值为a的结点
bool Insert(const T& a, BSTNode<T>* &ptr){ //第二个参数是指针的引用,因为插入是要进行修改的
if (ptr == NULL){
ptr = new BSTNode<T>(a);
return true;
}
else if(a < ptr->data)//小于,插入左子树
Insert(a, ptr->left);
else if(a > ptr->data)// 大于,插入右子树
Insert(a, ptr->right);
else //已在树中,不插入
return false;
}
// ptr为根的二叉搜索树中删除值为a的结点
bool Remove(const T& a, BSTNode<T>* &ptr){
if (ptr == NULL) return false;
BSTNode<T>* tmp;
if (a < ptr->data)
Remove(a, ptr->left);
else if (a > ptr->data)
Remove(a, ptr->right);
// 找到了要删除的结点
// 1、要删除的结点有左右子树
else if (ptr->left != NULL && ptr->right != NULL){
tmp = ptr->right; //右子树中搜索最小值(中序遍历的第一个结点)
while (tmp->left != NULL)
tmp = tmp->left;
ptr->data = tmp->data; //替换结点值(待删除结点与待删除结点的右子树中的最小值结点)
Remove(ptr->data, ptr->right); //删除掉这个最小值结点
}
// 2、不同时有左右子树
// 3、为叶子结点
else{
tmp = ptr;
if (ptr->left == NULL) //只有右子树
ptr = ptr->right; //将右子树接过来
else //只有左子树
ptr = ptr->left; //将左子树接过来
delete tmp;tmp = nullptr;
return true;
}
}
// ptr为根的二叉树中搜索值为x的结点
BSTNode<T>* Search(T x, BSTNode<T>* ptr){//搜索不涉及修改,参数有没有引用都可以
if (ptr == NULL)
return NULL;
else if (x < ptr->data)
return Search(x, ptr->left);
else if (x > ptr->data)
return Search(x, ptr->right);
else
return ptr;
}
//中序遍历
void Inorder(BSTNode<T>* root){//遍历不涉及修改,参数有没有引用都可以
if (root != NULL){
Inorder(root->left);
cout << root->data << " ";
Inorder(root->right);
}
}
private:
BSTNode<T>* root;
};
测试的cpp
:
#include <iostream>
#include "bsearchTree.h"
using namespace std;
int main(){
BST<int> tree;
cout << "请输入编号选择要进行的操作:" << endl;
cout << "1:插入元素 2:查询元素 3:删除元素 4:遍历" << endl;
cin.clear(); //清除错误状态(上一轮输入了ctrl+z)
int choice;
cout << "--请输入操作编号:" << endl;
while (cin >> choice){
int val;
switch (choice){
case 1:
cout << " 请输入要插入的元素:";
cin >> val;
tree.insert(val) ? cout << " 元素 " << val << " 插入成功!" << endl : cout << " 元素 " << val << " 已存在,插入失败!" << endl;
cout << "--请输入操作编号:" << endl;
break;
case 2:
cout << " 请输入要查询的元素:";
cin >> val;
tree.search(val) ? cout << " 元素 " << val << " 查询成功!" << endl : cout << " 元素 " << val << " 不存在,查询失败!" << endl;
cout << "--请输入操作编号:" << endl;
break;
case 3:
cout << " 请输入要删除的元素:";
cin >> val;
tree.remove(val) ? cout << " 元素 " << val << " 删除成功!" << endl : cout << " 元素 " << val << " 不存在,删除失败!" << endl;
cout << "请输入操作编号:" << endl;
break;
case 4:
tree.inorder();
cout << "--请输入操作编号:" << endl;
break;
default:
cout << "--请输入正确的操作编号!!!" << endl;
break;
}
}
return 0;
}