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

数据结构·树

树的特点

  • 最小连通图

  • 无环

  • 有且只有 n − 1 n-1 n1 条边

树的建立方式

顺序存储

  • 只适用于满n叉树,完全n叉树

  • 1<<n 表示结点 2 n 2^n 2n
  • P4715 【深基16.例1】淘汰赛
void solve() {cin >> n;for (int i = 0; i<(1<<n); i++) {cin >> value[i + (1 << n)];}

结构体数组

typedef struct node {int w,l,r,f;
};
vector<node>nodes(109, node());

链式存储

比结构体数组存储更加灵活,不依赖结点编号,且给定输入,父子关系明确。

leetcode的给定输入格式

  • 使用结构体存储结点信息,使用指针的形式存储父母和孩子的信息
 * struct TreeNode {*     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) {}

图的存储方式

树作为一种特殊的图,完全可以沿用图的存储方式










以下均为例题

遍历树的应用

    bool dfs(TreeNode*left,TreeNode*right){if(!left&&right)return false;if(left&&!right)return false;if(!left&&!right)return true;return left->val==right->val&&dfs(left->left,right->right)&&dfs(left->right,right->left);}bool isSymmetric(TreeNode* root) {if(!root)return true;return dfs(root->left,root->right);}
  • 104.二叉树的最大深度:后序遍历。
    int dfs(TreeNode* root){if(!root)return 0;return max(dfs(root->left),dfs(root->right))+1;}int maxDepth(TreeNode* root) {return dfs(root);   }
  • 111.二叉树的最小深度:后序遍历,但是只有叶子结点才算深度,所以遍历空结点会干扰最后答案,干脆不遍历空结点,空结点设置为INT_MAX终止条件也改为叶子结点。y
    int dfs(TreeNode*root){if(!root->left&&!root->right)return 1;int left=INT_MAX,right=INT_MAX;if(root->left)left=dfs(root->left);if(root->right)right=dfs(root->right);return min(left,right)+1;}int minDepth(TreeNode* root) {if(!root)return 0;return dfs(root);}

222.完全二叉树的节点个数:后序遍历或者BFS。

    int dfs(TreeNode*root){if(!root)return 0;return dfs(root->left)+dfs(root->right)+1;}int countNodes(TreeNode* root) {return dfs(root);}
  • 110. 平衡二叉树:本质是比较高度。可以用pair<int,int>分别表示子树的高度和子树是否满足平衡二叉树,也可以用特殊值-1处理。
    int dfs(TreeNode* root){if(!root)return 0;int left=dfs(root->left);int right=dfs(root->right);if(left==-1||right==-1)return -1;if(left-right>=2||right-left>=2){return -1;}return max(left,right)+1;}bool isBalanced(TreeNode* root) {if(dfs(root)!=-1)return true;return false;}
  • 257. 二叉树的所有路径:回溯,注意to_string函数的使用。还用了一点终止条件控制带条件的遍历
    vector<string>res;void dfs(TreeNode* root,string s){if(!root)return;if(!root->left&&!root->right){res.push_back(s);}if(root->left){string tmp(s);tmp+="->";tmp+=to_string(root->left->val);dfs(root->left,tmp);}      if(root->right){string tmp(s);tmp+="->";tmp+=to_string(root->right->val);dfs(root->right,tmp);}}vector<string> binaryTreePaths(TreeNode* root) {string s;s+=to_string(root->val);dfs(root,s);return res;}
  • 404.左叶子之和:使用后序遍历。特殊判断是否存在左叶子结点
    int dfs(TreeNode* root){if(!root)return 0;int value=0;if(root->left){if(!root->left->left&&!root->left->right){value+=root->left->val;}}return value+dfs(root->left)+dfs(root->right);}int sumOfLeftLeaves(TreeNode* root) {return dfs(root);}
  • 513.找树左下角的值:设置全局变量,然后dfs即可。
    int ans=0;int max_depth=0;void dfs(TreeNode* root,int depth){if(!root)return;if(!root->left&&!root->right){if(depth>max_depth){max_depth=depth;ans=root->val;}}dfs(root->left,depth+1);dfs(root->right,depth+1);}int findBottomLeftValue(TreeNode* root) {dfs(root,1);return ans;}
  • 112. 路径总和:后序遍历。
    bool dfs(TreeNode* root,int sum,int targetSum){if(!root->left&&!root->right){if(sum==targetSum){return true;}return false;}bool left=false,right=false;if(root->left)left=dfs(root->left,sum+root->left->val,targetSum);if(root->right)right=dfs(root->right,sum+root->right->val,targetSum);return left||right;}bool hasPathSum(TreeNode* root, int targetSum) {if(!root)return false;return dfs(root,root->val,targetSum);}
    TreeNode*dfs(vector<int>& inorder,vector<int>& postorder){if(inorder.size()==0)return nullptr;if(inorder.size()==1){TreeNode*node=new TreeNode(inorder[0]);return node;}int value=postorder[postorder.size()-1];TreeNode*root=new TreeNode(value);int idx=-1;for(int i=0;i<inorder.size();i++){if(inorder[i]==value){idx=i;break;}}vector<int>inorder_left(inorder.begin(),inorder.begin()+idx);vector<int>inorder_right(inorder.begin()+idx+1,inorder.end());vector<int>postorder_left(postorder.begin(),postorder.begin()+idx);vector<int>postorder_right(postorder.begin()+idx,postorder.end()-1);root->left=dfs(inorder_left,postorder_left);root->right=dfs(inorder_right,postorder_right);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {return dfs(inorder,postorder);}

相关文章:

  • Upwork全球化战略:用“文化套利”收割国际客户
  • Spark-SQL核心编程
  • 无人机气动-结构耦合技术要点与难点
  • API:科技赋能,引领智能文字识别、身份认证与发票查验真伪变革
  • centos yum install environment-modules
  • 初识Redis · list和hash类型
  • 速卖通商品详情API接口:功能、应用与开发指南
  • 一文了解:北斗短报文终端是什么,有哪些应用场景?
  • UE 使用事件分发器设计程序
  • 深入 Java 正则表达式源码:透视 Matcher.group(int) 的分组提取机制
  • 服务器ssh安装
  • 考研408参考用书:计算机组成原理(唐朔飞)介绍,附pdf
  • 观察者模式(行为模式)
  • JavaScript `new Date()` 方法移动端 `兼容 ios`,ios环境new Date()返回NaN
  • mysql no space left on device
  • Ubuntu20.04 设置开机自启
  • YOLO11改进——融合BAM注意力机制增强图像分类与目标检测能力
  • 黑马头条day01
  • Deepseek本地部署 + 个性化 Rag 知识库
  • 【过程控制系统】PID算式实现,控制系统分类,工程应用中控制系统应该注意的问题
  • 王毅集体会见加勒比建交国外长及代表
  • 海北州委常委、常务副州长桑本履新青海省供销社理事会主任
  • “降息潮”延续,多家民营银行下调存款利率
  • 他站在当代思想的地平线上,眺望浪漫主义的余晖
  • 巫蛊:文化的历史暗流
  • 上海“世行对标改革”的税务样本:设立全国首个税务审判庭、制定首个税务行政复议简易程序