当前位置:网站首页>二叉搜索树的实现
二叉搜索树的实现
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
边栏推荐
- Wintun:一款惊艳的 WireGuard 虚拟网卡接口驱动
- 华为设备配置BFD多跳检测
- How to use windbg check c # a thread stack size?
- ABAP grammar small review
- The Orsay in Informatics (1256: Bouquet for Algernon)
- 实现fashion_minst服装图像分类
- 你是几星测试/开发程序员?技术型选手王大拿......
- 基本语法(三)
- 软件测试的流程规范有哪些?具体要怎么做?
- Xcode13.1 run engineering error fatal error: 'IFlyMSC/IFly h' file not found
猜你喜欢
The time series database has been developed for 5 years. What problem does it need to solve?
pytorch的tensor创建和操作记录
Common tools and test methods for interface testing (Introduction)
56.【全局变量和局部变量专题】
开关、电机、断路器、电热偶、电表接线图大全
Solve the docker mysql can't write Chinese
Li Mu hands-on learning deep learning V2-bert and code implementation
Thread线程类基本使用(上)
【手撕AHB-APB Bridge】~ AMBA总线 之 APB
Qt提升自定义控件,找不到头文件
随机推荐
C语言中变量在内存中的保存与访问
新增指令 v-memo
js如何获取浏览器缩放比例
.NET performance optimization - you should set initial size for collection types
基于 flex 布局实现的三栏布局
C# Barrier class
有效解决MySQL报错:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO/YES)
你是几星测试/开发程序员?技术型选手王大拿......
奥特学园ROS笔记--7(289-325节)
php 单引号 双引号 -> => return echo
DataGrip 安装教程 详细版
Golang source code analysis: juju/ratelimit
arm64麒麟安装paddlehub(国产化)
传感器工作原理
EasyExcel dynamic parsing and save table columns
线程安全(上)
基于 outline 实现头像剪裁以及预览
2170. 使数组变成交替数组的最少操作数
浅议.NET遗留应用改造
信息学奥赛一本通(1259:【例9.3】求最长不下降序列)