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

二叉树的存储方式和遍历方式

文章目录

  • 二叉树的存储方式
  • 二叉树的遍历方式
    • DFS--递归遍历
    • DFS--迭代遍历
    • BFS--层次遍历 LC102

二叉树的存储方式

链式存储(指针)或 顺序存储(数组)

(1)链式存储:通过指针把分布在各个地址的节点串联一起。

(2)顺序存储:元素在内存是连续分布的,就是用数组来存储二叉树。
遍历方式:如果父节点的数组下标是 i,那么它的左孩子就是 2i + 1,右孩子 2i + 2,孩子的父节点为(i-1)/2。

链式存储的二叉树节点的定义方式(二叉树的定义和链表是差不多的,相对于链表 ,二叉树的节点里多了一个指针, 有两个指针,指向左右孩子)

public class TreeNode {int val;TreeNode left; //表示左子节点的引用,类型为TreeNodeTreeNode right;TreeNode() {}TreeNode(int val) {this.val = val;}TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}
}

二叉树的遍历方式

  • 广度优先遍历

    • 层次遍历(迭代法)
  • 深度优先遍历

    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)

DFS–递归遍历

// 前序遍历·递归·LC144_二叉树的前序遍历
class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<Integer>();preorder(root, result);return result;}public void preorder(TreeNode root, List<Integer> result) {if (root == null) {return;}result.add(root.val);preorder(root.left, result);preorder(root.right, result);}public void preorder(TreeNode root, List<Integer> result) {//     if (root != null) {//     result.add(root.val);//     preorder(root.left, result);//     preorder(root.right, result);//     }// }}
// 中序遍历·递归·LC94_二叉树的中序遍历
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();inorder(root, res);return res;}void inorder(TreeNode root, List<Integer> list) {if (root == null) {return;}inorder(root.left, list);list.add(root.val);             inorder(root.right, list);}
}
// 后序遍历·递归·LC145_二叉树的后序遍历
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();postorder(root, res);return res;}void postorder(TreeNode root, List<Integer> list) {if (root == null) {return;}postorder(root.left, list);postorder(root.right, list);list.add(root.val);           }
}

DFS–迭代遍历

// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();//必须要先判断,因为如果root==null,在执行 stack.push(root)时将会抛出空指针异常if (root == null){return result;}Stack<TreeNode> stack = new Stack<>();stack.push(root);while (!stack.isEmpty()){TreeNode node = stack.pop();result.add(node.val);if (node.right != null){stack.push(node.right);}if (node.left != null){stack.push(node.left);}}return result;}
}// 中序遍历顺序: 左-中-右 入栈顺序: 左-右
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;//stack.push(root);(不能先把根节点入栈)while(cur != null || !stack.isEmpty()){// 尽可能深入左子树if(cur != null){stack.push(cur);cur = cur.left;}//当前节点为空,说明左子树已经遍历完毕,弹出栈顶元素,再处理右子树else{cur = stack.pop();result.add(cur.val);cur = cur.right;}}return result;}
}// 后序遍历:先序遍历是中左右,我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();if (root == null){return result;}Stack<TreeNode> stack = new Stack<>();stack.push(root);while (!stack.isEmpty()){TreeNode node = stack.pop();result.add(node.val);if (node.left != null){stack.push(node.left);}if (node.right != null){stack.push(node.right);}}Collections.reverse(result);return result;}
}

BFS–层次遍历 LC102

//BFS--迭代方式--借助队列  (题源)
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> resList = new ArrayList<>();if (root == null) {return resList;}//创建一个队列,使用 LinkedList 作为底层实现Queue<TreeNode> que = new LinkedList<>();que.offer(root);  //将元素插入到队尾while(!que.isEmpty()){List<Integer> itemList = new ArrayList<>();int levelSize = que.size();//for(int i = 0;i < que.size();i++)   不正确,因为for循环过程中size会变化for (int i = 0; i < levelSize; i++) {//移除并返回队列头部的元素,如果队列为空,则返回nullTreeNode tmpNode = que.poll();itemList.add(tmpNode.val);if(tmpNode.left != null){que.offer(tmpNode.left);}if(tmpNode.right != null){ que.offer(tmpNode.right);}}resList.add(itemList);}return resList;}
}//BFS--递归方式
class Solution {List<List<Integer>> resList = new ArrayList<>();public List<List<Integer>> levelOrder(TreeNode root) {// 初始层级为0,调用递归函数处理checkFun01(root, 0);return resList;}    public void checkFun01(TreeNode node, int deep) {if (node == null) {return;}deep++;//当层级增加时,确保resList中已经有足够的层级列表if (resList.size() < deep) {resList.add(new ArrayList<Integer>());}// 将当前节点值加入对应层级的列表中resList.get(deep - 1).add(node.val);// 递归处理左右子节点checkFun01(node.left, deep);checkFun01(node.right, deep);}
}LC107自底向上的层序遍历,就是在最后将集合翻转即可:Collections.reverse(resList);

http://www.mrgr.cn/news/60680.html

相关文章:

  • SQL LIKE 操作符
  • Ubuntu忘记密码
  • Django-中间件(切面编程AOP)
  • OceanBase 安全体系解析之身份鉴别
  • Python实现摇号系统
  • 当我们在微服务中使用API网关时,它是否会成为系统的瓶颈?这种潜在的瓶颈如何评估和解决?如何在微服务架构中保证高效请求流量?|API网关|微服务|异步处理
  • 错误概率平均错误概率的计算
  • WPF+MVVM案例实战(九)- 霓虹灯字效果控件封装实现
  • 【Javaee】网络原理—http协议(一)
  • 特种作业操作高压电工题库
  • Spring AOP
  • 洛谷P1025-数的划分 详解
  • DNS域名解析服务器
  • 大模型低资源部署策略
  • 驱动-----LED
  • Cesium着色器
  • NFT Insider #153:The Sandbox 推出 Biggie 奇妙宇宙体验,ApeChain 推出顶级交易员游戏
  • RHCE的学习(8)
  • leetcode-63-不同陆路径II
  • 超子物联网HAL库笔记:[汇总]
  • 开发维护初学者指南——软件维护
  • 小米大模型岗离职了,聊一下现在的面试....
  • Python 基础语法 - 关系运算符
  • [JAVAEE] 面试题(一) - 锁策略, synchronized的详细介绍
  • 【HTML】之基本标签的使用详解
  • GitHub每日最火火火项目(10.28)