一、二叉搜索树的概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树
根据二叉搜索树的性质,我们很容易看出它的中序遍历是升序,下面画一个二叉搜索树,可以试着用中序遍历遍历一遍,对二叉树有所遗忘的可以去看看二叉树详解
二、二叉搜索树的实现
//定义结点
template<class T>
struct BSTreeNode {T val;BSTreeNode* left;BSTreeNode* right;BSTreeNode(const T& x):val(x),left(nullptr),right(nullptr){}
};template<class T>
class BSTree {typedef BSTreeNode<T> Node;
public:void InOrder();//中序遍历Node* Find(const T& x);//查找bool Insert(const T& x);//插入bool Erase(const T& x);//删除
private:Node*_root;
};
注意:下面代码涉及的递归函数都是写了两层,一层供对象调用,一层实现底层逻辑,因为_root被设置为了私有成员,而树的操作基本都需要遍历,所以通过成员函数实现对_root的使用
1.中序遍历
//这里二叉树的递归函数建议写两层,因为_root是私有成员只能在类内访问
void _InOrdered(Node* root) //该函数可以设为私有/保护,仅供类内使用,具体在场景
{if (root == __nullptr)return;_InOrdered(root->left);cout << root->val << " ";_InOrdered(root->right);
}void InOrdered()
{_InOrdered(_root);cout << endl;
}
2.查找
2.1迭代
Node* Find(const T& x) {Node* cur = _root;while (cur) {if (cur->val == x)return cur;else if (cur->val > x)cur = cur->left;elsecur = cur->right;}return nullptr;
}
2.2递归
Node* _FindR(Node* root, const T& x)
{if (root->val > x)return _FindR(root->left, x);else if (root->val < x)return _FindR(root->right, x);elsereturn root;return nullptr;
}Node* FindR(const T& x)
{return _FindR(_root, x);
}
3.插入
- 二叉搜索树中没有重复元素
3.1迭代
bool Insert(const T& x)
{if (_root == nullptr) //为空树,直接插入{_root = new Node(x);return true;}Node* cur = _root;Node* parent = nullptr;while (cur) {parent = cur;if (cur->val < x)cur = cur->right;else if (cur->val > x)cur = cur->left;else//出现该值出现过return false;}Node* newnode = new Node(x);if (parent->val > x) parent->left = newnode;else parent->right = newnode;return true;
}
3.2递归
bool _InsertR(Node*& root,const T& x) //注意这里的引用
{if (root == nullptr) {root = new Node(x);//这是引用,不是变量,不用担心连接问题,本质和用二级指针一样return true;}if (root->val > x)return _InsertR(root->left, x);else if (root->val < x)return _InsertR(root->right, x);elsereturn false;
}bool InsertR(const T& x) {return _InsertR(_root, x);
}
4.删除(重点)
4.1迭代
bool Erase(const T& x)
{Node* cur = _root;Node* parent = nullptr;while (cur) {int val = cur->val;if (x < val) {parent = cur;cur = cur->left;}else if (x > val) {parent = cur;cur = cur->right;}else {if (cur->left == nullptr) //左为空{if (parent->val > x)parent->left = cur->right;elseparent->right = cur->right;}else if (cur->right == nullptr)//右为空{if (parent->val > x)parent->left = cur->left;elseparent->right = cur->left;}else//左右都不为空{//这里采取在右子树种找最小结点Node* L = cur->right;Node* fa = cur;while (L->left) {fa = L;L = L->left;}swap(L->val, cur->val);if (fa != cur)fa->left = nullptr;else//这里需要注意如果最小结点就是右子树的根结点的情况fa->right = L->right;cur = L;}delete cur;return true;}}return false;
}
4.2递归
bool _EraseR(Node*& root, const T& x) //注意这里的引用
{if (root == nullptr)return false;if (root->val > x)return _EraseR(root->left, x);else if (root->val < x)return _EraseR(root->right, x);else {if (root->left == nullptr) {Node* del = root;root = root->right;delete del;return true;}else if (root->right == nullptr) {Node* del = root;root = root->left;delete del;return true;}else{Node* subleft = root->right;//找比它大的第一个数字while (subleft->left)subleft = subleft->left;swap(subleft->val, root->val);return _EraseR(root->right, x);//将问题转化为更小的子问题}}
}bool EraseR(const T& x)
{return _EraseR(_root, x);
}
三、完整版
template<class T>
struct BSTreeNode {T val;BSTreeNode* left;BSTreeNode* right;BSTreeNode(const T& x):val(x),left(nullptr),right(nullptr){}
};template<class T>
class BSTree {typedef BSTreeNode<T> Node;
public:bool Insert(const T& x) {if (_root == nullptr) {_root = new Node(x);return true;}Node* cur = _root;Node* parent = nullptr;while (cur) {parent = cur;if (cur->val < x) {cur = cur->right;}else if (cur->val > x) {cur = cur->left;}else{return false;}}Node* newnode = new Node(x);if (parent->val > x) parent->left = newnode;else parent->right = newnode;return true;}Node* find(const T& x) {Node* cur = _root;while (cur) {if (cur->val == x)return cur;else if (cur->val > x)cur = cur->left;elsecur = cur->right;}return nullptr;}bool erase(const T& x) {Node* cur = _root;Node* parent = nullptr;while (cur) {int val = cur->val;if (x < val) {parent = cur;cur = cur->left;}else if (x > val) {parent = cur;cur = cur->right;}else {if (cur->left == nullptr) //左为空{if (parent->val > x)parent->left = cur->right;elseparent->right = cur->right;}else if (cur->right == nullptr)//右为空{if (parent->val > x)parent->left = cur->left;elseparent->right = cur->left;}else//左右都不为空{Node* L = cur->right;Node* fa = cur;while (L->left) {fa = L;L = L->left;}swap(L->val, cur->val);if (fa != cur)fa->left = nullptr;elsefa->right = L->right;cur = L;}delete cur;return true;}}return false;}void _InOrdered(Node* root) {if (root == __nullptr)return;_InOrdered(root->left);cout << root->val << " ";_InOrdered(root->right);}void InOrdered() {_InOrdered(_root);cout << endl;}Node* FindR(const T& x) {return _FindR(_root, x);}bool InsertR(const T& x) {return _InsertR(_root, x);}bool EraseR(const T& x) {return _EraseR(_root, x);}//BSTree() {}BSTree() = default;//强制生成默认构造~BSTree(){Destroy(_root);}BSTree(const BSTree& t) {_root = Copy(t._root);}BSTree& operator=(const BSTree t){swap(t._root);return *this;}
private:Node* Copy(Node* root) {if (root == nullptr)return nullptr;Node* newnode = new Node(root->val);newnode->left = Copy(root->left);newnode->right = Copy(root->right);return newnode;}void Destroy(Node*& root) {if (root == nullptr)return;Destroy(root->left);Destroy(root->right);delete root;root = nullptr;}bool _EraseR(Node*& root, const T& x) {if (root == nullptr)return false;if (root->val > x)return _EraseR(root->left, x);else if (root->val < x)return _EraseR(root->right, x);else {if (root->left == nullptr) {Node* del = root;root = root->right;delete del;return true;}else if (root->right == nullptr) {Node* del = root;root = root->left;delete del;return true;}else{Node* subleft = root->right;//找比它大的第一个数字while (subleft->left) {subleft = subleft->left;}swap(subleft->val, root->val);return _EraseR(root->right, x);}}}bool _InsertR(Node*& root,const T& x) {if (root == nullptr) {root = new Node(x);return true;}if (root->val > x)return _InsertR(root->left, x);else if (root->val < x)return _InsertR(root->right, x);elsereturn false;}Node* _FindR(Node* root, const T& x) {if (root->val > x)return _FindR(root->left, x);else if (root->val < x)return _FindR(root->right, x);elsereturn root;return nullptr;}
private:Node* _root = nullptr;
};