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

二叉搜索树与双向链表

目录

基本要求

节点结构

核心算法:中序遍历 + 指针修改

算法思想

递归实现

非递归实现

复杂度分析

时间复杂度:

空间复杂度:


基本要求

这是一个经典的算法问题:将二叉搜索树(BST)转换成一个排序的双向循环链表(或双向链表)。

通常题目要求是:

  1. 双向链表中的节点顺序与二叉搜索树的中序遍历顺序一致(即升序)。
  2. 需要将节点的左右指针分别作为双向链表的前驱(prev)和后继(next)指针。
  3. 有时要求链表是循环的(头尾相连),有时只要求是双向链表。
  4. 原地转换:不能创建新节点,只能调整原有指针

节点结构

class Node { public: int val; Node* left; Node* right; Node(int _val) : val(_val), left(nullptr), right(nullptr) {} };

核心算法:中序遍历 + 指针修改

算法思想

利用BST(二叉搜索树)的中序遍历特性:

  1. 中序遍历BST会按升序访问所有节点
  2. 在遍历过程中,记录前一个访问的节点(prev)
  3. 将当前节点与prev节点双向连接
  4. 遍历完成后,连接头尾节点形成循环

递归实现

class Solution { private: Node* prev = nullptr; // 记录前驱节点 Node* head = nullptr; // 记录链表头节点 // 中序遍历递归函数 void inorderTraversal(Node* curr) { if (!curr) return; // 1. 递归遍历左子树 inorderTraversal(curr->left); // 2. 处理当前节点 if (!prev) { // 第一个节点(最小值),设为头节点 head = curr; } else { // 连接前驱和当前节点 prev->right = curr; curr->left = prev; } // 更新prev为当前节点 prev = curr; // 3. 递归遍历右子树 inorderTraversal(curr->right); } public: Node* treeToDoublyList(Node* root) { if (!root) return nullptr; // 中序遍历并调整指针 inorderTraversal(root); //如果需要转换BST为双向循环链表(不需要删除下面两行代码即可) // 连接头尾形成循环链表 head->left = prev; // 头的前驱指向尾 prev->right = head; // 尾的后继指向头 return head; } };

非递归实现

不使用递归,通过显式栈来模拟中序遍历的过程,在遍历过程中调整指针指向。

class Solution { public: Node* treeToDoublyList(Node* root) { if (!root) return nullptr; Node* prev = nullptr; Node* head = nullptr; stack<Node*> st; Node* curr = root; // 中序遍历(迭代版) while (curr || !st.empty()) { // 左子树入栈 while (curr) { st.push(curr); curr = curr->left; } // 弹出当前节点 curr = st.top(); st.pop(); // 连接节点 if (!prev) { head = curr; // 第一个节点 } else { prev->right = curr; curr->left = prev; } prev = curr; curr = curr->right; // 处理右子树 } //如果需要转换BST为双向循环链表(不需要删除下面两行代码即可) // 形成循环 head->left = prev; prev->right = head; return head; } };

复杂度分析

时间复杂度:

O(n):每个节点被访问一次,n为节点总数

空间复杂度:

O(h),h为树的高度

  • 最坏情况(链状树):O(n)
  • 最好情况(平衡树):O(log n)
http://www.jsqmd.com/news/102742/

相关文章:

  • LobeChat安全性评估:数据隐私保护如何做到位?
  • 银行回单识别技术:企业财务智能化的重要基石
  • GitHub级文档美化终极方案:github-markdown-css完整指南
  • d2s-editor终极指南:暗黑破坏神2存档修改完全手册
  • GitHack终极指南:快速检测Git泄露与完整源代码恢复
  • 图像测量技术详解(含 Halcon 示例)
  • LobeChat用量统计面板:跟踪Token消耗与GPU使用率
  • Vosk Android语音识别:5个常见模型部署问题及解决方案
  • EmotiVoice语音合成在心理咨询机器人中的应用潜力
  • EmotiVoice语音合成在电子宠物产品中的情感互动设计
  • Vosk Android中文语音识别终极部署指南:5个关键避坑点深度解析
  • [鸿蒙2025领航者闯关]人情往来应用开源项目实战
  • 5个关键步骤快速掌握Unitree GO2 ROS2 SDK:从环境搭建到实战应用
  • CSS 伪类 after 清除浮动:前端老手都在用的布局妙招
  • 矢量计算的交响乐:Ascend C向量编程范式与指令级并行优化
  • 基于VUE的企业员工管理系统 [VUE]-计算机毕业设计源码+LW文档
  • 基于VUE的MBTI人格测试系统 [VUE]-计算机毕业设计源码+LW文档
  • 基于VUE的汽车维修保养智能预约系统 [VUE]-计算机毕业设计源码+LW文档
  • 基于VUE的汽车出租管理系统 [VUE]-计算机毕业设计源码+LW文档
  • 基于VUE的企业咨询管理系统 [VUE]-计算机毕业设计源码+LW文档
  • 图像处理函数与形态学操作笔记(含 Halcon 示例)
  • Archipack建筑建模插件新手入门指南:从问题解决到实战应用
  • Koodo Reader如何实现智能封面管理?电子书封面优化全攻略
  • 在Docker环境中安装RabbitMQ延迟消息插件实战记录
  • 具身智能:零基础入门睿尔曼机械臂(五)—— 手眼标定核心原理与数学求解
  • d2s-editor:暗黑破坏神2存档编辑的终极解决方案
  • 光储充一体化方案如何进行精准设计
  • 如何快速实现大屏自适应:前端开发的终极解决方案
  • LSM 原理、实现及与 B+ 树的核心区别
  • 神经网络(1)基本原理 正向传播反向传播 - MKT