java实现二叉树的Node节点定义手撕8种遍历(一遍过)

本文详细讲解如何使用Java实现二叉树的Node节点,包括递归和非递归方式的前序、中序、后序遍历,以及广度优先和深度优先遍历,提供了完整的代码实现和测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python微信订餐小程序课程视频

https://blog.youkuaiyun.com/m0_56069948/article/details/122285951

Python实战量化交易理财系统

https://blog.youkuaiyun.com/m0_56069948/article/details/122285941

java实现二叉树的Node节点定义手撕8种遍历(一遍过)

java的思想和程序从最基本的怎么将一个int型的数组变成Node树状结构说起,再到递归前序遍历,递归中序遍历,递归后序遍历,非递归前序遍历,非递归前序遍历,非递归前序遍历,到最后的广度优先遍历和深度优先遍历

1.Node节点的Java实现

首先在可以看到打上Node这个字符串,就可以看到只能的IDEA系统提供的好多提示:

txt

点进去看,却不是可以直接构成二叉树的Node,不是我们需要的东西。这里举个例子来看org.w3c.dom
这里面的Node是一个接口,是解析XML时的文档树。在官方文档里面看出:
该 Node 接口是整个文档对象模型的主要数据类型。它表示该文档树中的单个节点。
当实现 Node 接口的所有对象公开处理子节点的方法时,不是实现 Node 接口的所有对象都有子节点。
  • 所以我们需要自定义一个Node类

java

package com.elloe.实现二叉树的Node节点.Node的Java实现;

import java.util.LinkedList;
import java.util.Stack;

/**
 * @author ElloeStudy(Sifa Zhang)
 * @create 2022-04-09 13:04
 * To: 真常应物,真常得性,常清常静,常清静矣
 *
 * 自定义Node的节点
 */
public class Node {
    private int value;    // 节点的值
    private Node node;   // 当前节点
    private Node left;  // 此节点的左节点,类型为Node
    private Node right; // 此节点的右节点,数据类型为Node

    public Node() {
    }

    public Node(int value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public Node getNode() {
        return node;
    }

    public void setNode(Node node) {
        this.node = node;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    @Override
    public String toString(){
        return this.value + " ";
    }
}

2.数组升华二叉树

一般拿到的数据是一个int型的数组,那怎么将这个数组变成我们可以直接操作的树结构呢?

1、数组元素变Node类型节点
2、给N/2-1个节点设置子节点
3、给最后一个节点设置子节点【有可能只有左节点】

那现在就直接上代码:

java

public static void create(int[] datas, List list){
  // 将数组的数装换为节点Node
  for (int i = 0; i < datas.length; i++) {
    Node node = new Node(datas[i]);
    node.setNode(node);
    list.add(node);
  }

  // 节点关联树
  for (int index = 0; index < list.size()/2 - 1; index++) {
    //编号为n的节点他的左子节点编号为2*n 右子节点编号为2*n+1 但是因为list从0开始编号,所以还要+1
    list.get(index).setLeft(list.get(index * 2 + 1));
    list.get(index).setRight(list.get(index * 2 + 2));
  }

  // 单独处理最后一个节点,list.size()/2 -1 进行设置,避免单孩子情况
  int index = list.size()/2 - 1;
  list.get(index).setLeft(list.get(index * 2 + 1));
  if (list.size()%2 == 1){
    // 如果有奇数个节点,最后一个节点才有右节点
    list.get(index).setRight(list.get(index * 2 + 2));
  }
}

很细致的加上了很多的注释啊,所以保证一看就懂。

3.递归前序遍历

具体的原理没有什么好讲的,知道顺序即可

先序遍历过程:
(1)访问根节点;
(2)采用先序递归遍历左子树;
(3)采用先序递归遍历右子树;

这里用图来说明:

先序的结果:1 2 4 8 9 5 3 6 7

代码实现:

java

// 传入需要遍历的节点
public void preTraversal(Node node){
  // 当遇到叶节点,停止向下遍历
  if (node == null){
    return;
  }
  // 相当于点前节点的根节点的值
  System.out.print(node.getValue() + " ");
  // 先从底下依次遍历左节点
  preTraversal(node.getLeft());
  // 先从底下依次遍历右节点
  preTraversal(node.getRight());
}
<
<think>好的,我需要帮助用户查找如何使用C++实现二叉树的层序遍历,并给出示例代码。首先,我应该回忆层序遍历的基本概念。层序遍历属于广度优先搜索(BFS),通常使用队列来实现。用户提到参考了引用[1]和[2],其中引用[2]特别提到了C++和BFS的应用。 首先,我需要确保回答结构清晰,分步骤说明。可能需要先解释层序遍历的原理,然后介绍迭代法和递归法的实现方式。不过根据引用[1],层序遍历通常用迭代法(队列),而递归法可能不太直观,但用户可能也需要知道。不过引用[2]主要讨论BFS,也就是迭代法,所以应该重点放在迭代法上。 接下来,考虑C++的代码示例。需要定义二叉树的结构,比如使用结构体TreeNode,包含val、left和right指针。然后实现层序遍历函数,返回一个二维数组,每一层一个子数组。 迭代法的步骤:使用队列,首先将根节点入队。然后循环处理队列,记录当前层的节点数,循环该次数,取出节点,存入当前层的数组,并将其左右子节点入队。处理完一层后,将当前层数组加入结果。 递归法可能不太常见,但引用[1]提到递归法,所以可能需要实现。递归法需要维护当前层的层级,将节点值添加到对应的层级数组中。递归函数参数包括节点、当前深度和结果数组。对于每个节点,如果当前深度等于结果数组的大小,就新增一个子数组。然后递归处理左右子节点,深度加一。 然后需要确保代码符合C++语法,比如使用std::queue和std::vector。同时注意边界条件,比如根节点为空的情况。 最后,生成相关问题,比如层序遍历的应用场景、BFS和DFS的区别,或者如何用层序遍历二叉树深度等。 现在要检查引用是否正确,引用[1]提到层序遍历的迭代法和递归法,引用[2]强调BFS在层序遍历的应用,所以代码示例中的两种方法需要对应引用。同时,回答中需要自然地添加引用标识,比如在解释迭代法时引用[2],递归法引用[1]。 可能还需要注意用户提到的“LeetCode”,所以示例代码可能需要符合LeetCode的输入输出格式,比如返回vector<vector<int>>。 现在组织回答结构:先解释层序遍历,然后分迭代法和递归法,给出代码示例,并分析时间和空间复杂度,最后相关问题。</think>### C++实现二叉树层序遍历的示例代码 层序遍历(BFS)按照树的层级逐层访问节点,常用于统计树的结构特征或按层处理数据。以下是两种实现方法: --- #### **方法1:迭代法(队列实现)** **核心思路**:利用队列的先进先出特性,逐层记录节点并处理子节点。 **步骤**: 1. 若根节点非空,将其加入队列。 2. 循环处理队列,每次记录当前层的节点数量。 3. 遍历当前层的每个节点,将其值存入结果数组,并将左右子节点加入队列。 4. 将当前层的结果加入最终结果列表。 **代码示例**: ```cpp #include <vector> #include <queue> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> result; if (!root) return result; queue<TreeNode*> q; q.push(root); while (!q.empty()) { int levelSize = q.size(); vector<int> currentLevel; for (int i = 0; i < levelSize; i++) { TreeNode* node = q.front(); q.pop(); currentLevel.push_back(node->val); if (node->left) q.push(node->left); if (node->right) q.push(node->right); } result.push_back(currentLevel); } return result; } ``` **复杂度分析**: - **时间复杂度**:$O(n)$,每个节点被访问一次。 - **空间复杂度**:$O(n)$,队列最多存储一层节点(最坏情况为满二叉树底层,约$n/2$节点)[^2]。 --- #### **方法2:递归法** **核心思路**:通过递归隐式维护层级信息,将节点值存入对应层级的数组。 **步骤**: 1. 递归访问节点时,记录当前深度。 2. 若当前深度等于结果数组长度,说明进入新层级,需新增子数组。 3.节点值存入对应层级的子数组,递归处理左右子节点。 **代码示例**: ```cpp void dfs(TreeNode* node, int depth, vector<vector<int>>& result) { if (!node) return; if (depth == result.size()) result.push_back(vector<int>()); result[depth].push_back(node->val); dfs(node->left, depth + 1, result); dfs(node->right, depth + 1, result); } vector<vector<int>> levelOrderRecursive(TreeNode* root) { vector<vector<int>> result; dfs(root, 0, result); return result; } ``` **复杂度分析**: - **时间复杂度**:$O(n)$,每个节点被访问一次。 - **空间复杂度**:$O(n)$,递归栈深度在最坏情况(树退化为链表)下为$O(n)$[^1]。 --- ### 关键点总结 | 方法 | 适用场景 | 空间复杂度优势 | |---------|----------------------|----------------------| | 迭代法 | 大规模数据、避免栈溢出 | 队列空间可控 | | 递归法 | 代码简洁、层级信息明确 | 依赖递归栈,可能溢出 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值