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

java算法OJ(4)树与二叉树


目录

​编辑

1.前言

2.正文

2.1树的结构定义

2.2定义树的节点

2.3树的遍历

2.4递归实现

2.4.1树的前序遍历

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

2.4.2树的中序遍历

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

2.4.3树的后序遍历

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

2.4.4树的层序遍历

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

2.5非递归实现

3.小结


1.前言

哈喽大家好喔,今天博主继续进行数据结构的分享与学习,今天的主要内容是树与二叉树,从这节课开始就标志着数据结构从线性的转化为树形,让我们开始吧。

2.正文

2.1树的结构定义

我们如何来理解树的结构定义呢。让我们先看图片中的左侧一部分,1->4->6,是不是可以把它理解成为一个链表,那么链表中的next变量就是树的边界。那我们又如何实现其中一个节点可以往下指多个节点呢,即将类里面访问成员变量左右子树即可。

以下是树的结构特点:

  1. 有且仅有一个特定的节点被称为根节点(Root):树中的每个节点都直接或间接地与根节点相连。
  2. 树中的其他节点可以被分为m(m>0)个子树:这些子树本身也是树结构。
  3. 树中的节点不包含任何循环:即从任一节点出发,沿着有向边走,不能回到原节点。

2.2定义树的节点

讲完了树的结构定义,那么他到底代码是如何实现的呢,让我们逐层来分析:

首先需要一个头结点,既然是树那么就有俩个子节点,另外头节点和俩个子节点下都有需要存储的值,最后再在类里面写上构造方法,这个类就完成了。明白了我们所有需要的量,接下来就可以开始敲代码了。

public static class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode(int v) {val = v;}}

2.3树的遍历

在树中,一共有四种遍历的方式,前序遍历,中序遍历,后序遍历和层序遍历,接下来让我们详细讲解一下其中的含义:

前序遍历

在前序遍历中,我们首先访问根节点,然后递归地对左子树进行前序遍历,最后递归地对右子树进行前序遍历。

访问顺序:根 -> 左 -> 右。


中序遍历

在中序遍历中,我们首先递归地对左子树进行中序遍历,然后访问根节点,最后递归地对右子树进行中序遍历。

访问顺序:左 -> 根 -> 右。

中序遍历的一个重要特性是,它可以按照升序输出二叉搜索树中的所有节点。


后序遍历

在后序遍历中,我们首先递归地对左子树进行后序遍历,然后递归地对右子树进行后序遍历,最后访问根节点。

访问顺序:左 -> 右 -> 根。

后序遍历通常用于删除二叉树,因为它可以确保在访问节点之前,其子节点已经被处理。


层序遍历

通常使用队列来实现层序遍历,每次从队列中取出一个节点,访问它,然后将它的子节点加入队列中。

访问顺序:从树的顶部开始,逐层向下,每层从左到右访问所有节点。

2.4递归实现

下面四种遍历都主要的采用递归来进行实现,代码量不大但需要一定的理解,接下来我会详细的展开。

2.4.1树的前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

先看解析:

  • 首先创造一个用于接受答案的列表
  • 建立递归函数
  • 如果递归函数是空则返回到上一步,非空而往下进行
  • 先将中节点接入列表,先走左子树,左子树走完再走右子树,完成递归
  • 最后return即可

下文的中序遍历和后序遍历只是代码逻辑顺序不同,实现思路一致,不做讲解。

再上代码:

class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();preorder(root,res);return res;}public void preorder(TreeNode root,List<Integer>res){if(root == null)return ;res.add(root.val);preorder(root.left,res);preorder(root.right,res);}
}

2.4.2树的中序遍历

94. 二叉树的中序遍历 - 力扣(LeetCode)

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();postorder(root,res);return res;}public void postorder(TreeNode root,List<Integer> res){if(root == null)return;postorder(root.left,res);res.add(root.val);postorder(root.right,res);}
}

2.4.3树的后序遍历

145. 二叉树的后序遍历 - 力扣(LeetCode)

2.4.1.1题目

2.4.1.2示例

 

2.4.1.3代码
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();postorder(root,res);return res;}public void postorder(TreeNode root,List<Integer> res){if(root == null)return;postorder(root.left,res);postorder(root.right,res);res.add(root.val);}
}

2.4.4树的层序遍历

102. 二叉树的层序遍历 - 力扣(LeetCode)

2.4.1.1题目

2.4.1.2示例

2.4.1.3代码

层序遍历需要稍微复杂一些,但是实现的方式也有很多,下面展示了其中的一种方式,有兴趣的小伙伴还可以尝试多种实现哦,上思路:

这道题主体思路就是先创建一个储存元素为列表的列表(题目要求的返回形式),用队列来模拟每一层的状态。

  • 先将头节点压入队列,进入while循环,创建一个储存当前层的列表。
  • 判断队列中元素数量作为for循环条件
  • 先将队列中当前头节点元素压入储存当前层的列表,再将头节点弹出队列
  • 如果左子树不为空,就把它压入队列,右节点同理
  • 最后将本层列表压入res总列表中,继续下一次循环
  • 此时原先的左右节点化为上文的头结点继续循环,直到二者皆为空。
  • 最后return即可
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res = new ArrayList<List<Integer>>();if(root == null)return res;Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);while(!queue.isEmpty()){LinkedList list = new LinkedList<Integer>();int n = queue.size();TreeNode treeNode = new TreeNode();for(int i = 0;i < n;i++){treeNode = queue.poll();list.add(treeNode.val);if(treeNode.left != null){queue.offer(treeNode.left);}if(treeNode.right != null){queue.offer(treeNode.right);}}res.add(list);}return res;}
}

2.5非递归实现

当然除了通过递归实现树的各种遍历以外,还可以通过非递归的方式来进行实现,比如通过栈实现,下面我就以一个栈来实现后序遍历。

我们都知道后序遍历先打印左,再打印右,再打印中,栈是一种先进后出的数据结构,这样我们在把元素压入栈的时候则需要额外注意。过程如下:

  • 先将头节点压入栈中
  • 判断左子树是否为空或者是否被处理过,如果不为空也没被处理过则将其也压入栈中
  • 右子树同上面理
  • 如果遇到子书遍历到树底(即其左右子树均为空且该未被处理),打印后弹出
  • 最后return即可

接下来我们附上代码:

public static void posOrderOneStack(TreeNode h) {if (h != null) {Stack<TreeNode> stack = new Stack<>();stack.push(h);while (!stack.isEmpty()) {TreeNode cur = stack.peek();if (cur.left != null && h != cur.left && h != cur.right) {stack.push(cur.left);} else if (cur.right != null && h != cur.right) {stack.push(cur.right);} else {System.out.print(cur.val + " ");h = stack.pop();} }System.out.println();}}

3.小结

今天java算法OJ(4)树与二叉树到这里就结束了,不要忘了点一手关注再走哦,希望喜欢的朋友多多支持我哦~


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

相关文章:

  • 读论文框架
  • 离线数仓(2)
  • 浅谈SpringBoot读取application配置文件流程
  • Whisper 音视频转写
  • 5个免费下载高清无水印带货短视频素材的网站推荐
  • linuxC读取bin文件
  • Spring 事务支持
  • python 爬虫 入门 一、基础工具
  • Rotary Position Embedding(RoPE)在视觉Transformer中的应用与提升
  • 两个案例全面阐述全链路测试怎么做
  • JAVA封装和包
  • C# 里反射(Reflection)的應用說明
  • 并查集算法
  • 一站式讲解Wireshark网络抓包分析的若干场景、过滤条件及分析方法
  • 深入探索 C++ STL: 高效双向链表 list 的使用与实践
  • 【数据结构】在二叉树中有两个结点m和n,若m是n的祖先,则使用后序遍历可以找到从m到n的路径
  • 兰迪·舍克曼担任生命银行链(LBC)顾问,赋能基因数据技术发展
  • 【C++刷题】力扣-#170-两数之和III-数据结构设计
  • 基础实验4-2.7 修理牧场
  • kernel panic 稳定性分析实例(三)