🌈欢迎来到数据结构专栏~~搜索二叉树
- (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort
- 目前状态:大三非科班啃C++中
- 🌍博客主页:张小姐的猫~江湖背景
- 快上车🚘,握好方向盘跟我有一起打天下嘞!
- 送给自己的一句鸡汤🤔:
- 🔥真正的大师永远怀着一颗学徒的心
- 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏
- 🎉🎉欢迎持续关注!


二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则 左子树上所有节点的值都小于根节点的值
若它的左子树不为空,则 右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树


//查找bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_right;}else if (cur->_key < key){cur = cur->_left;}else{return true;}}}
思路如下:
cur 从root开始,插入的元素比当前位置元素小就往左走,比当前位置元素大就往右走,直到为空;parent记录 cur的前一个位置,最后判断cur是parent的左子树or右子树动画演示:

//相同的bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key > key){ parent = cur;cur = cur->_right;}else if (cur->_key < key){parent = cur;cur = cur->_left;}else{return false;}}//链接节点cur = new Node(key);if(parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}
删除有三种情况:

其实在代码层面第一种情况可以归类到第二种情况(没有左孩子,就链接上右孩子)
在代码层面实际上是四种:
root)
//删除bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{//找到了,开始删除,有三种情况//1、左为空//2、右为空//3、左右都不为空//4、删除跟root 要移动root(特殊情况)if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;cur = nullptr;}else if (cur->_right == nullptr){if (_root == cur){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;cur = nullptr;}else{//左右都不为空 —— 替换法删除//找到右树最小节点进行替换Node* min = cur->_right;Node* minparent = nullptr;while (min->_left){minparent = min;min = min->_left;}swap(cur->_key, min->_key);//注意min的右子树还有连接节点的可能//和判断min在哪边的问题?if (minparent->left = min){minparent->_left = min->_right;}else{minparent->_right = min->_right;}delete min;}return true;}}return false;}
唤起递归的记忆吧
void _FindR(Node* root, const K& key){//根为空的情况下if (root == nullptr){return false;}if (root->_key < key){return _FindR(root->_right);}else if (root->_key > key){return _FindR(root->_left);}else{return true;}}
要注意,这里有“神之一手”


void _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key);return true;}if (root->_key < key){return _InsertR(root->_right, key);}else if (root->_key > key){return _InsertR(root->_left, key);}else{return false;}}
神之操作:root = root->_left


bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false;}if (root->_key < key){return _EraseR(root->_right, key);}else if (root->_key > key){return _EraseR(root->_left, key);}else {//找到了要删除的位置Node* del = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{//找右树的最小节点 - 替换删除Node* min = root->_right;while (min->_left){min = min->_left;}swap(min->_key, root->_key);return _Erase(root->_right)}delete del;return true;}}
最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:log2Nlog_2 Nlog2N
最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:N2\frac{N}{2}2N

key的搜索模型,判断关键字在不在
以上都是把全部相关的资料都插入到一颗搜索树中,然后开始寻找,判断在不在
KV模型:每一个关键码key,都有与之对应的值Value,即的键值对。
// 改造二叉搜索树为KV结构
template
struct BSTNode
{BSTNode(const K& key = K(), const V& value = V()): _pLeft(nullptr), _pRight(nullptr), _key(key), _Value(value){}BSTNode* _pLeft;BSTNode* _pRight;K _key;V _value
};
template
class BSTree
{typedef BSTNode Node;typedef Node* PNode;
public:BSTree() : _pRoot(nullptr) {}PNode Find(const K& key);bool Insert(const K& key, const V& value)bool Erase(const K& key)
private:PNode _pRoot;
}void TestBSTree3()
{// 输入单词,查找单词对应的中文翻译BSTree dict;dict.Insert("string", "字符串");dict.Insert("tree", "树");dict.Insert("left", "左边、剩余");dict.Insert("right", "右边");dict.Insert("sort", "排序");// 插入词库中所有单词string str;while (cin >> str){BSTreeNode* ret = dict.Find(str);if (ret == nullptr){cout << "单词拼写错误,词库中没有这个单词:" << str << endl;}else{cout << str << "中文翻译:" << ret->_value << endl;}}
}
BinarySearchTree.h#pragma once#include
using namespace std;namespace Key
{templatestruct BSTreeNode{BSTreeNode* _left;BSTreeNode* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};//class BinarySearchTreetemplateclass BSTree{typedef BSTreeNode Node;public://插入bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//链接节点cur = new Node(key);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}//查找bool Find(const K& key){Node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_right;}else if (cur->_key < key){cur = cur->_left;}else{return true;}}}//删除bool Erase(const K& key){Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{//找到了,开始删除,有三种情况//1、左为空//2、右为空//3、左右都不为空//4、删除跟root 要移动root(特殊情况)if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;cur = nullptr;}else if (cur->_right == nullptr){if (_root == cur){_root = cur->_left;}else{if (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;cur = nullptr;}else{//左右都不为空 —— 替换法删除//找到右树最小节点进行替换Node* min = cur->_right;Node* minparent = nullptr;while (min->_left){minparent = min;min = min->_left;}swap(cur->_key, min->_key);//注意min的右子树还有连接节点的可能//和判断min在哪边的问题?if (minparent->_left = min){minparent->_left = min->_right;}else{minparent->_right = min->_right;}delete min;}return true;}}return false;}//这样就能避免this指针问题,因为递归必须显示给参数void InOrder(){_InOrder(_root);//这样就可以使用_rootcout << endl;}/// ///// 递归写法bool FindR(const K& key){return _FindR(_root, key);}bool InsertR(const K& key){return _InsertR(_root, key);}bool EraseR(const K& key){return _EraseR(_root, key);}~BSTree(){_Destory(_root);}//BSTree()//{}//C++11的用法:强制编译器生成默认构造BSTree() = default;//拷贝构造BSTree(const BSTree& t){_root = _Copy(t._root);}//t2 = t1BSTree& operator = (BSTree t){swap(_root, t._root);return *this;}private:Node* _Copy(Node* root){if (root == nullptr){return nullptr;}Node* copyRoot = new Node(root->_key);copyRoot->_left = _Copy(root->_left);copyRoot->_right = _Copy(root->_right);return copyRoot;}void _Destory(Node*& root){if (root == nullptr){return;}_Destory(root->_left);_Destory(root->_right);delete root;root = nullptr;}bool _EraseR(Node*& root, const K& key){if (root == nullptr){return false;}if (root->_key < key){return _EraseR(root->_right, key);}else if (root->_key > key){return _EraseR(root->_left, key);}else{//找到了要删除的位置Node* del = root;if (root->_left == nullptr){root = root->_right;}else if (root->_right == nullptr){root = root->_left;}else{//找右树的最小节点 - 替换删除Node* min = root->_right;while (min->_left){min = min->_left;}swap(min->_key, root->_key);return _Erase(root->_right);//防止找不到key的情况}delete del;return true;}}void _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key);return true;}if (root->_key < key){return _InsertR(root->_right, key);}else if (root->_key > key){return _InsertR(root->_left, key);}else{return false;}}void _FindR(Node* root, const K& key){//根为空的情况下if (root == nullptr){return false;}if (root->_key < key){return _FindR(root->_right, key);}else if (root->_key > key){return _FindR(root->_left, key);}else{return true;}}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;};void TestBSTree1(){BSTree t;int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };for (auto e : a){t.Insert(e);}//排序+去重t.InOrder();t.Erase(3);t.InOrder();t.Erase(6);t.InOrder();}void TestBSTree2(){BSTree t;int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };for (auto e : a){t.Insert(e);}BSTree copy = t;copy.InOrder();t.InOrder();}
}
test.c#include "BinarySearchTree.h"int main()
{//TestBSTree1();/*TestBSTree2();*/TestBSTree3();return 0;
}
多多更新
上一篇:华为开源自研AI框架昇思MindSpore数据处理:性能优化
下一篇:【软件STM32cubeIDE下STM32F4xx使用DMA+定时器+推PWM+点亮灯带WS2812相关-进阶(全数据流版)】