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

ngx_rbtree_insert_value

1 定义

ngx_rbtree_insert_value 函数 定义在 ./nginx-1.24.0/src/core/ngx_rbtree.c
voidngx_rbtree_insert_value(ngx_rbtree_node_t*temp,ngx_rbtree_node_t*node,ngx_rbtree_node_t*sentinel){ngx_rbtree_node_t**p;for(;;){p=(node->key<temp->key)?&temp->left:&temp->right;if(*p==sentinel){break;}temp=*p;}*p=node;node->parent=temp;node->left=sentinel;node->right=sentinel;ngx_rbt_red(node);}
`ngx_rbtree_insert_value` 函数的作用是: 按节点 `key` 值进行二叉搜索树插入, 将新节点挂载到树中正确的位置并初始化为红色叶子节点,不进行任何红黑树自平衡修复。

2 详解

1 函数签名

voidngx_rbtree_insert_value(ngx_rbtree_node_t*temp,ngx_rbtree_node_t*node,ngx_rbtree_node_t*sentinel)
该函数不向调用者返回任何值,它的职责是纯副作用:修改树的结构,将 node 挂入树中。
参数1 ngx_rbtree_node_t *temp temp 表示“临时指针”,它将在函数内部作为循环游标, 从根节点逐步向下移动,直至找到插入位置的父节点。 调用者传入的是树的 根节点(tree->root)。 函数执行过程中,temp 会被不断更新为当前比较节点的左/右孩子。 最终状态:函数结束时,temp 指向新节点 node 的父节点
参数2 ngx_rbtree_node_t *node 指向待插入节点的指针
参数3 ngx_rbtree_node_t *sentinel 指向全局唯一的哨兵节点

2 逻辑流程

1 局部变量 2 循环查找 3 挂载

1 局部变量
{ngx_rbtree_node_t**p;
p 将用于存放新节点要挂载的“目标位置”的地址,即父节点 left 或 right 指针的地址

2 循环查找
for(;;){p=(node->key<temp->key)?&temp->left:&temp->right;if(*p==sentinel){break;}temp=*p;}
#1 开始一个无限循环,用于沿树向下查找插入点。 循环会在遇到空子树(哨兵)时通过 break 退出,否则不断下行
#2 比较新节点与当前节点 temp 的 key 值: 若 node->key < temp->key,则新节点应插入左子树,p 指向 temp->left 的地址(&temp->left)。 否则(>=),插入右子树,p 指向 &temp->right。
#3 解引用 p,即检查当前节点的相应孩子是否就是哨兵节点 哨兵节点代表“空位”。如果成立,说明已经到达了叶子下一层的空位置,找到了插入点 立即退出 for 循环。 此时 temp 停留在将成为新节点父节点的真实节点上, p 仍保存着 temp 的某侧孩子指针(当前指向哨兵)的地址。
#4 若未遇到哨兵(即 *p 是真实节点), 则将 temp 更新为该孩子节点,继续向树的深层探索。

3 挂载
*p=node;node->parent=temp;node->left=sentinel;node->right=sentinel;ngx_rbt_red(node);}
*p = node; 挂载新节点:将新节点 node 的地址写入 *p。 由于 p 指向父节点 temp 的 left 或 right 指针(原指向哨兵), 这条语句相当于让父节点正确地指向了新节点,完成了物理连接。 node->parent = temp; 设置新节点的父节点指针,指向 temp(即循环结束时的当前节点)。双向链接建立。 node->left = sentinel; 新节点的左孩子设为哨兵节点,表示它是叶子,没有左子树。 node->right = sentinel; 右孩子同样设为哨兵节点,确保新节点是干净的叶子,左右皆空。 ngx_rbt_red(node); 将新节点的颜色设为红色。 红黑树插入规则要求新节点总是红色, 这样可以尽可能地避免违反“从根到叶子的所有路径黑高相同”的性质 (只有当父节点也是红色时才会破坏“不连续红”规则,而这种情况由后续旋转修复)。

整体逻辑总结 函数通过 for 循环遍历树, 利用二级指针 p 同时完成“选择方向”和“定位插入点”的操作。 循环结束时,temp 是父节点,p 存放其子指针的地址,然后将新节点接入,并完成叶子初始化和颜色设定。 将“查找”与“挂载”无缝结合,并且完全依赖哨兵节点避免了 NULL 检查
http://www.jsqmd.com/news/761657/

相关文章:

  • 保姆级教程:基于RK3588 EVB1参考板,手把手教你创建自定义板级DTS文件
  • Python玩转Word:用python-docx给你的简历/论文自动排版(附完整代码)
  • 不只是system分区:为RK3588配置完整的A/B无缝升级分区列表(以Android 12为例)
  • YOLOv5模型改造避坑指南:添加CA注意力机制后,训练时可能遇到的3个问题及解决
  • 告别混乱调用:一文搞懂SAP ABAP中‘->’与‘=>’符号的正确使用场景(含SE24类示例)
  • FPGA实战:手把手教你用Vivado ROM IP核实现HDMI屏幕OSD字符叠加(附Verilog源码)
  • 誉财 YC - 03 - HF 多功能激光门襟机:门襟加工的高效智能专家
  • Go语言打造极简AI图像生成CLI:Imagemage的设计哲学与实战应用
  • SoC设计中PRCM模块架构与低功耗优化实践
  • PotPlayer AI翻译插件:基于大语言模型的本地播放器智能字幕解决方案
  • 保姆级教程:在Windows上用VMware Workstation 16 Pro流畅运行macOS Ventura 13.6
  • 洛雪音乐桌面版:打破平台壁垒,重塑你的音乐世界
  • 在Obsidian中集成Gemini AI助手:实现智能笔记与自动化工作流
  • 从黑盒到透明:用图神经网络揭开药物分子相互作用的神秘面纱
  • Keil5编译报错找不到ARM编译器V5?手把手教你从官网下载并配置AC5.06(附路径设置截图)
  • 告别闪屏!ESP32+SPI墨水屏低功耗显示方案:深度睡眠与局部刷新实战
  • UPDESH数据集:多语言NLP中的文化适配实践
  • 告别SPI/I2C:用GD32F470的EXMC并行总线与FPGA高速通信(附完整时序配置)
  • FastCI:基于智能缓存与增量构建的CI/CD极速引擎实战
  • 实战指南,利用快马为你的项目快速生成代码文档分析工具
  • 2026年成都军事拓展基地实力排行及实测评测:四川军事拓展基地/成都军事夏令营/成都军事拓展基地/四川军事夏令营/选择指南 - 优质品牌商家
  • 多模态视频生成技术SkyReels-V3解析与应用
  • 内脏脂肪 = 脂肪肝?
  • 5分钟掌握VideoDownloadHelper:浏览器视频下载神器全攻略
  • 通达信缠论量化分析插件:5分钟实现智能化技术分析
  • 2026年西南职场压力心理疏导机构排行与选型参考:成都空心病心理咨询/成都线上心理疏导/成都老年人孤独心理疏导/选择指南 - 优质品牌商家
  • 告别裸写寄存器!像玩STM32一样用库函数配置STC15的IO口模式
  • 魔兽争霸III终极地图编辑器HiveWE:5分钟快速上手指南
  • 基于LLM的智能体化SOC平台:架构设计与安全运营实践
  • 别再混淆了!一文讲透WLAN中‘直接转发’和‘隧道转发’到底怎么选?附华为配置对比