当前位置:网站首页>二叉搜索树的实现
二叉搜索树的实现
2022-08-02 20:27:00 【'派派'】
目录
1.二叉搜索树概念

2.二叉树插入的实现
如何插入?
如果树为空,直接插入。
如果树不为空,则将要插入的值与二叉树中各结点的值比较,最后再插入
例如:
代码实现:
先创建一个结构体存储每个结点的信息:
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
bool _InsertR(const K& key)
{
return _InsertR(_root, key);
}
private:
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (key > root->_key)
{
return _InsertR(root->_right, key);
}
else if (key < root->_key)
{
return _InsertR(root->_left, key);
}
else//不允许存在相同的值
return false;
}
}
root是父亲结点的左右指针的引用,修改root也就是修改父亲结点的左右指针,
3. 二叉搜索树的查找
bool _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;
}
}
4.二叉树的删除
二叉树的删除可分为两种情况。
1.要删除的结点只有一个孩子或无孩子。
2.要删除的结点有两个孩子。
例如:
第一种情况:
1.删除4;
2.删除10;
第二种情况:
1.删除3;在它的右子树中寻找中序下的第一个结点(关键码最小,也就是最左结点),用它的值填补到被删除
节点中,再来处理该结点的删除问题--替换法删除
bool _EraseR(Node*& root, const K& key)//root是父亲结点左右指针的引用
{
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* minRight = root->_right;//找到被删删除结点的右孩子,minRight
while (minRight->_left)//以minRight为根,找到最左的孩子。
{
minRight = minRight->_left;
}
swap(root->_key, minRight->_key);//将被删出的结点与最左孩子值替换。
return _EraseR(root->_right, key);//此时被删除的结点在之前最左孩子的位置,它
无左孩子,转换成了第一种情况对其删除。
}
delete del;
return true;
}
}
画图分析:
完整代码:
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{}
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
private:
void DestoryTree(Node* root)
{
if (root == nullptr)
return;
DestoryTree(root->_left);
DestoryTree(root->_right);
delete root;
}
Node* CopyTree(Node* root)
{
if (root == nullptr)
return nullptr;
Node* copyNode = new Node(root->_key);
copyNode->_left = CopyTree(root->_left);
copyNode->_right = CopyTree(root->_right);
return copyNode;
}
public:
// 强制编译器自己生成构造,C++11支持
BSTree() = default;
BSTree(const BSTree<K>& t)//写了拷贝构造,不会默认生成构造函数
{
_root = CopyTree(t._root);
}
BSTree<K>& operator=(BSTree<K> t)
{
swap(_root, t._root);
return *this;
}
~BSTree()
{
DestoryTree(_root);
_root = nullptr;
}
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);
}
void InOrder()
{
_InOrder(_root);
}
private:
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* minRight = root->_right;
while (minRight->_left)
{
minRight = minRight->_left;
}
swap(root->_key, minRight->_key);
return _EraseR(root->_right, key);
}
delete del;
return true;
}
}
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (key > root->_key)
{
return _InsertR(root->_right, key);
}
else if (key < root->_key)
{
return _InsertR(root->_left, key);
}
else
return false;
}
bool _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;
};
5.二叉搜索树的应用
5.1 K模型
5.2 KV模型
template<class K, class V>
struct BSTreeNode
{
BSTreeNode<K, V>* _left;
BSTreeNode<K, V>* _right;
const 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:
void InOrder()
{
_InOrder(_root);
cout << endl;
}
Node* FindR(const K& key)//返回结点的指针,可对结点内容进行修改
{
return _FindR(_root, key);
}
bool InsertR(const K& key, const V& value)
{
return _InsertR(_root, key, value);
}
private:
bool _InsertR(Node*& root, const K& key, const V& value)
{
if (root == nullptr)
{
root = new Node(key, value);
return true;
}
if (root->_key < key)
return _InsertR(root->_right, key, value);
else if (root->_key > key)
return _InsertR(root->_left, key, value);
else
return false;
}
Node* _FindR(Node* root, const K& key)
{
if (root == nullptr)
return nullptr;
if (root->_key < key)
{
return _FindR(root->_right, key);
}
else if (root->_key > key)
{
return _FindR(root->_left, key);
}
else
{
return root;
}
}
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 test2()
{
string arr[] = { "香蕉","苹果","梨","桃子","梨","香蕉","黄瓜" };
BSTree<string, int> p;
for (auto ch : arr)
{
auto ret = p.FindR(ch);
if (ret==nullptr)
{
p.InsertR(ch, 1);
}
else
{
ret->_value++;
}
}
p.InOrder();
}
int main()
{
test2();
return 0;
}
结果:
黄瓜:1
梨:2
苹果:1
桃子:1
香蕉:2
边栏推荐
猜你喜欢
随机推荐
setup syntax sugar defineProps defineEmits defineExpose
js Fetch返回数据res.json()报错问题
太魔人招新啦|快来加入我们吧!
Use the TCP protocol, we won't lost package?
WPF development through practical 】 【 automatic production management platform
MSTP与STP
对话亚洲高校首个博士论文奖-裘捷中丨KDD2022
Flutter 常见异常分析
J9 Digital Currency Theory: Identifying Web3's New Scarcity: Open Source Developers
js如何获取浏览器缩放比例
EasyExcel dynamic parsing and save table columns
你是几星测试/开发程序员?技术型选手王大拿......
Wiring diagrams of switches, motors, circuit breakers, thermocouples, and meters
Which thread pool does Async use?
The five classification of software testing
Day35 LeetCode
SQL基础练习题(mysql)
Linphone 被叫方如何解析来电SIP消息中的自定义头消息
【SLAM】DM-VIO(ros版)安装和论文解读
setup语法糖 defineProps defineEmits defineExpose