次优二叉查找树(次优查找树)_递归和非递归实现_20230414
次优二叉查找树(次优查找树)-递归和非递归实现
- 前言
当有序表中的各记录的查找概率相等的时候,采用折半查找效率可以提升查找性能;如果有序表中的各记录的查找概率不相等,那么折半查找就不再适用。
如果只考虑查找成功的情况,则使查找性能达到最佳性能的判定树就是带权路径长度的之和,也即路径各个记录的查找深度与查找权值的乘积之和,当这个和取得最小值的时候。
P H = Σ c i ∗ w i , i ∈ ( 1.... n ) PH=Σc_i*w_i,\ i∈(1....n) PH=Σci∗wi, i∈(1....n)
最优二叉查找树需要利用到动态规划的相关知识,之前的文章有所涵盖,有兴趣的读者可查阅之前的文章进行理解。本文所阐述的方法,采用的是贪婪的编程思维,构建出次优二叉查找树(Nearly optimal binary search tree)。
- 问题分析
已知一个按照关键有序的记录:
(rl,rl+1…rh)
其中关键字为升序排列,对于每个记录的权值
(wl,wl+1…wh)
现在构造一颗二叉树,是这颗二叉树的带权路径长度PH在同样的二叉树中近似最小,我们称这类二叉树为次优二叉树。
利用贪婪方法,构造次优查找树的方法是:首先在序列l…h构造根节点root(i),使根节点左右两颗子树的差值取最小值,那么这个点就是根节点。采用公式,让理解更为方便。
Δpi=|Σwj(i+1<j<h)-Σwj(l<j<i-1)|
求得i之后,然后分别对子序列(rl,rl+1…ri-1)和(ri+1,rr+2…rh)再分别构造两颗次优二叉树,并设定其根节点为root(i),分别定位root(i)的左子树和右子树。

根据上面的分析,引入递归算法和非递归算法构造次优二叉书。
- 递归算法分析
由于构造二叉树的过程需要分别对左右子树进行处理,所以整体的需要涉及两次递归调用。二叉树的构造过程和遍历过程非常类似,都是对左右子树访问的过程。针对本问题,我们选择先序遍历模式完成问题的解答。
由于采用递归,那么递归的结束条件是什么呢? 递归的结束条件就是遍历到叶子结点,在本问题当中,可以理解问题根节点的下标等于high或者low的时候,此时递归就满足结束条件(不再进行入栈操作)。
- 递归代码C语言实现
递归函数的操作对象为记录的权值和,在递归函数之前需要求解sw[0…n-1],我们使用void find_sw(int *sw, SSTable st)函数完成此项任务。
递归函数中包含子树下标的最小值与最大值,在先序递归之前,通过迭代求出根节点所在位置,然后与high和low进行比较,我们使用void second_optimal(BiTree *bt, SElemType *rec, int *sw, int low, int high)函数完成这项任务。
a.) find_sw函数实现,注意第1个元素的sw值为0
void find_sw(int *sw, SSTable st)
{int i;*(sw + 0) = 0;for (i = 1; i <= st.len; i++){sw[i] = sw[i - 1] + st.elem[i].value;}
}
b.) second_optimal函数实现
void second_optimal(BiTree *bt, SElemType *rec, int *sw, int low, int high)
{int min;int i;int j;int dw;int delta;min=INT_MAX;dw=sw[high]+sw[low-1];i=low;for(j=i;j<=high;j++){delta=abs(dw-(sw[j]+sw[j-1]));if(delta<min){i=j;min=delta;}}*bt=(BiTree)malloc(sizeof(BiTNode));(*bt)->data=rec[i];if(i==low){(*bt)->lchild=NULL;}else{second_optimal(&((*bt)->lchild),rec,sw,low,i-1);}if(i==high){(*bt)->rchild=NULL;}else{second_optimal(&((*bt)->rchild), rec, sw, i + 1, high);}
}
- 非递归实现
为了实现非递归建立次优二叉查找树,就需要借助栈(stack)的概念,本质是就是借助自定义栈来实现编译器中的函数栈的管理。栈实际上储存的是记忆的状态,采用“后进先出”模式来模拟编译器中的函数栈。我们在利用栈实现功能之前,首先需要定义过程中需要记忆(保存)哪些参数。很明显,对于本问题,我们至少需要保留三个变量参数的当前状态,下一个待处理二叉树结点的指针(它必定来自于当前结点的左孩子或者右孩子),子树需要处理的范围,也就是low和high的下标位置,有了这些背景分析,定义栈保存的元素:
typedef struct StackNode
{BiTree node;int low;int high;
}StackNode;
基于上述定义,非递归次优二叉树实现函数如下:
void second_optimal(BiTree *bt, SElemType *rec, int *sw, int len)
{int min;int i;int j;int delta;int dw;int low;int high;SqStack S;StackNode st_node;StackNode temp;low=1;high=len;InitStack_Sq(&S);st_node.low=low;st_node.high=high;st_node.node=(BiTree)malloc(sizeof(BiTNode));*bt = st_node.node;Push_Sq(&S,st_node);while(!StackEmpty_Sq(S)){Pop_Sq(&S,&temp);low=temp.low;high=temp.high;i=low;min=INT_MAX;dw=sw[high]+sw[low-1];for(j=i;j<=high;j++){delta=abs(dw-sw[j]-sw[j-1]);if(delta<min){i=j;min=delta;}}temp.node->data=rec[i];//it should start with from pushing the right child into the stackif(i==high){temp.node->rchild=NULL;}else{st_node.low=i+1;st_node.high=high;temp.node->rchild=(BiTree)malloc(sizeof(BiTNode));st_node.node=temp.node->rchild;// here it is st_node.node instead of st_node.node->rchildPush_Sq(&S, st_node);}if (i == low){temp.node->lchild = NULL;}else{st_node.low = low;st_node.high = i - 1;temp.node->lchild = (BiTree)malloc(sizeof(BiTNode));st_node.node= temp.node->lchild;// here it is st_node.node instead of st_node.node->lchildPush_Sq(&S, st_node);}}}
上述函数的实现涉及到栈操作,有兴趣的读者可以参考《数据结构》严蔚敏版自行实现,在此不再赘述。对于上述非递归代码,请读者自行理解。
- 总结
次优二叉查找树是一种基于贪心算法实现的二叉树,它摒弃了动态规划建立最优二叉树的繁琐流程,同时又保留了查询的效率。本文针对次优二叉树,采用递归和迭代两种不同的方式加以实现,加深了对递归的理解,同时也复习了栈(stack)的相关知识。
参考资料:
- 《数据结构》-清华大学,严蔚敏
相关文章:
次优二叉查找树(次优查找树)_递归和非递归实现_20230414
次优二叉查找树(次优查找树)-递归和非递归实现 前言 当有序表中的各记录的查找概率相等的时候,采用折半查找效率可以提升查找性能;如果有序表中的各记录的查找概率不相等,那么折半查找就不再适用。 如果只考虑查找成功的情况&a…...
贯穿设计模式第八话--设计原则总结篇
🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳 从今天开始,将…...
地理信息系统(ArcGIS)在水文水资源、水环境中的实践技术应用及案例分析
目录 专题一 ArcGIS:数据管理 专题二 ArcGIS:数据转换 专题三 ArcGIS:地图制作 专题四 水文水环境数据编辑与管理 专题五 水文水环境数据处理与分析 专题六 ArcGIS水文分析及流域特征提取 专题七 湖泊水库水环境监测及评价 专题八 河…...
部分国产水文水动力模型介绍
一、HydroMPM模型 1、模型介绍 2016年度自立项目HydroMPM系统开发与集成完成的洪水分析模拟软件等成果经权威专家鉴定整体达到国际领先水平,HydroMPM_FloodRisk入选国家防总《全国重点地区洪水风险图编制项目可选软件名录》。成果应用项目100余项,累计…...
HTTP请求
1、get请求工具类 public static String requestGet(String url) throws Exception { String strResult null; try { HttpClient httpsClient HttpsClient.getInstance(); HttpGet request new HttpGet(url); HttpResponse response http…...
网络威胁情报项目:为什么仍然很疯狂
大约五年前,向首席信息安全官( CISO)询问他们的网络威胁情报 (CTI) 计划时,得到了两种截然不同的回答。 资源丰富的大型企业正在投资他们的威胁情报计划,目的是为了战术、运营和战略目的更好地实施它。 规模较小、资…...
Linux系统下使用shell“多线程执行命令”
前言 在工作中常遇到如下场景: 系统未接入日志中心,系统本身使用集群部署,那么再查找日志的时候只能一台一台的去搜索关键字,后来运维同学发现这样一台一台效率太低了,于是有了升级版,升级之后的方式还是一…...
HighTec编译器错误记录
目录 1、HighTec安装后缺少Universal Debug Engine 2、HighTec工程改名后不能跳转函数定义,提示找不到定义。 3、HighTec工程重复编译 1、HighTec安装后缺少Universal Debug Engine 在HighTec安装后,没有调试UDE,重装系统后还是没有&#x…...
智慧校园大数据云平台(3)
技术详解 OTN技术OTN是以波分复用技术为基础、 在光层组织网络的传送网, 是下一代的骨干传送网。OTN是通过G.872、G.709、G.798等一系列ITU-T的建议所规范的新一代“数字传送体系”和“光传送体系”,将解决传统WDM网络无波长/子波长业务调度能力差、组网…...
《花雕学AI》15:BingGPT桌面端——尝鲜体验ChatGPT4.0同源技术新Bing的最新成果
引言: 本文将介绍 BingGPT桌面端的开发背景和目的,以及它与新 Bing 的关系和区别。本文还将说明BingGPT桌面端的主要功能和特点,以及如何下载、安装和使用。最后,本文将评价 BingGPT桌面端对于新 Bing 的人工智能聊天功能的推广和…...
反序列化漏洞及PHP魔法函数
目录 1、漏洞原理 2、序列化(以PHP语言为例) 3、反序列化 4、PHP魔法函数 (1)__wakeup() (2)__destruct() (3)__construct() (4)__toString() &…...
企业应用程序单点登录
企业每天都依赖于各种企业应用程序,包括云和本地应用程序。这意味着用户必须经常输入更多密码才能访问这些应用程序并完成他们的工作。为了提高用户的工作效率、减少密码疲劳并使身份管理更有效,您的组织需要部署高效的 SSO 解决方案。 AD360 提供企业 …...
前馈PID控制(热交换器/反应釜温度控制)
如何利用PID进行温度控制请参看下面博客文章: 博途PID 1200/1500PLC PID_Compact比例作用权重b微分作用权重c解读(PI-D控制器 I-PD控制器)_RXXW_Dor的博客-CSDN博客很多人会问PLC自带的PID指令和我们自己设计的PID有什么区别,这个问题要看你和什么PID控制器作对比,PID负反…...
Nginx配置ssl证书实现https安全访问
目录 一、Nginx的安装与配置 安装步骤 二、SSL证书获取 三、Nginx配置 前题条件,拥有服务器与可以解析到该服务器的自己的域名。 一、Nginx的安装与配置 若已安装好了Nginx,则需查看自己的Nginx是否开启了SSL的模块功能: ./nginx -V 显…...
大学生必备神器
大学生要掌握的办公软件因专业和工作需求而异,但是以下是一些普遍适用于大学生的办公软件,可以帮助提高学习和工作效率,今天就给大家推荐几款大学生常用的软件。 1.OneDrive 这是微软出品的云存储产品,与百度网盘有些类似&#…...
【MyBatis Plus】004 -- MyBatis Plus高级(AR、MP插件、自定义全局操作、自动填充、逻辑删除、枚举、代码生成器)
目录 1、ActiveRecord 1.1 开启AR之旅(根据主键 id 进行查询) 1.2 新增数据 1.3 更新操作 1.4 删除操作 1.5 根据条件查询 2、Oracle 主键 Sequence 2.1 部署Oracle环境 2.2 创建表以及序列 2.3 jdbc驱动包 2.4 修改application.properties 2.5 配置序列…...
3年外包终上岸,我只能说:但凡有点机会,千万别去外包...
我大学学的是计算机专业,毕业的时候,对于找工作比较迷茫,也不知道当时怎么想的,一头就扎进了一家外包公司的软件测试岗,一干就是3年。现在终于跳槽到了互联网公司了,我想说的是,但凡有点机会&am…...
【故障诊断】基于 KPCA 进行降维、故障检测和故障诊断研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
软件质量保证与软件测试复习笔记(第一周总体介绍+黑盒测试详细)
第一周 2.23 (总体性介绍) 软件测试的定义 常用术语解释 错误 缺陷 故障 失效 测试和测试用例、测试过程 出现软件缺陷的原因 软件开发的主要环节 测试过程的生命周期模型 软件测试的本质是针对要测试的内容确定一组测试用例 测试用…...
WRF模式与Python融合技术在多领域中的应用及精美绘图教程
当今从事气象及其周边相关领域的人员,常会涉及气象数值模式及其数据处理,无论是作为业务预报的手段、还是作为科研工具,掌握气象数值模式与高效前后处理语言是一件非常重要的技能。WRF作为中尺度气象数值模式的佼佼者,模式功能齐全…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
Unity VR/MR开发-VR开发与传统3D开发的差异
视频讲解链接:【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
VSCode 使用CMake 构建 Qt 5 窗口程序
首先,目录结构如下图: 运行效果: cmake -B build cmake --build build 运行: windeployqt.exe F:\testQt5\build\Debug\app.exe main.cpp #include "mainwindow.h"#include <QAppli...
