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

算法实战:亲自写红黑树之五 删除erase的平衡

        本文承接自:

        算法实战:亲自写红黑树之一-CSDN博客

        算法实战:亲自写红黑树之二 完整代码-CSDN博客

        算法实战:亲自写红黑树之三 算法详解-CSDN博客

        算法实战:亲自写红黑树之四 插入insert的平衡-CSDN博客

目录

一、入口

二、删除

三、转换中间节点(左右子树都存在)

四、简单情形

五、复杂情形


一、入口

        有几个不同参数的删除入口:

	bool erase(const_iterator it){T_COMP comp;return erase(it, comp);}//删除并指向下一个iterator& DeleteAndMoveNext(iterator& it){if (end() == it)return it;iterator& ret = it;iterator tmp = ret;++ret;erase(tmp);return ret;}bool erase(const_iterator it, T_COMP& comp){if (it.handle < 0)return true;//DEBUG_LOG<<"要删除节点"<<show(it.handle)<<endi;bool ret = _erase(it.handle);return ret;}bool erase(T_DATA const& data){T_COMP comp;return erase(data, comp);}bool erase(T_DATA const& data, T_COMP& comp){const_iterator it = find(data, comp);if (it.handle < 0)return true;return erase(it, comp);}

        最终都进入_erase(h),直接删除一个节点。

        在到达这一步之前要先找到要删除的节点,这个属于二叉树的标准算法,很简单。

二、删除

        删除的控制代码:

	//删除bool _erase(T_SHM_SIZE position){string  report;//DEBUG_LOG<<"开始删除...."<<Report(report) <<endi;bool vLeft;//删除的节点是左子节点bool vRed;//删除的节点是红色T_SHM_SIZE p = TREE_NODE::at(position).hParent;//父节点T_SHM_SIZE u;//替换节点bool uRed;//替换节点是红色(-1为黑色)if (TREE_NODE::at(position).hLeft != -1 && TREE_NODE::at(position).hRight != -1){debug_log << "左右都存在,替换为左子树最大值" << endi;if (!__erase_change_middle(position, vLeft, vRed, u, uRed, p))return false;debug();return _erase(position);}else if (-1 == TREE_NODE::at(position).hLeft && -1 == TREE_NODE::at(position).hRight){vLeft = TREE_NODE::at(position).isLeft();vRed = TREE_NODE::at(position).bColorRed;u = -1;uRed = false;if (-1 == p){debug_log << "最后一个节点" << endi;tree_head->hHead = -1;vRed = true;//阻止后面继续处理,删除红色无需额外处理}else{debug_log << "叶子节点" << endi;if (TREE_NODE::at(position).isLeft())TREE_NODE::at(p).hLeft = -1;else TREE_NODE::at(p).hRight = -1;}}else{vLeft = TREE_NODE::at(position).isLeft();vRed = TREE_NODE::at(position).bColorRed;if (-1 != TREE_NODE::at(position).hLeft){debug_log << "左子树存在" << endi;u = TREE_NODE::at(position).hLeft;}else{debug_log << "右子树存在" << endi;u = TREE_NODE::at(position).hRight;}if (-1 == p){debug_log << "根节点" << endi;tree_head->hHead = u;}else{if (vLeft)TREE_NODE::at(p).hLeft = u;else TREE_NODE::at(p).hRight = u;}TREE_NODE::at(u).hParent = p;uRed = TREE_NODE::at(u).bColorRed;p = TREE_NODE::at(u).hParent;}bool ret = true;if (vRed){debug_log << "删除红色节点,不用调整" << endi;}else if (!vRed && uRed){debug_log << "删除黑色节点,替换节点红色改为黑色" << endi;TREE_NODE::at(u).bColorRed = false;}else{debug_log << "删除双黑节点================================================" << endi;ret = _RB_erase_Balance(p, u);}debug();if (ret)__erase_node(position);if (-1 != tree_head->hHead)TREE_NODE::at(tree_head->hHead).bColorRed = false;return ret;}

        这个函数的逻辑分为两部分:

  1. 分析要删除的节点的分支情况,将左右节点都存在的情形改为删除叶子数据节点(不是红黑树意义的叶子节点,指一般意义的叶子节点),然后确定删除节点和替换节点。
  2. 根据删除节点和替换节点的颜色进行处理,黑节点减少则需要平衡。

三、转换中间节点(左右子树都存在)

        很容易把中间节点替换掉,跟左子树最大值或者右子树最小值交换即可。

        本代码用__erase_change_middle(h)函数做这件事,将颜色也做了交换(逻辑上相当于不改变结构数据,只交换用户数据,但是我们的用户数据一般都很大,所以反过来操作,改变了除用户数据以外的所有结构数据),执行完毕后红黑树结构仍然正确,删除节点变成了最多只有一个子树的节点。

	//删除中间节点,将中间节点替换为左子树最大值(数据不动,改变树结构)bool __erase_change_middle(T_SHM_SIZE const position, bool& vLeft, bool& vRed, T_SHM_SIZE& u, bool& uRed, T_SHM_SIZE& p){string tmp;T_SHM_SIZE new_position = TREE_NODE::at(position).hLeft;if (-1 != new_position){while (-1 != TREE_NODE::at(new_position).hRight){new_position = TREE_NODE::at(new_position).hRight;}}debug_log << "position " << position << " new_position " << new_position << endi;debug_log << "position " << position << TREE_NODE::at(position).toString(tmp) << endi;debug_log << "new_position " << new_position << TREE_NODE::at(new_position).toString(tmp) << endi;vLeft = false;vRed = TREE_NODE::at(new_position).bColorRed;p = TREE_NODE::at(new_position).hParent;debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;if (p != position){debug_log << "非直接对调 p " << TREE_NODE::at(p).toString(tmp) << ende;TREE_NODE t;t._CopyWithoutData(TREE_NODE::at(new_position));TREE_NODE::at(new_position)._CopyWithoutData(TREE_NODE::at(position));TREE_NODE::at(position)._CopyWithoutData(t);debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;//注意,这里无法用isLeft来判断,因为父节点的hLeft和hRight是旧数据if (TREE_NODE::at(new_position).hParent != -1){if (TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft == position)TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft = new_position;else TREE_NODE::at(TREE_NODE::at(new_position).hParent).hRight = new_position;}if (TREE_NODE::at(position).hParent != -1){if (TREE_NODE::at(TREE_NODE::at(position).hParent).hLeft==new_position)TREE_NODE::at(TREE_NODE::at(position).hParent).hLeft = position;else TREE_NODE::at(TREE_NODE::at(position).hParent).hRight = position;}if (TREE_NODE::at(new_position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(new_position).hLeft).hParent = new_position;if (TREE_NODE::at(position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(position).hLeft).hParent = position;if (TREE_NODE::at(new_position).hRight != -1)TREE_NODE::at(TREE_NODE::at(new_position).hRight).hParent = new_position;if (TREE_NODE::at(position).hRight != -1)TREE_NODE::at(TREE_NODE::at(position).hRight).hParent = position;}else{debug_log << "直接对调 p " << TREE_NODE::at(p).toString(tmp) << endi;TREE_NODE t;t._CopyWithoutData(TREE_NODE::at(new_position));TREE_NODE::at(new_position)._CopyWithoutData(TREE_NODE::at(position));TREE_NODE::at(position)._CopyWithoutData(t);debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;//注意,这里无法用isLeft来判断,因为父节点的hLeft和hRight是旧数据if (TREE_NODE::at(new_position).hParent != -1){if (TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft == position)TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft = new_position;else TREE_NODE::at(TREE_NODE::at(new_position).hParent).hRight = new_position;}TREE_NODE::at(position).hParent = new_position;TREE_NODE::at(new_position).hLeft=position;if (TREE_NODE::at(position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(position).hLeft).hParent = position;if (TREE_NODE::at(new_position).hRight != -1)TREE_NODE::at(TREE_NODE::at(new_position).hRight).hParent = new_position;if (TREE_NODE::at(position).hRight != -1)TREE_NODE::at(TREE_NODE::at(position).hRight).hParent = position;}//如果是根节点if (-1 == TREE_NODE::at(new_position).hParent){TREE_NODE::at(new_position).bColorRed = false;tree_head->hHead = new_position;}debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;debug();return true;}

        这个代码不复杂,就是累。

四、简单情形

        现在要删除的节点要么没有子树,要么只有一个子树(说起来是子树,其实最多就是一个红节点,否则必定违反红黑树规则),只需要把子树接上去就可以了,然后把要删除的节点扔掉。

        这里我们还是用一般二叉树的概念来理解,以下说的节点都是数据节点,不包括空节点。

  1.         如果删除节点是红节点,不管下面有没有子树,不用平衡,因为不影响规则。
  2.         如果删除节点是黑节点而下面有一个红节点(前面已经说了,没有更多可能性),把这个红节点变成黑节点就行了。
  3.         如果删除节点是黑节点而下面没有可供变色的红节点(也就是没有子节点,红黑树规则不允许下面有黑色数据节点,因为只有一个子树,另外一边深度是0),这就导致红黑树规则被破坏,很多文章称这种情况为“双黑”,其实就是黑节点少了。

        第三种情形就被称为“复杂情形”,需要调用_RB_erase_Balance()来平衡。

五、复杂情形

        前面已经说了,所谓复杂情形就是少了一个黑节点,现在涉及到这么几个节点:

        u 替换节点,也就是出问题的节点,这个节点的高度比兄弟少一。这个节点可能是是空节点。

        p 替换节点的父节点

        s 替换节点的兄弟节点

        由于红黑树的规则限制,最初进入这种情形只可能是被删除节点下没有子节点,所以一定是p的一边为空另一边黑高为1。递归之后黑高少一的节点就有了各种可能,可能是红色或黑色,可能有或没有子节点。

        重新平衡有三种策略:

  1. 如果能把p改成黑同时让s黑高减一,这样就恢复平衡了,这要求p为红,p为红则s必为黑,如果s的子节点均为黑(此时s的子节点必定都是空节点,否则违反红黑树规则),只需要将p和s颜色交换就可以了。
  2. 另一边如果有红色节点,能挪过来改成黑色,平衡就完成了。按照红色节点的位置不同,需要有不同的挪法,虽然繁琐但并不困难。
  3. 另一边如果有红色节点,挪过来也不能平衡,想办法把问题往上移,递归处理。
psss处理
1黑黑/不存在p、s交换颜色,问题上移,递归
2红红挪一个红改成黑
3黑黑-[红红红红]旋转p,p、s交换颜色,p还是少1,但是变色了,重新处理p,递归
4红红挪一个红改成黑
5黑黑/不存在p、s交换颜色

        上表是所有情形,“不存在”指的是空节点,也是黑色。ss指的是s的子节点。“红红”也可能是只有一个红,因为处理时只要有一个红就不用管另一个。第三种情形的ss是双黑,后面还可能有红色子节点,不过与算法无关。

        为什么只有五种组合而不是八种?因为不允许连续红,另外三种不可能存在。

        上面第二种和第四种处理方式相同,因为并不关心p的颜色,通过挪一个改成黑,下面就平衡了。

        代码的实际处理逻辑是从ss开始判断的,先分成ss至少有一个红和没有红,然后没有红的分三种,有红的分四种(所谓四种不过是四种结构的挪法而已)。

        代码如下:

	//删除时做平衡,u可能是空节点bool _RB_erase_Balance(T_SHM_SIZE p, T_SHM_SIZE u){if (-1 == p){debug_log << "已经到顶,结束" << endi;return true;}string tmp;debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;if (u != -1)debug_log << "u " << TREE_NODE::at(u).toString(tmp) << endi;else debug_log << "u -1" << endi;bool isL = (u == TREE_NODE::at(p).hRight);//兄弟节点是否是左节点T_SHM_SIZE s = (isL ? TREE_NODE::at(p).hLeft : TREE_NODE::at(p).hRight);T_SHM_SIZE r = -1;//s的红色子节点bool is_rL;//s的红色子节点是否是左节点debug_log << "平衡:p " << p << " u " << u << " s " << s << " TREE_NODE::at(s).hRight " << TREE_NODE::at(s).hRight << endi;if (TREE_NODE::at(s).hRight != -1 && TREE_NODE::at(TREE_NODE::at(s).hRight).bColorRed){r = TREE_NODE::at(s).hRight;is_rL = false;}else if (TREE_NODE::at(s).hLeft != -1 && TREE_NODE::at(TREE_NODE::at(s).hLeft).bColorRed){r = TREE_NODE::at(s).hLeft;is_rL = true;}else{r = -1;is_rL = false;//无意义}debug_log << "p " << p << " u " << u << " s " << s << " r(-1表示双黑) " << r << endi;debug();if (-1 == r){debug_log << "s子节点均为黑" << endi;if (TREE_NODE::at(p).bColorRed){debug_log << "p为红,s必为黑 s改为红p改为黑 结束" << endi;//s子节点均为黑,p改为黑,所以s改为红是安全的,不会造成双红TREE_NODE::at(s).bColorRed = true;TREE_NODE::at(p).bColorRed = false;debug();}else{debug_log << "p为黑" << endi;if (!TREE_NODE::at(s).bColorRed){debug_log << "s为黑 s改为红平衡下层并向上递归" << endi;//p的左右分支均少1,所以p成为新的双黑节点//置s为红,p为新的u,递归TREE_NODE::at(s).bColorRed = true;debug();return _RB_erase_Balance(TREE_NODE::at(p).hParent, p);}else{debug_log << "s为红 " << TREE_NODE::at(s).toString(tmp) << endi;debug_log << TREE_NODE::at(TREE_NODE::at(s).hParent).toString(tmp) << endi;if (TREE_NODE::at(s).isLeft()){debug_log << "s为左 " << s << endi;//右旋p_RRotate(p);}else{debug_log << "s为右" << endi;_LRotate(p);}//p和s变色TREE_NODE::at(s).bColorRed = false;TREE_NODE::at(p).bColorRed = true;debug();//此时深度情况不变,但p变成了红,重新对p和u做平衡处理return _RB_erase_Balance(p, u);}}}else{if (isL && is_rL){debug_log << "LL" << ende;TREE_NODE::at(r).bColorRed = TREE_NODE::at(s).bColorRed;TREE_NODE::at(s).bColorRed = TREE_NODE::at(p).bColorRed;_RRotate(p);TREE_NODE::at(p).bColorRed = false;}else if (isL && !is_rL){debug_log << "LR" << endi;debug();TREE_NODE::at(r).bColorRed = TREE_NODE::at(p).bColorRed;debug();_LRotate(s);debug();_RRotate(p);debug();TREE_NODE::at(p).bColorRed = false;debug();}else if (!isL && is_rL){debug_log << "RL------------------------" << endi;debug();TREE_NODE::at(r).bColorRed = TREE_NODE::at(p).bColorRed;debug();_RRotate(s);debug();string tmp;debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;debug_log << "s " << TREE_NODE::at(p).toString(tmp) << endi;_LRotate(p);debug();TREE_NODE::at(p).bColorRed = false;debug();}else if (!isL && !is_rL){debug_log << "RR" << endi;TREE_NODE::at(r).bColorRed = TREE_NODE::at(s).bColorRed;TREE_NODE::at(s).bColorRed = TREE_NODE::at(p).bColorRed;_LRotate(p);TREE_NODE::at(p).bColorRed = false;}else{thelog << "非预期的状态" << ende;return false;}}return true;}

        我感觉吧,我应该刚好解决了一部分人的困惑。

(这里是结束,而且是整个系列的结束)

相关文章:

算法实战:亲自写红黑树之五 删除erase的平衡

本文承接自&#xff1a; 算法实战&#xff1a;亲自写红黑树之一-CSDN博客 算法实战&#xff1a;亲自写红黑树之二 完整代码-CSDN博客 算法实战&#xff1a;亲自写红黑树之三 算法详解-CSDN博客 算法实战&#xff1a;亲自写红黑树之四 插入insert的平衡-CSDN博客 目录 一、入口…...

春秋云境靶场CVE-2021-41402漏洞复现(任意代码执行漏洞)

文章目录 前言一、CVE-2021-41402描述二、CVE-2021-41402漏洞复现1、信息收集1、方法一弱口令bp爆破2、方法二7kb扫路径&#xff0c;后弱口令爆破 2、找可能可以进行任意php代码执行的地方3、漏洞利用找flag 总结 前言 此文章只用于学习和反思巩固渗透测试知识&#xff0c;禁止…...

12 Go的接口

概述 在上一节的内容中&#xff0c;我们介绍了Go的作用域&#xff0c;包括&#xff1a;局部作用域、全局作用域、命名空间作用域等。在本节中&#xff0c;我们将介绍Go的接口。Go语言中的接口是一种类型&#xff0c;它定义了一组函数的集合。接口是一种抽象的描述&#xff0c;它…...

Python编程-----并行处理应用程序

目录 一.进程 二.线程 三.Python标准库中并行处理的相关模块 Threading模块 &#xff08;1&#xff09;使用Thread对象创建线程 &#xff08;2&#xff09;自定义派生于Thread的对象 &#xff08;3&#xff09;线程加入join() (4)用户线程和daemon线程 (5)Timer线程 线…...

kubernetes集群编排——istio

官网&#xff1a;https://istio.io/latest/zh/about/service-mesh/ 部署 [rootk8s2 ~]# tar zxf istio-1.19.3-linux-amd64.tar.gz [rootk8s2 ~]# cd istio-1.19.3/[rootk8s2 istio-1.19.3]# export PATH$PWD/bin:$PATH demo专为测试准备的功能集合 [rootk8s2 istio-1.19.3]# i…...

mfc140u.dll丢失的解决方法,以及mfc140u.dll解决方法的优缺点

在使用电脑过程中&#xff0c;有时会遇到一些与动态链接库文件&#xff08;DLL&#xff09;相关的错误。其中&#xff0c;mfc140u.dll丢失的错误是较为常见的一种。当这个关键的mfc140u.dll文件丢失或损坏时&#xff0c;可能会导致某些应用程序无法正常运行。在本文中&#xff…...

2源码安装网络协议

2.2源码安装/网络协议 一、源码包应用场景 有时我们所用的内核版本太旧&#xff0c;系统自带的库&#xff08;如libstdc.so.6&#xff09;版本低或者依赖的其他软件版 本较低&#xff0c;导致无法安装目标软件。 软件/库其实是对机器汇编指令集的封装&#xff0c;在X86体系下…...

未来服务器操作系统的趋势与展望

摘要&#xff1a; 随着云计算、大数据和人工智能不断的发展&#xff0c;服务器操作系统也需要随之进行新一轮的升级。本文通过分析当前服务器操作系统的现状&#xff0c;探讨了未来服务器操作系统的趋势和展望&#xff0c;并针对一些关键问题提出了解决方案。 一、引言 服务器…...

VB.net WebBrowser网页元素抓取分析方法

在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

自建ES6.2.4切阿里云商业版ES(7.10)整体方案

一、切换目的&阿里云商业版ES版本选择 1.1 升级切换阿里云商业版7.10目的 自建的Elasticsearch服务运维难度高,操作复杂,需要手动调整资源,遇到性能瓶颈时优化难度相对云上Elasticsearch较大。使用阿里云提供的ES服务,提高系统稳定性使用云服务es,易于备份,数据恢复…...

Vue实现封装自定义指令

目录 一、什么是自定义指令&#xff1f; 二、自定义指令的使用 Vue中的自定义指令使用Vue.directive函数进行定义。该函数接受两个参数&#xff0c;第一个是指令名称&#xff0c;第二个是指令选项对象。 上述代码中&#xff0c;我们定义了一个名为my-directive的自定义指令…...

<MySQL> 查询数据进阶操作 -- 聚合查询

目录 一、聚合查询概述 二、聚合函数查询 2.1 常用函数 2.2 使用函数演示 2.3 聚合函数参数为*或列名的查询区别 2.4 字符串不能参与数学运算 2.5 具有误导性的结果集 三、分组查询 group by 四、分组后条件表达式查询 五、MySQL 中各个关键字的执行顺序 一、聚合查询…...

arm开发板

一个简单的hello world程序 minicom用来和开发板之间交互并且可以向开发板传输文件。打印hello world字符串。在linux虚拟机上编译我的代码&#xff0c;使用的交叉编译工具是arm-linux-gnueabihf-gcc (hard float) 可以使用 readelf -h libc.so.6 查看开发板是不是&#xff08…...

nodejs+vue教室管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

用户 用户管理&#xff1a;查看&#xff0c;修改自己的个人信息 教室预约&#xff1a;可以预约今天明天的教室&#xff0c;按着时间段预约&#xff08;可多选&#xff09;&#xff0c;如果当前时间超过预约时间段不能预约该时间段的教室 预约教室的时候要有个预约用途&#xff…...

rabbitMQ的Topic模式的生产者与消费者使用案例

topic模式 RoutingKey 按照英文单词点号多拼接规则填充。其中消费者匹配规则时候 * 代表一个单词&#xff0c;#表示多个单词 消费者C1的RoutingKey 规则按照*.orange.* 匹配 绑定队列Q1 package com.esint.rabbitmq.work05;import com.esint.rabbitmq.RabbitMQUtils; import …...

【软考篇】中级软件设计师 第五部分

中级软件设计师 第五部分 三十六. 下午题变动题型参考答案例题一 如何保持数据流图平衡例题二 结构化语言例题三 关系模式例题四 用例关系内涵例题五 观察者模式 三十七&#xff1a;下午题第四题往年算法部分参考答案 读前须知&#xff1a; 【软考篇】中级软件设计师 学前须知 …...

论文阅读——RetNet

transformer的问题&#xff1a;计算量大&#xff0c;占用内存大&#xff0c;不好部署。 所以大家在找能解决办法&#xff0c;既能和transformer表现一样好&#xff0c;又能在推理阶段计算复杂度很低。 这些方法大概分类三类&#xff1a;一是代替transformer非线性注意力机制的…...

【Proteus仿真】【51单片机】锂电池管理系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1602显示模块、DS18B20温度传感器、PCF8691 ADC模块、按键、LED蜂鸣器模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示温度…...

【工具使用-VScode】设置 VSCode 的自动保存功能

要设置 VSCode 的自动保存功能&#xff0c;请按照以下步骤进行操作&#xff1a; 打开 VSCode 编辑器。在顶部菜单中选择 “文件&#xff08;File&#xff09;”。选择 “首选项&#xff08;Preferences&#xff09;”。在下拉菜单中选择 “设置&#xff08;Settings&#xff0…...

常用Git命令记录

持续补充… git add&#xff1a;提交到暂存区git remote add <remote_name> <remote_url> : 添加一个新的远程仓库。指定一个远程仓库的名称和 URL&#xff0c;将其添加到当前仓库中。git commit&#xff1a;暂存区提交到本地仓库&#xff1b;-m&#xff1a;添加日…...

Go语言常用库

Go语言常用库 文本主要介绍Go常用的一些系统库&#xff1a; sort、math、copy、strconv、crypto 1、sort package mainimport ("fmt""sort" )// sort // int排序 // sort.Ints([]int{}) // 字符串排序 // sort.Strings([]string{}) // 自定义排序 // s…...

二叉树(进阶)

文章目录 1.内容安排说明2. 二叉搜索树2.1二叉搜索树的概念2.2二叉搜索树的实现2.3二叉树的性能&#xff1a; 搜索二叉树的应用k 模型kv模型 1.内容安排说明 二叉树在前面c数据结构阶段&#xff1b;已经讲过了&#xff1b;本节取名二叉树进阶的原因是&#xff1a; 1.map和set特…...

Flink之OperatorState

在Flink中状态主要分为三种: Operator State(算子状态)Keyed State(键控状态)Broadcast State(广播状态) 这里简单介绍一下Operator State的使用,说到使用State就必然要使用到Flink的容错机制也就是Checkpoint.具体内容见代码注解 数据源 这里选用Socket作为Source输入,便于…...

Python集成学习和随机森林算法

大家好&#xff0c;机器学习模型已经成为多个行业决策过程中的重要组成部分&#xff0c;然而在处理嘈杂或多样化的数据集时&#xff0c;它们往往会遇到困难&#xff0c;这就是集成学习&#xff08;Ensemble Learning&#xff09;发挥作用的地方。 本文将揭示集成学习的奥秘&am…...

代码随想录算法训练营第二十四天| 77 组合

目录 77 组合 暴力 减枝优化 77 组合 暴力 class Solution {List<List<Integer>>res new ArrayList<>();LinkedList<Integer>newList new LinkedList<>();public List<List<Integer>> combine(int n, int k) {dfs(n,k,1);r…...

el-dialog element-ui弹窗

bulkImport.vue 自定义组件 <template> <el-dialog :visible"modalVisible" title"批量导入" centered close"$emit(close)" :fullscreen"true"> <span>弹窗内容</span> <span slot"foot…...

计算机网络的发展

目录 一、计算机网络发展的四个阶段 1、第一阶段&#xff1a;面向终端的计算机网络&#xff08;20世纪50年代&#xff09; 2、第二阶段&#xff1a;计算机—计算机网络&#xff08;20世纪60年代&#xff09; 3、第三阶段&#xff1a;开放式标准化网络&#xff08;20世纪70年…...

官宣!Wayland正式支持基于IntelliJ的IDE

对于基于IntelliJ IDE的Linux用户来说&#xff0c;一项令人期待的进步即将到来 – 对 Wayland 显示服务器协议的支持。 这项更新将带来许多好处&#xff0c;包括解决古老的分数缩放问题以及在与适用于 Linux 的 Windows 子系统 (WSLg)&#xff08;在底层运行 Wayland 服务器&am…...

大模型在数据分析场景下的能力评测|进阶篇

做数据分析&#xff0c;什么大模型比较合适&#xff1f; 如何调优大模型&#xff0c;来更好地做数据计算和洞察分析&#xff1f; 如何降低整体成本&#xff0c;同时保障分析体验&#xff1f;10月25日&#xff0c;我们发布了数据分析场景下的大模型能力评测框架&#xff08;点击…...

服务注册发现 springcloud netflix eureka

文章目录 前言角色&#xff08;三个&#xff09; 工程说明基础运行环境工程目录说明启动顺序&#xff08;建议&#xff09;&#xff1a;运行效果注册与发现中心服务消费者&#xff1a; 代码说明服务注册中心&#xff08;Register Service&#xff09;服务提供者&#xff08;Pro…...