[C++笔记]二叉搜索树

news/2024/12/6 18:47:14/

BSTree.h

#pragma oncenamespace key {template<class K>//这里习惯用K而不是T,keystruct BSTreeNode {BSTreeNode<K>* _left;BSTreeNode<K>* _right;K _key;BSTreeNode(const K& key):_left(nullptr), _right(nullptr), _key(key){}};template<class K>class BSTree {//这里简写了,一般应该写全称:BinarySearchTreetypedef BSTreeNode<K> Node;//在类域内部重命名以防冲突public:BSTree() = default; // 制定强制生成默认构造BSTree(const BSTree<K>& t){_root = Copy(t._root);}BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}~BSTree(){Destroy(_root);//_root = nullptr;}//插入bool Insert(const K& key) {//可能插入失败,BSTree默认不允许冗余,若试图插入已存在的元素便会失败//树的形状只取决于插入的先后顺序,最先插入的元素便是根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;}}return false;}//删除(难点)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 {//找到目标,开始删除if (cur->_left == nullptr) {//1.左为空if (cur == _root) {//处理删根的情况_root = cur->_right;}else {if (parent->_left == cur) {parent->_left = cur->_right;//托孤右子节点}else {parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr) {//2.右为空if (cur == _root) {//处理删根的情况_root = cur->_left;}else {if (parent->_left == cur) {parent->_left = cur->_left;//托孤左子节点}else {parent->_right = cur->_right;}}delete cur;}else {//3.左右都不为空,不能托孤两个,改找保姆:左树的最大节点(左树最右节点)或右树的最小节点(右树最左节点)//这里找右树的最小节点Node* pminRight = cur;//不能是nullptr,若根就是最左节点会进不了循环Node* minRight = cur->_right;while (minRight->_left) {pminRight = minRight;minRight = minRight->_left;}cur->_key = minRight->_key;if (pminRight->_left == minRight) {pminRight->_left = minRight->_right;}else {pminRight->_right = minRight->_right;}delete minRight;}return true;}}return false;//未找到目标数值,故未进行删除操作}//递归插入bool InsertR(const K& key) {return _InsertR(_root, key);}//递归查找bool FindR(const K& key){return _FindR(_root, key);}//递归删除bool EraseR(const K& key){return _EraseR(_root, key);}//中序递归遍历void InOrder() {//为便于调用,套一层无参的壳让子函数带参递归_InOrder(_root);cout << endl;}protected:Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newRoot = new Node(root->_key);newRoot->_left = Copy(root->_left);newRoot->_right = Copy(root->_right);return newRoot;}void Destroy(Node*& root){if (root == nullptr) {return;}Destroy(root->_left);Destroy(root->_right);delete root;root = nullptr;}bool _FindR(Node* root, const K& key){if (root == nullptr)return false;if (root->_key == key)return true;if (root->_key < key)return _FindR(root->_right, key);elsereturn _FindR(root->_left, key);}bool _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;}}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->_right == nullptr){root = root->_left;}else if (root->_left == nullptr){root = root->_right;}else{Node* maxleft = root->_left;while (maxleft->_right){maxleft = maxleft->_right;}swap(root->_key, maxleft->_key);return _EraseR(root->_left, key);}delete del;return true;}}void _InOrder(Node* root) {//↑不能缺省传Node* root = _root ,因为://1.缺省参数必须是常量或全局变量或静态变量2.访问成员变量需要的this指针只能在函数内部使用。if (root == nullptr) {return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}private:Node* _root = nullptr;};}namespace key_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 (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, value);if (parent->_key < key){parent->_right = cur;}else{parent->_left = cur;}return true;}Node* 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 cur;}}return nullptr;}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{if (cur->_left == nullptr){if (cur == _root){_root = cur->_right;}else{if (parent->_left == cur){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){if (cur == _root){_root = cur->_left;}else{if (parent->_left == cur){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{Node* pminRight = cur;Node* minRight = cur->_right;while (minRight->_left){pminRight = minRight;minRight = minRight->_left;}cur->_key = minRight->_key;if (pminRight->_left == minRight){pminRight->_left = minRight->_right;}else{pminRight->_right = minRight->_right;}delete minRight;}return true;}}return false;}void InOrder(){_InOrder(_root);cout << endl;}protected:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << ":" << root->_value << endl;_InOrder(root->_right);}private:Node* _root = nullptr;};
}

test.cpp

#include <iostream>
#include <string>
using namespace std;#include "BSTree.h"void TestBSTree1(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };key::BSTree<int> t1;for (auto e : a){t1.Insert(e);}t1.InOrder();//t1.Erase(4);//t1.InOrder();//t1.Erase(14);//t1.InOrder();//t1.Erase(3);//t1.InOrder();t1.Erase(8);t1.InOrder();for (auto e : a){t1.Erase(e);t1.InOrder();}t1.InOrder();
}void TestBSTree2(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };key::BSTree<int> t1;for (auto e : a){t1.InsertR(e);}t1.InOrder();t1.EraseR(10);t1.EraseR(14);t1.EraseR(13);t1.InOrder();for (auto e : a){t1.EraseR(e);t1.InOrder();}t1.InOrder();
}void TestBSTree3(){int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };key::BSTree<int> t1;for (auto e : a){t1.InsertR(e);}t1.InOrder();key::BSTree<int> t2(t1);t2.InOrder();cout << endl;
}void TestBSTree4(){key_value::BSTree<string, string> dict;dict.Insert("sort", "排序");dict.Insert("left", "左");dict.Insert("right", "右");dict.Insert("string", "字符串");dict.Insert("insert", "插入");dict.Insert("erase", "删除");dict.Insert("菠萝", "面包");string str;while (cin >> str){auto ret = dict.Find(str);if (ret){cout << ":" << ret->_value << endl;}else{cout << "无此单词" << endl;}}
}void TestBSTree5(){string arr[] = { "门", "大桥", "鸭", "鸭", "大桥", "大桥", "大桥", "门", "门", "门", "二四六", "七八" };key_value::BSTree<string, int> countTree;for (auto str : arr){//key_value::BSTreeNode<string, int>* ret = countTree.Find(str);auto ret = countTree.Find(str);if (ret == nullptr){countTree.Insert(str, 1);}else{ret->_value++;}}countTree.InOrder();
}int main(){TestBSTree1();TestBSTree2();TestBSTree3();TestBSTree5();TestBSTree4();return 0;
}

运行结果:
在这里插入图片描述


http://www.ppmy.cn/news/988259.html

相关文章

ViT-vision transformer

ViT-vision transformer 介绍 Transformer最早是在NLP领域提出的&#xff0c;受此启发&#xff0c;Google将其用于图像&#xff0c;并对分类流程作尽量少的修改。 起源&#xff1a;从机器翻译的角度来看&#xff0c;一个句子想要翻译好&#xff0c;必须考虑上下文的信息&…

RedHat7.9安装mysql8.0.32 ↝ 二进制方式

RedHat7.9安装mysql8.0.32 ↝ 二进制方式 一、rpm方式安装1、检查是否安装了mariadb2、下载mysqlmysql8.0.323、上传解压4、创建安装目录&#xff0c;拷贝解压后的文件至安装目录/usr/local/mysql8.0/5、创建相关目录&#xff0c;开始安装6、创建mysql组和用户7、更改安装目录归…

Reinforcement Learning with Code 【Chapter 9. Policy Gradient Methods】

Reinforcement Learning with Code This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced such as ZhaoShiyu’s Mathematical Foundation of Reinforcement Learning, . 文章…

论文浅尝 | 预训练Transformer用于跨领域知识图谱补全

笔记整理&#xff1a;汪俊杰&#xff0c;浙江大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/pdf/2303.15682.pdf 动机 传统的直推式(tranductive)或者归纳式(inductive)的知识图谱补全(KGC)模型都关注于域内(in-domain)数据&#xff0c;而比较少关…

uni-app优雅的实现时间戳转换日期格式

现在显示的格式如下图&#xff1a; 我期望统一格式&#xff0c;所以不妨前端处理一下&#xff0c;核心代码如下 filters: {// 时间戳处理formatDate: function(value, spe /) {value value * 1000let data new Date(value);let year data.getFullYear();let month data.…

[UE4][C++]调整分屏模式下(本地多玩家)视口的显示位置和区域

一、分屏模式设置 在UE4中&#xff0c;多个玩家共用一个显示器就可以启用分屏模式&#xff0c;按玩家人数&#xff08;最大四人&#xff09;将屏幕均匀分割&#xff0c;显示不同玩家的视角&#xff0c;开发者可以在编辑器里设置分割类型&#xff08;水平或者垂直&#xff09;&a…

小程序 获取用户头像、昵称、手机号的组件封装(最新版)

在父组件引入该组件 <!-- 授权信息 --><auth-mes showModal"{{showModal}}" idautnMes bind:onConfirm"onConfirm"></auth-mes> 子组件详细代码为: authMes.wxml <!-- components/authMes/authMes.wxml --> <van-popup show…

web流程自动化详解

今天给大家带来Selenium的相关解释操作 一、Selenium Selenium是一个用于自动化Web浏览器操作的开源工具和框架。它提供了一组API&#xff08;应用程序接口&#xff09;&#xff0c;可以让开发人员使用多种编程语言&#xff08;如Java、Python、C#等&#xff09;编写测试脚本&…