算法训练营第十三天:二叉树基础

算法训练营第十三天:二叉树基础

算法训练营第十三天|

二叉树理论基础

  • 二叉树类型有:满二叉树完全二叉树二叉搜索树平衡二叉搜索树
  • 存储方式有:链式存储(指针)和顺序存储(数组)。
  • 遍历方式有:
    1. 深度优先:前中后序遍历(递归,迭代)
    2. 广度优先:层序遍历(迭代)
  • 二叉树结点的定义
* Definition for a binary tree node.*structTreeNode{*int val;* TreeNode *left;* TreeNode *right;*TreeNode():val(0),left(nullptr),right(nullptr){}*TreeNode(int x):val(x),left(nullptr),right(nullptr){}*TreeNode(int x, TreeNode *left, TreeNode *right):val(x),left(left),right(right){}*};

二叉树的递归遍历

卡哥文字以及视频讲解链接

重点

  • 二叉树的学习引入了递归的大量使用
  • 递归三要素
    1. 确定递归函数的参数和返回值
    2. 确定终止条件
    3. 确定单层递归的逻辑
  • 递归开销大,内存占用久

c++实现(前序遍历)中,左,右

classSolution{public: vector<int>preorderTraversal(TreeNode* root){// if(root == nullptr) return {};三处注释搭配使用,起到递归函数中的终止条件作用 vector<int> result;travalTree(root, result);return result;}voidtravalTree(TreeNode* root, vector<int>& result){//这个引用很重要if(root ==nullptr)return;//终止条件 result.push_back(root -> val);//中/*if(root -> left)*/travalTree(root -> left, result);//左孩子/*if(root -> right)*/travalTree(root -> right, result);//右孩子return;}};

c++实现(中序遍历)左,中,右

classSolution{public: std::vector<int>preorderTraversal(TreeNode* root){ std::vector<int> result;traverse(root, result);return result;}private:voidtraverse(TreeNode* node, std::vector<int>& res){if(node ==nullptr)return;//递归终止条件traverse(node->left, res);//左 res.push_back(node->val);//中traverse(node->right, res);//右}};

c++实现(后序遍历)左,右,中

classSolution{public: vector<int>postorderTraversal(TreeNode* root){ vector<int> result;travalTree(root, result);return result;}voidtravalTree(TreeNode* root, vector<int>& result){if(root ==nullptr)return;travalTree(root -> left, result);travalTree(root -> right, result); result.push_back(root -> val);}};

二叉树的迭代遍历

卡哥文字以及视频讲解链接

重点

  • 手动实现一遍,按照实现步骤转换成代码,就理解了
  • 就是一个栈,放进放出。
  • 只用栈,所有的循环判断依靠的是栈本身。弹出顺序和使用顺序一致。
  • 中序遍历使用一个栈无法实现,就是因为栈顶节点和要使用节点不一致。循环判断条件依靠的是帮助指定的指针和栈本身

c++实现(前序遍历)中,左,右

classSolution{public: vector<int>preorderTraversal(TreeNode* root){ stack<TreeNode*> st; vector<int> result;if(root ==nullptr)return result;//检查非空,防止越界 st.push(root);//和while条件搭配while(!st.empty()){ TreeNode* temp = st.top(); st.pop(); result.push_back(temp -> val);//栈的特点,先进后出,所以要先使用就要后放。先放右,再放左if(temp -> right) st.push(temp -> right);if(temp -> left) st.push(temp -> left);}return result;}};

c++实现(中序遍历)左,中,右

一直向左走到底(入栈),遇到空就弹出栈顶(即“回溯”),访问该节点,然后转向其右子树。

classSolution{public: vector<int>inorderTraversal(TreeNode* root){ vector<int> result; stack<TreeNode*> st; TreeNode* cur = root;//这个循环是为了使用curwhile(cur !=NULL||!st.empty()){if(cur !=nullptr){ st.push(cur); cur = cur -> left;//左}else{ cur = st.top(); st.pop(); result.push_back(cur -> val);//中 cur = cur -> right;//右}}return result;}};
  • 因为栈放进去之后,所有元素都没有区别,只有栈顶获取,弹出,所以需要另一个指针来确定栈顶的元素是否要使用

c++实现(后序遍历)左,右,中

classSolution{public: vector<int>postorderTraversal(TreeNode* root){ vector<int> result; stack<TreeNode*> st;if(root ==nullptr)return result; st.push(root);while(!st.empty()){ TreeNode* temp = st.top(); st.pop(); result.push_back(temp -> val);//因为要保证使用顺序是先中,所以把左右中看作中右左的逆序。if(temp -> left) st.push(temp -> left);if(temp -> right) st.push(temp -> right);}//整体反转reverse(result.begin(), result.end());return result;}};

二叉树的统一迭代法

卡哥文字以及视频讲解链接

重点

  • 两种方法
  • 第一种,一个节点可以处理的范围是自己和左右孩子(该节点的根,该节点处理不到)。节点分两部分完成遍历,第一次通过节点来获得左右孩子,第二次看到第一次处理过的标志直接处理本节点。
  • 第二种,给一个pair,first表示节点,second表示是否使用过。
  • 本质是一种方式,就是让节点分两步进行。没处理过的先处理,处理过的直接用

c++实现 (前序遍历)使用null表示使用

classSolution{public: vector<int>preorderTraversal(TreeNode* root){ vector<int> result; stack<TreeNode*> st;if(root ==nullptr)return{};//检查非空 st.push(root);//还是和while搭配while(!st.empty()){ TreeNode* temp = st.top();//每次进入首先获取栈顶元素if(temp){ st.pop();//因为是前序,需要弹出重新排一下序if(temp -> right) st.push(temp -> right);if(temp -> left) st.push(temp -> left); st.push(temp); st.push(nullptr);//在要使用元素后加一个 NULL 表示这个节点和周围的父子关系已经实现过了,下一次就是使用}else{//栈顶为空,弹出,获得新栈顶,使用 st.pop(); temp = st.top(); st.pop(); result.push_back(temp -> val);}}return result;}};

c++实现 (中序遍历)使用null表示使用

classSolution{public: vector<int>inorderTraversal(TreeNode* root){ vector<int> result; stack<TreeNode*> st;if(root ==nullptr)return result; st.push(root);while(!st.empty()){ TreeNode* temp = st.top();if(temp){ st.pop();if(temp -> right) st.push(temp -> right); st.push(temp); st.push(NULL);if(temp -> left) st.push(temp -> left);}else{ st.pop(); temp = st.top(); st.pop(); result.push_back(temp -> val);}}return result;}};

c++实现 (后序遍历)使用null表示使用

classSolution{public: vector<int>postorderTraversal(TreeNode* root){ vector<int> result; stack<TreeNode*> st;if(root ==nullptr)return{}; st.push(root);while(!st.empty()){ TreeNode* temp = st.top();if(temp){//这里不用弹出 st.push(nullptr);if(temp -> right) st.push(temp -> right);if(temp -> left) st.push(temp -> left);}else{ st.pop(); temp = st.top(); st.pop(); result.push_back(temp -> val);}}return result;}};

c++实现 (中序遍历)使用 pair 携带一个bool来确定元素状态

classSolution{public: vector<int>inorderTraversal(TreeNode* root){ vector<int> result; stack<pair<TreeNode*,bool>> st;if(root !=nullptr) st.push(make_pair(root,false));// 多加一个参数,false 为默认值,含义见下文注释while(!st.empty()){auto node = st.top().first;auto visited = st.top().second;//多加一个 visited 参数,使“迭代统一写法”成为一件简单的事 st.pop();if(visited){// visited 为 True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了 result.push_back(node->val);continue;}// visited 当前为 false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”。// 中序遍历是'左中右',右儿子最先入栈,最后出栈。if(node->right) st.push(make_pair(node->right,false));// 把自己加回到栈中,位置居中。// 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割。 st.push(make_pair(node,true));if(node->left) st.push(make_pair(node->left,false));// 左儿子最后入栈,最先出栈}return result;}};

二叉树层序遍历

卡哥文字以及视频讲解链接

重点

  • 逐层

c++实现

classSolution{public: vector<vector<int>>levelOrder(TreeNode* root){ queue<TreeNode*> que; vector<vector<int>> result;if(root ==nullptr)return result; que.push(root);while(!que.empty()){int size = que.size(); vector<int> vec;for(int i =0; i < size ; i++){ TreeNode* temp = que.front(); que.pop(); vec.push_back(temp -> val);if(temp -> left) que.push(temp -> left);if(temp -> right) que.push(temp -> right);} result.push_back(vec);}return result;}};

一个重点

  • 也是特点吧
  • 遍历的时候,如果单一使用栈或者队列,函数体内的循环逻辑围绕的就是栈或队列是否为空
  • 如果是中序迭代,遍历需要一个指针来辅助,函数体内的循环逻辑围绕的就是栈是否空以及指针是否为空
  • 这样便于记忆二叉树的遍历逻辑

坚持就是胜利

日期天次题目
01-2613深度优先、广度优先
  • 第十三天,搞定!

author轩

Read more

LLaMA-Factory微调多模态大模型Qwen3-VL

LLaMA-Factory微调多模态大模型Qwen3-VL

LLaMA-Factory微调多模态大模型Qwen3-VL 目录 LLaMA-Factory微调多模态大模型Qwen3-VL 1. 显卡驱动 2. 模型微调 3. 模型导出 4. 模型部署:vLLM服务 5. 测试效果 1. 显卡驱动 * 显卡型号:NVIDIA GeForce RTX 3090 24G * 显卡驱动:NVIDIA-SMI 535.171.04             * CUDA: 12.2 ,Driver Version: 535.171.04   微调Qwen3-VL-2B模型,至少需要12G显存 2. 模型微调 项目采用大型语言模型工厂(LLaMA-Factory)对大模型微调,目前可支持Qwen3 / Qwen2.5-VL / Gemma 3 / GLM-4.1V / InternLM

By Ne0inhk
【混元AIGC+腾讯云智能体+首创Coze核心流思维导图MCP】:打造一个文思通-智能写作助手Agent

【混元AIGC+腾讯云智能体+首创Coze核心流思维导图MCP】:打造一个文思通-智能写作助手Agent

【混元AIGC+腾讯云智能体+首创Coze核心流思维导图MCP】:打造一个文思通-智能写作助手Agent 1.背景 作为一名长期关注人工智能发展的内容创作者,我经常需要撰写关于AI技术、应用趋势和产品体验的文章。然而,在实际写作过程中,常常会遇到灵感枯竭、结构混乱、表达不够精准等问题。有时候写到一半才发现逻辑断层,或者内容重复,甚至忘记了一些关键知识点。 为了解决这些痛点,我决定打造一个专属于自己的智能写作助手,取名为“文思通”——寓意“文思如泉涌,条理通达”。这个助手不仅要能帮我生成内容,更要具备结构化思维引导、逻辑梳理和语言润色的能力。 最近,我接触到一种创新的工具组合:以 Coze 平台为核心逻辑流,结合自研的思维导图 MCP 服务,可以实现从文本到可视化思维导图的自动转换。这正好解决了我在构思阶段缺乏条理的问题。而选择开发平台时,我注意到腾讯云智能体开发平台与腾讯混元大模型(Hunyuan AIGC) 的深度整合能力非常出色,支持工作流编排、插件扩展(MCP),并且提供稳定高效的推理服务。 最终,我决定采用“混元AIGC + 腾讯云智能体平台

By Ne0inhk
Qwen3.5-4B 微调实战:LLaMA-Factory 打造医疗AI助手

Qwen3.5-4B 微调实战:LLaMA-Factory 打造医疗AI助手

最近在帮一个医疗创业团队做技术支持,他们想把通用大模型改造成能回答专业医疗问题的智能助手。今天就把整个过程整理出来,希望对有类似需求的朋友有所帮助。 核心工具链:LLaMA-Factory + Qwen3.5-4B + 医疗问答数据集 Qwen3.5 是阿里最新发布的千问系列模型,4B 参数量刚好卡在"效果够用 + 显存友好"的甜蜜点;LLaMA-Factory 则是目前开源社区最成熟的微调框架,上手简单,坑也相对少。 准备工作 先说硬件要求。4B 模型用 LoRA 微调的话,一张 12GB 显存的显卡就够了(比如 RTX 4070)。如果手头只有 8GB 显存的卡,可以上 QLoRA 量化方案,牺牲一点精度换显存空间。 微调方式 4B 模型显存需求 推荐显卡 LoRA (16-bit) ~10-12 GB

By Ne0inhk
2026年高校AIGC检测新规解读:AI率多少算合格?

2026年高校AIGC检测新规解读:AI率多少算合格?

2026年高校AIGC检测新规解读:AI率多少算合格? 从2024年知网正式上线AIGC检测功能开始,短短两年时间,"AI率"已经从一个新鲜名词变成了每个毕业生必须面对的硬性指标。2026年,各高校的AIGC检测政策进一步收紧和细化,要求也越来越明确。 那么,2026年AI率到底多少才算合格?不同学校的标准差别大吗?不合格会面临什么后果?本文将对这些问题进行深入解读。 一、AIGC检测已成为毕业论文审查的标配 回顾AIGC检测在高校中的普及历程,可以用"指数级扩散"来形容: * 2024年:知网上线AIGC检测功能,少数985/211院校开始试点,大部分学校处于观望状态 * 2025年:超过60%的本科院校和80%的研究生培养单位将AIGC检测纳入论文审查流程 * 2026年:AIGC检测基本实现全覆盖,包括专科院校在内的绝大部分高等教育机构都已建立相关制度 这一进程的背后,是教育部在2025年初发布的《关于加强高等学校学位论文学术诚信管理的指导意见》,其中明确提到"鼓励各高校引入人工智能生成内容检测机制,将AIGC检测作为论文质量保障的重要环节"。 虽然教育部没

By Ne0inhk