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

【C++】map和set的封装(红黑树)

map和set的封装

  • 一、介绍
  • 二、stl源码剖析
  • 三、仿函数获取数值
  • 四、红黑树的迭代器
  • 五、map的[]
    • 5.1 普通迭代器转const迭代器
  • 六、set源码
  • 七、map源码
  • 八、红黑树源码

一、介绍

首先要知道map和set的底层都是用红黑树实现的
【数据结构】红黑树
set只需要一个key,但是map既有key也有val。
那么我们怎么同时兼容呢?

二、stl源码剖析

在这里插入图片描述

从这张图可以看出红黑树的节点里面存的类型是由Value决定的,跟Key无关。

所以我们实现的时候就可以给RBTree添加一个模板参数

template<class K, class T>
class RBTree

T模板参数我们既可以传K也可以传pair<k, V>
map

template <class K>
class set
{
private:RBTree<K,K> _t;
};

set

template <class K, class V>
class map
{
private:RBTree<K, pair<const K,V>> _t;
};

既然通过第二个参数就能确定节点的类型,那么第一个参数有什么用呢?

当我们查找的时候,如果是map,第二个参数就是pair类型,不能使用,所以得加上第一个参数,方便查找。

参照stl的方法定义节点:

template <class T>
struct RBTreeNode
{RBTreeNode(const T& data): _data(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){}T _data;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;
};

三、仿函数获取数值

我们知道红黑树是搜索树,插入的时候需要比较大小,而我们插入的有可能是K,也有可能是pair<K, V>,导致我们无法直接比较。

而stl的做法就是利用仿函数获取我们需要进行比较的元素。
在这里插入图片描述
set

template <class K>
class set
{struct SetKeyOfT{const K& operator()(const K& k){return k;}};
public:
private:RBTree<K, K, SetKeyOfT> _t;
};

map

template <class K, class V>
class map
{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
public:
private:RBTree<K, pair<K, V, >, MapKeyOfT> _t;
};

在这里插入图片描述
进行大小比较

KeyOfT kot;// 仿函数比较
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_left;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_right;}else return false;
}

四、红黑树的迭代器

template <class T, class Ref, class Ptr>
struct RBTIterator
{typedef RBTreeNode<T> Node;typedef RBTIterator<T, Ref, Ptr> self;RBTIterator(Node* node): _node(node){}Node* _node;
};

*:解引用操作,返回对应结点数据的引用:

Ref operator*()
{return _node->_data;
}

->:访问成员操作符,返回节点数据的地址

Ptr operator->()
{return &_node->_data;
}

!=、== 比较迭代器是否指向同一节点

bool operator!=(const self& it)
{return _node != it._node;
}bool operator==(const self& it)
{return _node == it._node;
}

begin()end()
begin():返回的是最左节点(中序遍历的第一个节点)
end():迭代器的end()一般是返回最后一个节点的下一个位置,这里设置为nullptr。

typedef RBTIterator<T, T&, T*> iterator;
typedef RBTIterator<T, const T&, const T*> const_iterator;
iterator begin()
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);
}iterator end()
{return iterator(nullptr);
}

map里面的begin()end()

typedef typename RBTree<K, pair<const K, V>, MapKeyOfT >::iterator iterator;
iterator begin()
{return _t.begin();
}iterator end()
{return _t.end();
}

这里注意因为编译的时候编译器不知道RBTree<K, pair<const K, V>, MapKeyOfT >::iterator这是个类型还是静态成员变量,会编译出错,加上typename就是告诉编译器这里是一个类型

set的begin()end()

typedef typename RBTree<K, K, SetKeyOfT >::iterator iterator;
iterator begin()
{return _t.begin();
}iterator end()
{return _t.end();
}

这里重要的是迭代器的++--
++
寻找中序遍历的下一个节点:
1️⃣ 如果右子树不为空++就是找右子树的最左节点。
1️⃣ 如果右子树为空++就是找祖先(孩子是父亲的左的那个祖先)

self& operator++()
{if (_node->_right){Node* min = _node->_right;while (min->_left){min = min->_left;}_node = min;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_right == cur){cur = parent;parent = parent->_parent;}_node = parent;}return *this;
}

--
++刚好是反过来:
1️⃣ 如果左子树不为空++就是找左子树的最右节点。
1️⃣ 如果左子树为空++就是找祖先(孩子是父亲的右的那个祖先)

self& operator--()
{if (_node->_left){Node* max = _node->_left;while (max && max->_right){max = max->_right;}_node = max;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_left == cur){cur = parent;parent = parent->_parent;}_node = parent;}return *this;
}

这里还有一个重要的问题:
如果这么写那么set的值也可以被修改。那么如何保证set不能被修改呢?

在这里插入图片描述
可以直接把普通迭代器和const迭代器都变成const_iterator。

此时这里会出现问题:

iterator begin()
{return _t.begin();
}iterator end()
{return _t.end();
}

这里_t是普通对象,会调用普通的迭代器,类型不同,无法返回。
在这里插入图片描述

我们只需要在函数后面加上const就可以权限缩小,变成const对象。

iterator begin() const
{return _t.begin();
}iterator end() const
{return _t.end();
}

在红黑树中也要加入对应的const版本begin()end()

const_iterator begin() const
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return const_iterator(cur);
}const_iterator end() const
{return const_iterator(nullptr);
}

五、map的[]

当我们想使用map来统计次数的时候,就需要重载[]
如果想要支持[],那么insert的返回值就得设置成pair<iterator, bool>
如果在bool就是false,iterator返回当前节点。

return make_pair(iterator(cur), false);

不在就插入。

return make_pair(iterator(newnode), true);

map

V& operator[](const K& key)
{pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;
}

这里要注意set:

pair<iterator, bool> insert(const K& k)
{return _t.insert(k);
}

这里的iterator其实是const_iterator,所以导致类型不同。

5.1 普通迭代器转const迭代器

正常情况下普通迭代器不能转化为const迭代器。
为了解决这种情况,我们在迭代器内添加一个拷贝构造即可。
在这里插入图片描述

1️⃣ 当传进来的是普通迭代器的时候,iterator是普通迭代器,这个函数相当于拷贝构造
2️⃣ 当传进来的是const迭代器的时候,iterator依然是普通迭代器,此时该函数就相当于构造函数(普通迭代构造const迭代器)。

其实普通迭代器和const的区别就在operator*operator->

而set的插入不需要修改:

pair<iterator, bool> insert(const K& k)
{return _t.insert(k);
}

return的时候会调用拷贝构造函数,也就是构造函数,把普通迭代器转化为const迭代器。

六、set源码

#pragma once
#include "RBTree.h"namespace yyh
{template <class K>class set{struct SetKeyOfT{const K& operator()(const K& k){return k;}};public:typedef typename RBTree<K, K, SetKeyOfT >::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT >::const_iterator const_iterator;iterator begin() const{return _t.begin();}iterator end() const{return _t.end();}pair<iterator, bool> insert(const K& k){return _t.insert(k);}private:RBTree<K, K, SetKeyOfT> _t;};
}

七、map源码

#pragma once
#include "RBTree.h"namespace yyh
{template <class K, class V>class map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfT >::iterator iterator;typedef typename RBTree<K, pair<const K, V>, MapKeyOfT >::const_iterator \const_iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}pair<iterator, bool> insert(const const pair<K, V>& kv){return _t.insert(kv);}V& operator[](const K& key){pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};
}

八、红黑树源码

#pragma once
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <string>using namespace std;enum Colour
{RED,BLACK,
};template <class T>
struct RBTreeNode
{RBTreeNode(const T& data): _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){}T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;
};template <class T, class Ref, class Ptr>
struct RBTIterator
{typedef RBTreeNode<T> Node;typedef RBTIterator<T, Ref, Ptr> self;typedef RBTIterator<T, T&, T*> iterator;RBTIterator(const iterator& s): _node(s._node){}RBTIterator(Node* node): _node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}self& operator++(){if (_node->_right){Node* min = _node->_right;while (min->_left){min = min->_left;}_node = min;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_right == cur){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}self& operator--(){if (_node->_left){Node* max = _node->_left;while (max && max->_right){max = max->_right;}_node = max;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && parent->_left == cur){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Node* _node;
};template <class K, class T, class KeyOfT>
class RBTree
{
public:typedef RBTreeNode<T> Node;typedef RBTIterator<T, T&, T*> iterator;typedef RBTIterator<T, const T&, const T*> const_iterator;iterator begin(){Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);}iterator end(){return iterator(nullptr);}const_iterator begin() const{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return const_iterator(cur);}const_iterator end() const{return const_iterator(nullptr);}pair<iterator, bool> insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(iterator(_root), true);}KeyOfT kot;// 仿函数比较Node* parent = nullptr;Node* cur = _root;while (cur){if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else return make_pair(iterator(cur), false);}cur = new Node(data);Node* newnode = cur;if (kot(data) < kot(parent->_data)){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;while (parent && parent->_col == RED){// 找g 与 uNode* g = parent->_parent;if (parent == g->_left){Node* u = g->_right;// 情况一 u存在且为红if (u && u->_col == RED){parent->_col = u->_col = BLACK;g->_col = RED;// 继续往上处理cur = g;parent = cur->_parent;}else // 情况二或情况三{if (cur == parent->_left)// 情况二{//   g//  p// cRotateR(g);parent->_col = BLACK;g->_col = RED;}else// 情况三{//  g// p//  cRotateL(parent);RotateR(g);//   c// p   gcur->_col = BLACK;g->_col = RED;}break;}}else{Node* u = g->_left;// 情况一if (u && u->_col == RED){u->_col = parent->_col = BLACK;g->_col = RED;cur = g;parent = cur->_parent;}else{// 情况二// g//  p//   cif (cur == parent->_right){RotateL(g);parent->_col = BLACK;g->_col = RED;}else// 情况三{// g//  p// cRotateR(parent);RotateL(g);cur->_col = BLACK;g->_col = RED;}break;}}}// 上面有可能把_root的颜色变为红_root->_col = BLACK;return make_pair(iterator(newnode), true);}void RotateL(Node* parent){Node* top = parent->_parent;Node* right = parent->_right;parent->_right = right->_left;if (right->_left) right->_left->_parent = parent;right->_left = parent;parent->_parent = right;if (top)// 子树{if (parent == top->_left) top->_left = right;else top->_right = right;right->_parent = top;}else// 完整的树{_root = right;_root->_parent = nullptr;}}void RotateR(Node* parent){Node* top = parent->_parent;Node* left = parent->_left;Node* leftR = left->_right;parent->_left = leftR;if (leftR) leftR->_parent = parent;left->_right = parent;parent->_parent = left;if (top){if (parent == top->_left) top->_left = left;else top->_right = left;left->_parent = top;}else{_root = left;_root->_parent = nullptr;}}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_kv.first << "<=>" << root->_kv.second << endl;_Inorder(root->_right);}void Inorder(){_Inorder(_root);}bool _IsBalance(Node* root, int i, int flag){if (root == nullptr){if (i != flag){cout << "errno: 左右子树黑色节点数目不同" << endl;return false;}return true;}// 红节点时判断父亲if (root->_col == RED){if (root->_parent->_col == RED){cout << "errno: 红-红" << endl;return false;}}if (root->_col == BLACK){i++;}return _IsBalance(root->_left, i, flag) && _IsBalance(root->_right, i, flag);}bool IsBalance(){if (_root == nullptr){return true;}if (_root->_col != BLACK){return false;}// 找标准值Node* cur = _root;int flag = 0;while (cur){if (cur->_col == BLACK){flag++;}cur = cur->_left;}int i = 0;return _IsBalance(_root, i, flag);}private:Node* _root = nullptr;
};

相关文章:

【C++】map和set的封装(红黑树)

map和set的封装一、介绍二、stl源码剖析三、仿函数获取数值四、红黑树的迭代器五、map的[]5.1 普通迭代器转const迭代器六、set源码七、map源码八、红黑树源码一、介绍 首先要知道map和set的底层都是用红黑树实现的 【数据结构】红黑树 set只需要一个key&#xff0c;但是map既…...

【批处理脚本】-1.14-移动文件(夹)命令move

"><--点击返回「批处理BAT从入门到精通」总目录--> 共10页精讲(列举了所有move的用法,图文并茂,通俗易懂) 在从事“嵌入式软件开发”和“Autosar工具开发软件”过程中,经常会在其集成开发环境IDE(CodeWarrior,S32K DS,Davinci,EB Tresos,ETAS…)中,…...

逻辑地址和物理地址转换

在操作系统的学习中&#xff0c;很多抵挡都会涉及虚拟地址转换为物理地址的计算&#xff0c;本篇就简单介绍一下在分页存储管理、分段存储管理、磁盘存储管理中涉及的地址转换问题。 虚拟地址与物理地址 编程一般只有可能和逻辑地址打交道&#xff0c;比如在 C 语言中&#x…...

HyperGBM用4记组合拳提升AutoML模型泛化能力

本文作者&#xff1a;杨健&#xff0c;九章云极 DataCanvas 主任架构师 如何有效提高模型的泛化能力&#xff0c;始终是机器学习领域的重要课题。经过大量的实践证明比较有效的方式包括&#xff1a; 利用Early Stopping防止过拟合通过正则化降低模型的复杂度使用更多的训练数…...

P6软件中的前锋线设置

卷首语 所谓前锋线&#xff0c;是指从评估时刻的时标点出发&#xff0c;用点划线一次连接各项活动的实际进展位置所形成的的线段&#xff0c;其通常为折线。 关键路径法 前锋线比较法&#xff0c;是通过在进度计划中绘制实际进度前锋线以判断活动实际进度与计划进度的偏差&a…...

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<二>---后端架构完善与接口开发

数据库准备&#xff1a; 在上一次Spring Boot Vue3 前后端分离 实战 wiki 知识库系统<一>---Spring Boot项目搭建已经将SpringBoot相关的配置环境给搭建好了&#xff0c;接下来则需要为咱们的项目创建一个数据库。 1、mysql的安装&#xff1a; 关于mysql的安装这里就…...

如何在logback.xml中自定义动态属性

原文地址&#xff1a;http://blog.jboost.cn/trick-logback-prop.html 当使用logback来记录Web应用的日志时&#xff0c;我们通过在logback.xml中配置appender来指定日志输出格式及输出文件路径&#xff0c;这在一台主机或一个文件系统上部署单个实例没有问题&#xff0c;但是…...

嵌入式系统硬件设计与实践(第一步下载eda软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 现实生活中&#xff0c;我们经常发现有的人定了很多的目标&#xff0c;但是到最后一个都没有实现。这听上去有点奇怪&#xff0c;但确实是实实在在…...

Portraiture4免费磨皮插件支持PS/LR

Portraiture 4免去了繁琐的手工劳动&#xff0c;选择性的屏蔽和由像素的平滑&#xff0c;以帮助您实现卓越的肖像润色。智能平滑&#xff0c;并删除不完善之处&#xff0c;同时保持皮肤的纹理和其他重要肖像的细节&#xff0c;如头发&#xff0c;眉毛&#xff0c;睫毛等。 一键…...

Python学习笔记202302

1、numpy.empty 作用&#xff1a;根据给定的维度和数值类型返回一个新的数组&#xff0c;其元素不进行初始化。 用法&#xff1a;numpy.empty(shape, dtypefloat, order‘C’) 2、logging.debug 作用&#xff1a;Python 的日志记录工具&#xff0c;这个模块为应用与库实现了灵…...

2023年大数据面试开胃菜

1、kafka的message包括哪些信息一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成&#xff0c;header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。当magic的值为1的时候&#xff0c;会在magic和crc32之间多一个字节…...

优雅的controller层设计

controller层设计 Controller 层逻辑 ​ MVC架构下&#xff0c;我们的web工程结构会分为三层&#xff0c;自下而上是dao层&#xff0c;service层和controller层。controller层为控制层&#xff0c;主要处理外部请求。调用service层&#xff0c;一般情况下&#xff0c;contro…...

同步、通信、死锁

基础概念竞争资源引起两个问题死锁&#xff1a;因资源竞争陷入永远等待的状态饥饿&#xff1a;一个可运行程序由于其他进程总是优先于它&#xff0c;而被调用程序总是无限期地拖延而不能执行进程互斥&#xff1a;若干进程因相互争夺独占型资源而产生的竞争关系进程同步&#xf…...

【聚类】谱聚类解读、代码示例

【聚类】谱聚类详解、代码示例 文章目录【聚类】谱聚类详解、代码示例1. 介绍2. 方法解读2.1 先验知识2.1.1 无向权重图2.1.2 拉普拉斯矩阵2.2 构建图&#xff08;第一步&#xff09;2.2.1 ϵ\epsilonϵ 邻近法2.2.2 k 近邻法2.2.3 全连接法2.3 切图&#xff08;第二步&#xf…...

最牛逼的垃圾回收期ZGC(1),简介

1丶什么是ZGC? ZGC是JDK 11中引入的一种可扩展的、低延迟的垃圾收集器。ZGC最主要的特点是&#xff1a;在非常短的时间内&#xff08;一般不到10ms&#xff09;&#xff0c;就可以完成一次垃圾回收&#xff0c;而且这个时间是与堆的大小无关的。另外&#xff0c;ZGC支持非常大…...

微服务的Feign到底是什么

Feign是什么 分区是一种数据库优化技术&#xff0c;它可以将大表按照一定的规则分成多个小表&#xff0c;从而提高查询和维护的效率。在分区的过程中&#xff0c;数据库会将数据按照分区规则分配到不同的分区中&#xff0c;并且可以在分区中使用索引和其他优化技术来提高查询效…...

JavaScript 正则表达式

正则表达式&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。什么是正则表达式&#xff1f;正则表达式是由一…...

【批处理脚本】-1.15-文件内字符串查找命令find

"><--点击返回「批处理BAT从入门到精通」总目录--> 共7页精讲(列举了所有find的用法,图文并茂,通俗易懂) 在从事“嵌入式软件开发”和“Autosar工具开发软件”过程中,经常会在其集成开发环境IDE(CodeWarrior,S32K DS,Davinci,EB Tresos,ETAS…)中,…...

【手撕面试题】JavaScript(高频知识点二)

目录 面试官&#xff1a;请你谈谈JS的this指向问题 面试官&#xff1a;说一说call apply bind的作用和区别&#xff1f; 面试官&#xff1a;请你谈谈对事件委托的理解 面试官&#xff1a;说一说promise是什么与使用方法&#xff1f; 面试官&#xff1a;说一说跨域是什么&a…...

Web学习1_HTML

在学校期间学的Web知识忘了一些&#xff0c;很多东西摸棱两可&#xff0c;现重新系统的学习一下。 首先下载安装完vsc后并下载拓展文件live server&#xff08;模拟一个服务器&#xff09; Auto Rename Tag&#xff08;在写网页时&#xff0c;自动对齐前后标签&#xff09;在设…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...