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

【数据结构】——二叉树

目录

一.深度优先遍历DFS(前中后序遍历)

1.先序遍历(中左右)

2.中序遍历(左中右)——>对于搜索树来说是递增序列

3.后序遍历(左右中)——>可以处理深度的问题(栈的最大高度就是树的最大深度)

4.如何走完整棵树

二.层序遍历BFS

1.层序遍历

2.Z字形遍历(无非就是奇偶数反一下)

二.最大深度——后序遍历

1.递归法

2.非递归(栈的最大深度就是树的最大高度)

3.层序遍历

三.最小深度

1.递归(后序遍历)

2.层序遍历

四.二叉树的右视图

五.二叉搜索树的最近公共祖先

六.判断是否为对称二叉树

七.二叉树的翻转

八.寻找二叉搜索树中的目标节点

九.二叉搜索树范围查询

十.范围和

1.中序遍历

2.递归解


一.深度优先遍历DFS(前中后序遍历)

1.先序遍历(中左右)

先打印出当前节点,然后往左走到底,走到底后再往右走。(走哪打哪

2.中序遍历(左中右)——>对于搜索树来说是递增序列

往右走之前,或者就没有右子树时,打印当前节点。(左边走完再打

3.后序遍历(左右中)——>可以处理深度的问题(栈的最大高度就是树的最大深度)

右子树处理完成了,也就是弹栈了,打印弹栈节点。(右边走完再打

4.如何走完整棵树

问题1:为什么要压栈?因为要记住来时的路,为什么要记住来时的路,因为当前节点还没处理完

一开始一直往左走,直到为空,要回头,怎么回头?有栈记住了来时的路——stack.peek()

问题2:开始处理右子树:怎么处理右子树?往右走?怎么知道右子树处理完了?

1.拿到的这个栈顶元素就没有右子树,当然就算处理完了,pop掉就完了

2.如果有右子树,栈顶元素的右孩子等于刚刚弹栈的元素,也就知道右子树也处理完了。pop掉

代码演示

        LinkedList<TreeNode> stack = new LinkedList<>();TreeNode curr = root; // 代表当前节点TreeNode pop = null; // 最近一次弹栈的元素while (!stack.isEmpty() || curr != null) {if (curr != null) {stack.push(curr);// 待处理左子树colorPrintln("前:" + curr.val, 31);curr = curr.left;} else {TreeNode peek = stack.peek();// 没有右子树if (peek.right == null) {colorPrintln("中:" + peek.val, 36);pop = stack.pop();colorPrintln("后:" + pop.val, 34);}// 右子树处理完成else if (peek.right == pop) {pop = stack.pop();colorPrintln("后:" + pop.val, 34);}// 待处理右子树else {colorPrintln("中:" + peek.val, 36);curr = peek.right;}}}

二.层序遍历BFS

1.层序遍历

每一层都可以用一个队列来存储

    public List<List<Integer>> levelOrder1(TreeNode root) {List<List<Integer>> result = new ArrayList<>();LinkedList<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);while (!queue.isEmpty()) {ArrayList<Integer> list = new ArrayList<>();int size = queue.size();for (int i = 0; i < size; i++) {TreeNode n = queue.poll();list.add(n.val);if (n.left != null){queue.offer(n.left);}if (n.right != null){queue.offer(n.right);}}result.add(list);}return result;}

2.Z字形遍历(无非就是奇偶数反一下)

    public List<List<Integer>> ZlevelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<>();LinkedList<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);boolean b = true;while (!queue.isEmpty()) {LinkedList<Integer> list = new LinkedList<Integer>();int size = queue.size();for (int i = 0; i < size; i++) {TreeNode n = queue.poll();if (b) {list.offerLast(n.val);}else {list.offerFirst(n.val);}if (n.left != null) {queue.offer(n.left);}if (n.right != null) {queue.offer(n.right);}}result.add(list);b = !b;}return result;}

二.最大深度——后序遍历

1.递归法

    public int maxDepth(TreeNode node) {if (node == null) {return 0;}/*if (node.left == null && node.right == null) {return 1;}*/int d1 = maxDepth(node.left);int d2 = maxDepth(node.right);return Integer.max(d1, d2) + 1;}

2.非递归(栈的最大深度就是树的最大高度)

    public int maxDepth(TreeNode root) {TreeNode curr = root;TreeNode pop = null;LinkedList<TreeNode> stack = new LinkedList<>();int max = 0; // 栈的最大高度while (curr != null || !stack.isEmpty()) {if (curr != null) {stack.push(curr);int size = stack.size();if (size > max) {max = size;}curr = curr.left;} else {TreeNode peek = stack.peek();if (peek.right == null || peek.right == pop) {pop = stack.pop();} else {curr = peek.right;}}}return max;}

3.层序遍历

    public int maxDepth(TreeNode root) {if (root == null) {return 0;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int depth = 0;while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {TreeNode poll = queue.poll();
//                System.out.print(poll.val + "\t");if (poll.left != null) {queue.offer(poll.left);}if (poll.right != null) {queue.offer(poll.right);}}
//            System.out.println();depth ++;}return depth;}

三.最小深度

1.递归(后序遍历)

    public int minDepth(TreeNode node) {if (node == null) {return 0;}int d1 = minDepth(node.left); // 1int d2 = minDepth(node.right); // 0if (d2 == 0) { // 当右子树为nullreturn d1 + 1; // 返回左子树深度+1}if (d1 == 0) { // 当左子树为nullreturn d2 + 1; // 返回右子树深度+1}return Integer.min(d1, d2) + 1;}

2.层序遍历

    public int minDepth(TreeNode root) {if (root == null) {return 0;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int depth = 0;while (!queue.isEmpty()) {int size = queue.size();depth ++;for (int i = 0; i < size; i++) {TreeNode poll = queue.poll();if (poll.left == null && poll.right == null) {return depth;}if (poll.left != null) {queue.offer(poll.left);}if (poll.right != null) {queue.offer(poll.right);}}}return depth;}

四.二叉树的右视图

    public List<Integer> rightSideView(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);List<Integer> list = new ArrayList<>();if(root == null) return list;while (!queue.isEmpty()){int size = queue.size();for (int i = 0; i < size; i++) {TreeNode node = queue.poll();if (node.left != null){queue.offer(node.left);}if (node.right != null){queue.offer(node.right);}if (i == size - 1){list.add(node.val);}}}return list;}

五.二叉搜索树的最近公共祖先

    /*__ 6 __/       \2         8/ \       / \0   4     7   9/ \3   5待查找节点 p q 在某一节点的两侧,那么此节点就是最近的公共祖先*/public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {TreeNode a = root;while (p.val < a.val && q.val < a.val || a.val < p.val && a.val < q.val) { // 在同一侧if (p.val < a.val) {a = a.left;} else {a = a.right;}}return a;}

六.判断是否为对称二叉树

    public boolean isSymmetric(TreeNode root) {return check(root.left, root.right);}private boolean check(TreeNode left, TreeNode right) {if (left == null && right == null) {return true;}// left 和 right 不能同时为 nullif(right == null || left == null) {return false;}if (left.val != right.val) {return false;}return check(left.left, right.right) && check(left.right, right.left);}

七.二叉树的翻转

    public TreeNode invertTree(TreeNode root) {fn(root);return root;}private static void fn(TreeNode node) {if (node == null) {return;}TreeNode t = node.left;node.left = node.right;node.right = t;fn(node.left);fn(node.right);}

八.寻找二叉搜索树中的目标节点

中序遍历可以得到一个二叉搜索树的递增序列,所以使用中序遍历。

class Solution {int index = 0;int res;public int findTargetNode(TreeNode root, int cnt) {dfs(root, cnt);return res;}public void dfs(TreeNode root, int cnt){if(root == null) return;dfs(root.right, cnt);index++;if(index > cnt) return;if(index == cnt) res = root.val;dfs(root.left, cnt);}
}

九.二叉搜索树范围查询

同理也是中序遍历,然后在打印的位置加上if条件

十.范围和

1.中序遍历

    public int rangeSumBST2(TreeNode root, int low, int high){LinkedList<TreeNode> stack = new LinkedList<>();TreeNode curr = root;TreeNode pop = null;int sum = 0;while(!stack.isEmpty() || curr != null){if (curr != null) {stack.push(curr);curr = curr.left;}else {//处理右子树TreeNode peek = stack.peek();if (peek.right == null){pop = stack.pop();if (pop.val > high) {break;}if (pop.val >= low){sum += pop.val;}}else if (peek.right == pop){pop = stack.pop();}else {if (peek.val > high) {break;}if (peek.val >= low){sum += peek.val;}curr = peek.right;}}}return sum;}

2.递归解

    public int rangeSumBST(TreeNode node, int low, int high) {if (node == null) {return 0;}if (node.val < low) {return rangeSumBST(node.right, low, high);}if (node.val > high) {return rangeSumBST(node.left, low, high);}// 在范围内return node.val + rangeSumBST(node.left, low, high) + rangeSumBST(node.right, low, high);}


文章转载自:

http://2Nh0QpUq.hgkbj.cn
http://EPTpgijK.hgkbj.cn
http://hhg3WAL4.hgkbj.cn
http://qwZMm0fT.hgkbj.cn
http://QqcKF3TE.hgkbj.cn
http://3snUOXQr.hgkbj.cn
http://CCIP0anw.hgkbj.cn
http://HV1gWOV3.hgkbj.cn
http://sj23BAPd.hgkbj.cn
http://yv2NhJKx.hgkbj.cn
http://0cgJsecG.hgkbj.cn
http://vrE2bQHi.hgkbj.cn
http://stDxfzsT.hgkbj.cn
http://mcUkpPqj.hgkbj.cn
http://MGwnY016.hgkbj.cn
http://n8Irylpd.hgkbj.cn
http://yL6l2xzw.hgkbj.cn
http://HB9ShOHl.hgkbj.cn
http://s717BO00.hgkbj.cn
http://DEaCGtEk.hgkbj.cn
http://gsLrIdV2.hgkbj.cn
http://fj1U2yw8.hgkbj.cn
http://8x4RjG3k.hgkbj.cn
http://tfDnCDZr.hgkbj.cn
http://g6MUwTFZ.hgkbj.cn
http://0h6hO9K4.hgkbj.cn
http://s9amqGja.hgkbj.cn
http://xwBBsRng.hgkbj.cn
http://Qim7YwUt.hgkbj.cn
http://cQjgAAUb.hgkbj.cn
http://www.dtcms.com/a/387077.html

相关文章:

  • 《怪物猎人 荒野》总整理:预载和开放时间、登场怪物
  • web服务解析案例
  • 莫烦Python基础笔记(部分)
  • ACP(四):RAG工作流程及如何创建一个RAG应用
  • qgis导入cad怎么做?
  • 在线图书借阅平台的设计与实现 —— 基于飞算JavaAI的实战开发全流程与优化实践(架构设计与核心模块开发)
  • Spring Cloud - 面试知识点(服务雪崩)
  • 【JQ】使用JS在前端达到存储cookie的效果
  • Git企业开发--分支管理
  • LoRaWAN方案详解:2025年LoRaWAN技术创新与行业发展趋势
  • 【Leetcode hot 100】108.将有序数组转换为二叉搜索树
  • 打包数据集解析及大模型强化学习拓展阅读(96)
  • 软考-系统架构设计师 系统分析与设计详细讲解
  • 什么是信创产品?信创产品认证有哪些标准?
  • docker和虚拟机对比
  • AI: Android 运行ONNX模型
  • transformer各层的输入输出
  • lvgl图形库和qt图形库比较
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘PIL’ 问题
  • 搭建 PHP 网站
  • 流式分析:细胞分群方法
  • Redis 底层数据结构之 Dict(字典)
  • UE 最短上手路线
  • 动手学Agent:Agent设计模式——构建有效Agent的7种模型
  • 苍穹外卖day01
  • 《LINUX系统编程》笔记p14
  • 可直接落地的pytest+request+allure接口自动化框架
  • 【精品资料鉴赏】267页政务大数据资源平台建设方案
  • 面试前端遇到的问题
  • 【深度学习计算机视觉】05:多尺度目标检测——从理论到YOLOv5实践