news 2026/9/9 13:04:32

二叉搜索树裁剪的非递归实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二叉搜索树裁剪的非递归实现

根结点值小于L 根结点和左子树中节点关键码值均小于L 在区间之外 应该全部丢弃 右子树中可能有节点值在区间外 也可能有节点值在区间内 所以对右子树递归裁剪 由于左子树和根结点均被丢弃 所以直接返回右子树裁剪结果的根结点
根结点大于R情形类似
如果根结点在区间内 则不应丢弃 但此时左右子树均可能有节点在区间外,所以对左右子树递归裁剪 裁剪结果链接回根结点
如果二叉搜索树为空 裁剪结果仍为空树 直接返回空指针
更新:2019.6.19
刚才看了一下,递归代码存在一个问题,假若向下搜索过程中找到了一棵根节点无需修剪,但根节点子树可能需要修剪的BST,那么递归函数会在左右子树中递归搜索根节点无需修剪的子树,在搜索过程中遇到的根节点和左子树或右子树需要全部修剪的子树对应递归调用的一层,调用栈中会为该层的函数调用信息开辟栈空间,而这是没有必要的,因为遇到的子树根节点和根节点的左子树(右子树)应全部抛弃,只需修剪根节点的右子树(左子树),因此在这一层为根节点和根节点的左子树(右子树)应该被抛弃的子树保留栈空间是没有必要,造成了空间的浪费,实际上我们只需将搜索过程中遇到的根节点不应被修剪的BST子树的根节点压栈即可,而且整个过程完全可以用非递归的方式实现
自己编写的经过优化后的非递归代码如下

#include<iostream>#include<stack>#include<vector>usingnamespacestd;structBSTNode//二叉搜索树节点定义{intdata;//数据域BSTNode*left_child=nullptr;BSTNode*right_child=nullptr;BSTNode(intd):data(d){}BSTNode(constBSTNode&be_copy):data(be_copy.data),left_child(nullptr),right_child(nullptr){}};BSTNode*trimBST(BSTNode*root,intleft,intright)//修剪二叉搜索树,只保留区间[left, right]内的节点{enumProcessRate{START,LEFT_SUB_TREE,RIGHT_SUB_TREE};//处理状态,尚未修剪任何子树,已修剪过左子树,两棵子树均已修剪structStackNode{BSTNode*ptr_to_node_every_layer;//需修剪的BST根节点指针ProcessRate rate=ProcessRate::START;//修剪状态BSTNode*ptr_to_root_beconstructed;//修剪后形成的新的BST根节点指针StackNode(BSTNode*p):ptr_to_node_every_layer(p){ptr_to_root_beconstructed=newBSTNode(*ptr_to_node_every_layer);}};stack<StackNode>work_stack;BSTNode*cur=root;while(cur!=nullptr){if(right<cur->data){cur=cur->left_child;}elseif(cur->data<left){cur=cur->right_child;}else{work_stack.push(StackNode(cur));break;}}if(cur==nullptr){returnnullptr;}while(true){if(work_stack.top().rate!=ProcessRate::RIGHT_SUB_TREE){if(work_stack.top().rate==ProcessRate::START)//左子树尚未修剪,修剪左子树{cur=work_stack.top().ptr_to_node_every_layer->left_child;}elseif(work_stack.top().rate==ProcessRate::LEFT_SUB_TREE)//右子树尚未修剪,修剪右子树{cur=work_stack.top().ptr_to_node_every_layer->right_child;}while(cur!=nullptr)//向下搜索,抛弃修剪掉的部分{if(right<cur->data){cur=cur->left_child;}elseif(cur->data<left){cur=cur->right_child;}else{work_stack.push(StackNode(cur));//找到根节点无需修剪,但子树需修剪的BST子树break;}}if(cur==nullptr)//被修剪的子树为空或子树中所有节点值都在[L,R]外{if(work_stack.top().rate==ProcessRate::START){work_stack.top().rate=ProcessRate::LEFT_SUB_TREE;}else{work_stack.top().rate=ProcessRate::RIGHT_SUB_TREE;}}}else//当前BST左右子树均修剪完毕{StackNode temp=work_stack.top();work_stack.pop();if(work_stack.empty()==false)//栈不为空,将已经修剪完毕的当前BST链接至上一层需修剪的BST的子女指针域,并更新上一层修剪状态{if(work_stack.top().rate==ProcessRate::START){work_stack.top().ptr_to_root_beconstructed->left_child=temp.ptr_to_root_beconstructed;work_stack.top().rate=ProcessRate::LEFT_SUB_TREE;}elseif(work_stack.top().rate==ProcessRate::LEFT_SUB_TREE){work_stack.top().ptr_to_root_beconstructed->right_child=temp.ptr_to_root_beconstructed;work_stack.top().rate=ProcessRate::RIGHT_SUB_TREE;}}else{returntemp.ptr_to_root_beconstructed;//如果栈为空,说明当前已经修剪完毕的BST子树就是最终修剪结果,直接返回}}}}voidinorderTraverse(BSTNode*root)//输出中序序列{if(root!=nullptr){inorderTraverse(root->left_child);cout<<root->data<<" ";inorderTraverse(root->right_child);}}intmain(){BSTNode*root=nullptr;vector<int>input{4,89,23,46,12,3,56,78,34,45,11};//插入BST中的数据for(constint&i:input){BSTNode*temp=root;if(temp==nullptr){root=newBSTNode(i);}else{BSTNode*parent=nullptr;while(temp!=nullptr){if(temp->data==i)break;parent=temp;if(temp->data<i){temp=temp->right_child;}elseif(temp->data>i){temp=temp->left_child;}}if(temp==nullptr){if(i<parent->data){parent->left_child=newBSTNode(i);}else{parent->right_child=newBSTNode(i);}}}}BSTNode*_new=trimBST(root,5,50);cout<<"修剪后的二叉树的中序序列为:";if(_new==nullptr){cout<<"NULL";}else{inorderTraverse(_new);}cout<<endl;return0;}

仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 13:03:39

基于三菱PLC的3×4立体车库控制设计:仿真与调试全流程

每年到这个季节&#xff0c;总有不少学弟学妹来问我毕业设计选什么课题好。电气自动化、机电一体化方向绕不开一个经典题目——立体车库控制。我手头这个“基于三菱PLC的34立体车库控制设计”项目&#xff0c;就是标准的三菱PLC MCGS画面仿真组合&#xff0c;带视频操作演示和…

作者头像 李华
网站建设 2026/9/9 13:03:11

MATLAB车道线检测GUI实战:图像处理与Hough变换调参指南

简介&#xff1a;基于MATLAB的车道线检测完整示例项目&#xff0c;面向自动驾驶、智能交通领域初学者及计算机视觉学习者&#xff0c;覆盖从图像预处理、特征提取、模型建立到跟踪更新的主要技术路径。开发环境以MATLAB图像处理与计算机视觉工具箱为基础&#xff0c;通过灰度化…

作者头像 李华
网站建设 2026/9/9 13:02:37

STM32 HAL库入门:从压缩包解压到工程搭建与实战排查

简介&#xff1a;STM32F1xx_HAL_Driver.rar 是一套面向 STM32F1XX 系列微控制器的 HAL 库驱动合集&#xff0c;基于意法半导体官方 HAL 框架整理&#xff0c;专为 Keil MDK 5 环境设计&#xff0c;帮助开发者在无需启动 STM32CubeMX 的情况下完成 HAL 层工程搭建。压缩包共 137…

作者头像 李华
网站建设 2026/9/9 13:02:24

EA高胜率背后的真相:从策略原理到风控架构的量化交易指南

简介&#xff1a;面向MT4平台交易者的自动化交易EA资源包&#xff0c;聚焦“阿拉丁”EA策略&#xff0c;适合对算法交易、MQL4编程和外汇自动执行感兴趣的初中级用户&#xff0c;可用于学习高胜率EA的策略设计思路与参数框架。压缩包共11个文件&#xff0c;约289KB&#xff0c;…

作者头像 李华
网站建设 2026/9/9 13:02:17

vivo互传只有云传输?六大原因排查与极速传输完整指南

“为什么我只能用云传输”这个问题&#xff0c;我被问了不下二十遍。其实 vovo 互传的正确打开方式&#xff0c;绝大多数人第一 步就走错了。身边用 vivo 手机的朋友不少&#xff0c;每次给他们发大文件&#xff0c;点开互传却发现界面里只有“云传输”一个选项&#xff0c;明明…

作者头像 李华