目录
1.二叉搜索树的结构与特性
2.二叉搜索树的实现
(1)节点
(2)功能实现
插入:
删除:
查找:
打印:
3.测试
插入删除:
查找:
4.变种测试,即带value值
单词查找:
个数统计:
1.二叉搜索树的结构与特性
BSTree(二叉搜索树)是一个神奇的数据结构,其的特点是,左子树的所有值比根小,而右子树的所有值比根大
根据这种特性,我们可以从该结构中快速的搜索一个数的存在,速度则为树的高度次。
类似于这样的数。
2.二叉搜索树的实现
(1)节点
因为是树的结构,所以肯定少不了节点:
template<class K>struct BSTreeNode{BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};
利用初始化列表将其进行初始化。
(2)功能实现
该结构应该有插入、删除功能,因为叫搜索树,所有肯定有查找功能
插入:
bool Insert(const K& key){if (_root == nullptr){_root = new Node(key);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left; }else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key);if (parent->_key > key)parent->_left = cur;elseparent->_right = cur;return true;}
插入功能的实现逻辑很简单,只需要遵循根比左子树大,比右子树小即可。
删除:
bool Erase(const K& key){Node* cur = _root;Node* parent = cur;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{if (cur->_left == nullptr){if (parent == cur)_root = cur->_right;else{if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}else if(cur->_right == nullptr){if (parent == cur)_root = cur->_left;else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}else{Node* MinRight = cur->_left; parent = cur;while (MinRight->_right){parent = MinRight;MinRight = MinRight->_right;}cur->_key = MinRight->_key;if(parent->_right == MinRight)parent->_right = MinRight->_left;elseparent->_left = MinRight->_left;}return true;}}return false;}
删除功能的逻辑就比较复杂了,分三种情况讨论,一种是cur有两个子节点,二是cur有一个子节点,三是cur无子节点。
最后可以将二、三中情况合并处理,因为都存在nullptr。
查找:
bool find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->_left;}else if (key > cur->_key){cur = cur->_right;}else{return true;}}return false;}
查找逻辑简单,无须多说,只需根据二叉搜索树的特性画图即可。
同时加入一个打印功能方便观察:
打印:
void Inorder(){_Inorder(_root);cout << endl;}void _Inorder(Node* _root){if (_root == nullptr){return;}_Inorder(_root->_left);cout << _root->_key << ' ';_Inorder(_root->_right);}
创建一个_Inorder的原因是方便读取底层的_root元素,然后中序遍历即可
3.测试
插入删除:
查找:
1表示存在,0表示不存在
4.变种测试,即带value值
namespace YC_Value
{template<class K, class V>struct BSTreeNode{BSTreeNode<K, V>* _left;BSTreeNode<K, V>* _right;K _key;V _value;BSTreeNode(const K& key, const V& value):_left(nullptr), _right(nullptr), _key(key), _value(value){}};template<class K, class V>class BSTree{typedef BSTreeNode<K, V> Node;public:bool Insert(const K& key, const V& value){if (_root == nullptr){_root = new Node(key, value);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key, value);if (parent->_key > key)parent->_left = cur;elseparent->_right = cur;return true;}Node* find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->_left;}else if (key > cur->_key){cur = cur->_right;}else{return cur;}}return cur;}void Inorder(){_Inorder(_root);cout << endl;}bool Erase(const K& key){Node* cur = _root;Node* parent = cur;while (cur){if (key < cur->_key){parent = cur;cur = cur->_left;}else if (key > cur->_key){parent = cur;cur = cur->_right;}else{if (cur->_left == nullptr){if (parent == cur)_root = cur->_right;else{if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}}else if (cur->_right == nullptr){if (parent == cur)_root = cur->_left;else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}}else{Node* MinRight = cur->_left;parent = cur;while (MinRight->_right){parent = MinRight;MinRight = MinRight->_right;}cur->_key = MinRight->_key;if (parent->_right == MinRight)parent->_right = MinRight->_left;elseparent->_left = MinRight->_left;}return true;}}return false;}private:void _Inorder(Node* root){if (root == nullptr){return;}_Inorder(root->_left);cout << root->_key << ":" << root->_value << endl;_Inorder(root->_right);}private:Node* _root = nullptr;};void TestBSTree2(){BSTree<string, string> dict;dict.Insert("string", "字符串");dict.Insert("left", "左边");dict.Insert("insert", "插入");//...string str;while (cin >> str){BSTreeNode<string, string>* ret = dict.find(str);if (ret){cout << ret->_value << endl;}else{cout << "无此单词,请重新输入" << endl;}}}void TestBSTree3(){// 统计次数string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
"苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };BSTree<string, int> countTree;for (const auto& str : arr){auto ret = countTree.find(str);if (ret == nullptr){countTree.Insert(str, 1);}else{ret->_value++;}}countTree.Inorder();}
};