目录
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;
else
parent->_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;
else
parent->_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;
else
parent->_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;
else
parent->_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();
}
};