当前位置: 首页 > news >正文

【C++】2.3 二叉搜索树的实现

二叉搜索树

左子树<=根,右子树>=根

根据需求不同,等于的元素可能会被去重也可能会被留下

这样查找一个数就可以只遍历一次,数大选哪个右走,小往左走

查找效率:ologn~on

改进:AVL树,红黑树,B树系列,查找效率:ologn

模拟实现(不多插入相同元素)


一.Key结构
1. 节点的定义

代码语言:javascript

AI代码解释

template<class K> struct bsnode { K _key; bsnode* _left; bsnode* _right; bsnode(const K& key) :_key(key) ,_left(nullptr) ,_right(nullptr) {} };
2. 成员

代码语言:javascript

AI代码解释

typedef bsnode<K> node; node* _root = nullptr;

代码语言:javascript

AI代码解释

这样,可以不用写构造函数
3. 二叉树的插入

代码语言:javascript

AI代码解释

bool insert(const K& key) { if (_root == nullptr) { _root = new node(key); return 1; } node* cur = _root; node* par = nullptr; while (cur != nullptr) { if (cur->_key < key) { par = cur; cur = cur->_right; } else if (cur->_key > key) { par = cur; cur = cur->_left; } else { return 0; } } node* newnode = new node(key); if (par->_key < key) { par->_right = newnode; } else { par->_left = newnode; } return 1; }

方案:定一个cur的指针,当根节点小于插入元素,向右走,大于则向左走

如果已经有这个数了,则返回false

如果cur为空,则构造一个节点,和cur最后一次经过的节点连接,返回true

那么,cur已经指向空了,怎么才能知道cur最后一次经过的节点?

在额外弄一个par指针尾随cur即可

4. 树排序

二叉搜索树的中序遍历(左->中->右)的特点:为从小到大的数组

因此,可以中序遍历得到有序数组,叫做树排序

代码语言:javascript

AI代码解释

void inorder() { _inorder(_root); } void _inorder(node* root) { if (root == nullptr)return; _inorder(root->_left); std::cout << root->_key << " "; _inorder(root->_right); }
5. 查找

和插入同理,但是要找的值大于节点向右走,小于往左走

代码语言:javascript

AI代码解释

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 1; } } return 0; }
6. 删除(重要)

删除的集中情况(设删除节点的名称为M)

  1. M子节点左右均空:直接删除即可
  2. M子节点一个为空:M父节点指向M的一个子节点,再删除M
  3. M左右节点都为空: 替换删除法:将M节点用下面的节点交换,再删除下面的数字节点 那么和哪个节点交换既可以做到快速删除又可以做到保持左子树<=根,右子树>=根的性质呢 和左子树的最右节点(最大节点)或右子树的最左节点(最小节点) (1)删除快速:由于两个情况都是最左或最右节点,因此一定满足删除方案1或2,因此删除简单 (2)由于两个情况要么是小的最大,要么是大的最小,因此性质也是满足的 下面用右边最左来演示

代码语言:javascript

AI代码解释

bool erase(const K& _key) { node* par = nullptr; node* cur = _root; while (cur) { if (cur->_key < key) { par = cur; cur = cur->_right; } else if (cur->_key > key) { par = cur; cur = cur->_left; } else { if (cur->_left == nullptr) { if (cur == _root) { _root = cur->_right; } else { if (par->_left == cur) { par->_left = cur->_right; } else { par->_right = cur->_right; } } delete cur; } else if (cur->_right == nullptr) { if (cur == _root) { _root = cur->_left; } else { if (par->_left == cur) { par->_left = cur->_left; } else { par->_right = cur->_left; } } delete cur; } else { node* rp = cur; node* r = cur->_right; while (r->_left) { rp = r; r = r->_left; } cur->_key = r->_key; if (rp->_left == r) { rp->_left = r->_right; } else { rp->_right = r->_right; } delete r; } return 1; } } return 0; }

代码逻辑

  1. 先找值为val的节点(找不到返回0),设找到的节点为M
  2. 节点M左为空: (1)节点M为根节点:直接将右节点设为根节点(有没有右节点都无所谓) (2)M不为根节点: A.M为左节点:M根节点连接M右节点,删M
http://www.jsqmd.com/news/826979/

相关文章:

  • 2026年4月SMC绝缘材料公司推荐,BMC绝缘材料/模压绝缘子/绝缘子/SMC绝缘材料,SMC绝缘材料厂商推荐分析 - 品牌推荐师
  • RTEMP8/16控制器模块
  • 基于小安派-Eyes-DU的PWM呼吸灯实现:从环境搭建到代码烧录全解析
  • MemOS:以内存为中心的操作系统如何重塑高性能计算与AI推理
  • AI智能体协作命令行工具squads-cli:多智能体编排与自动化实战
  • Arm CoreSight调试架构与多核追踪技术解析
  • 基于BLE与CircuitPython的远程服务器重启开关设计与实现
  • 从零构建高可用K8s集群:生产级架构设计与全链路实践
  • Excel控制机械臂:用办公软件实现低成本物理自动化
  • OpenLiberty深度解析:从Jakarta EE到云原生微服务的平滑演进
  • 西门子医疗与养和医疗集团合作在香港建立光子计数CT模拟定位技术卓越示范中心 | 美通社头条
  • 收藏这篇就够了!10 年机房运维转网安全,从月薪 5K 到年薪 80W 真实逆袭血泪史
  • CRC32工具:逆向计算、撤销与哈希校验的终极指南
  • 2026年酒店餐饮管理系统排名,多功能诚信之选 - 工业品牌热点
  • 开源项目质量门禁实践:从代码规范到安全扫描的自动化检查
  • Clawstash:模块化数据抓取与存储工具箱的设计与实践
  • 3步完成网易云音乐NCM格式转换:本地免费解锁完整教程
  • 2026厂区光伏全额投资运营企业发展趋势与实践案例 - 品牌排行榜
  • Laravel开发容器实战:一键搭建标准化PHP开发环境
  • GitHub Actions自动化代码审查:智能PR评论机器人实战指南
  • React Native开发环境自动化配置:Hermes引擎与技能库实践
  • Godot 4多边形动态切割与碎裂效果实现指南
  • 2026年5月北京十大装修公司排行榜推荐:专业评测夜间施工防尘降噪方案 - 品牌推荐
  • 从零构建卡牌构筑游戏引擎:数据驱动与组件化设计实战
  • 构建统一AI服务网关:OpenAI兼容门面模式实践指南
  • 【附C语言源码】C语言 栈结构 实现及其扩展操作
  • 2026工厂屋顶光伏全额投资公司项目合作与发展分析 - 品牌排行榜
  • 开源剪贴板管理器Clawstash:构建开发者本地化知识库
  • Arm Neoverse CMN-650一致性网格网络架构与优化
  • AI开发工具精选集:多语言导航与实战选型指南