二叉树的先序,中序,后序遍历

2023-11-17

java 二叉树的先序,中序,后序遍历
 

一、前序遍历

  访问顺序:先根节点,再左子树,最后右子树;上图的访问结果为:GDAFEMHZ。

  1)递归实现

public void preOrderTraverse1(TreeNode root) {
        if (root != null) {
            System.out.print(root.val + "->");
            preOrderTraverse1(root.left);
            preOrderTraverse1(root.right);
        }
    }
 

  2)非递归实现

public void preOrderTraverse2(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        while (node != null || !stack.empty()) {
            if (node != null) {
                System.out.print(node.val + "->");
                stack.push(node);
                node = node.left;
            } else {
                TreeNode tem = stack.pop();
                node = tem.right;
            }
        }
    }

二、中序遍历

  访问顺序:先左子树,再根节点,最后右子树;上图的访问结果为:ADEFGHMZ。

  1)递归实现

public void inOrderTraverse(TreeNode root) {
        if (root != null) {
            inOrderTraverse(root.left);
            System.out.print(root.val + "->");
            inOrderTraverse(root.right);
        }
    }

  2)非递归实现

public void inOrderTraverse(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        while (node != null || !stack.isEmpty()) {
            if (node != null) {
                stack.push(node);
                node = node.left;
            } else {
                TreeNode tem = stack.pop();
                System.out.print(tem.val + "->");
                node = tem.right;
            }
        }
    }

三、后序遍历

  访问顺序:先左子树,再右子树,最后根节点,上图的访问结果为:AEFDHZMG。

  1)递归实现

public void postOrderTraverse(TreeNode root) {
        if (root != null) {
            postOrderTraverse(root.left);
            postOrderTraverse(root.right);
            System.out.print(root.val + "->");
        }
    }

   2)非递归实现

方法1

public void postOrderTraverse(TreeNode root) {
        TreeNode cur, pre = null;

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.empty()) {
            cur = stack.peek();
            if ((cur.left == null && cur.right == null) || (pre != null && (pre == cur.left || pre == cur.right))) {
                System.out.print(cur.val + "->");
                stack.pop();
                pre = cur;
            } else {
                if (cur.right != null)
                    stack.push(cur.right);
                if (cur.left != null)
                    stack.push(cur.left);
            }
        }
    }

方法2

    public void thePostOrderTraversal_Stack(Node root) {   //后序遍历
        Stack<Node> stack = new Stack<Node>();
        Stack<Node> output = new Stack<Node>();//构造一个中间栈来存储逆后序遍历的结果
        Node node = root;
        while (node != null || stack.size() > 0) {
            if (node != null) {
                output.push(node);
                stack.push(node);
                node = node.getRightNode();
            } else {
                node = stack.pop();
                node = node.getLeftNode();
            }
        }
     
        while (output.size() > 0) {
 
            printNode(output.pop());
        }
    }

方法3

import java.util.*;
public class Solution {
    public int[] postorderTraversal (TreeNode root) {
        //添加遍历结果的数组
        List<Integer> list = new ArrayList(); 
        Stack<TreeNode> s = new Stack<TreeNode>();
        TreeNode pre = null;
        while(root != null || !s.isEmpty()){ 
            //每次先找到最左边的节点
            while(root != null){ 
                s.push(root);
                root = root.left;
            }
            //弹出栈顶
            TreeNode node = s.pop(); 
            //如果该元素的右边没有或是已经访问过
            if(node.right == null || node.right == pre){ 
                //访问中间的节点
                list.add(node.val); 
                //且记录为访问过了
                pre = node; 
            }else{
                //该节点入栈
                s.push(node); 
                //先访问右边
                root = node.right; 
            }
        }
        //返回的结果
        int[] res = new int[list.size()]; 
        for(int i = 0; i < list.size(); i++)
            res[i] = list.get(i);
        return res;
    }
}

 

四、层次遍历

  访问结果:GDMAFHZE。

public void levelOrderTraverse(TreeNode root) {
        if (root == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            System.out.print(node.val + "->");

            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
    }



C++ 二叉树的先序,中序,后序遍历

 三种遍历方式都分为递归与非递归的方式。三种遍历方式的递归思想相同。后序遍历非递归方法分为两种,具体见代码。

构造方式:

 1 #include<iostream>
 2 #include<stack>
 3 using namespace std;
 4 
 5 typedef struct BiTNode{
 6     char data;
 7     int lvisited,rvisited;//左、右孩子是否访问过,1表示已访问(此项只在后序非递归2算法中需要)
 8     struct BiTNode *lchild,*rchild;
 9 }BiTNode,*BiTree;
10 
11 void InitBiTree(BiTree &T)//构造空二叉树
12 {
13     T=NULL;
14 }
15 void CreateBiTree(BiTree &T)//生成二叉树
16 {
17     char ch;
18     cin>>ch;
19     if(ch=='0')//0代表空
20         T=NULL;
21     else
22     {
23         T=(BiTree)malloc(sizeof(BiTNode));//生成根结点
24         if(!T)
25         {
26             cout<<"生成结点错误!"<<endl;
27             return;
28         }
29         T->data=ch;
30         T->lvisited=0;
31         T->rvisited=0;
32         CreateBiTree(T->lchild);
33         CreateBiTree(T->rchild);
34     }
35 }

三种遍历方式代码:

  1 void PreOrder(BiTree T)//先序递归遍历
  2 {
  3     if(T!=NULL)
  4     {
  5         cout<<T->data<<" ";
  6         PreOrder(T->lchild);
  7         PreOrder(T->rchild);
  8     }
  9 }
 10 void SqlPreOrder(BiTree T)//先序非递归遍历
 11 {
 12     stack<BiTree> s;
 13     BiTree p=T;
 14     while(p || !s.empty())
 15     {
 16         if(p)
 17         {
 18             cout<<p->data<<" ";
 19             s.push(p);
 20             p=p->lchild;
 21         }
 22         else
 23         {
 24             p=s.top();
 25             p=p->rchild;
 26             s.pop();
 27         }
 28     }
 29 }
 30 
 31 
 32 
 33 void InOrder(BiTree T)//中序递归遍历
 34 {
 35     if(T!=NULL)
 36     {
 37         InOrder(T->lchild);
 38         cout<<T->data<<" ";
 39         InOrder(T->rchild);
 40     }
 41 }
 42 void SqInOrder(BiTree T)//中序非递归遍历
 43 {
 44     stack<BiTree> s;
 45     BiTree p=T;
 46     while(p || !s.empty())
 47         if(p)
 48         {
 49             s.push(p);
 50             p=p->lchild;
 51         }
 52         else
 53         {
 54             p=s.top();
 55             cout<<p->data<<" ";
 56             s.pop();
 57             p=p->rchild;
 58         }
 59 }
 60 
 61 
 62 
 63 void PostOrder(BiTree T)//后序递归遍历
 64 {
 65     if(T!=NULL)
 66     {
 67         PostOrder(T->lchild);
 68         PostOrder(T->rchild);
 69         cout<<T->data<<" ";
 70     }
 71 }
 72 
 73 //后序非递归遍历1思路:因为后序非递归遍历二叉树的顺序是先访问左子树,再访问后子树,最后
 74 //访问根结点。当用堆栈来存储结点,必须分清返回根结点时,是从左子树返回的,还是从右子树
 75 //返回的。所以,使用辅助指针r,其指向最近访问过的结点。
 76 void SqlPostOrder1(BiTree T)//后序非递归遍历1
 77 {
 78     stack<BiTree> s;
 79     BiTree p=T,r;
 80     while(p || !s.empty())
 81     {
 82         if(p)                             //走到最左边
 83         {
 84             s.push(p);
 85             p=p->lchild;
 86         }
 87         else                             //向右
 88         {
 89             p=s.top();//取栈顶结点
 90             if(p->rchild && p->rchild!=r)//如果右子树存在,且未被访问过
 91             {
 92                 p=p->rchild;
 93                 s.push(p);
 94                 p=p->lchild;             //再走到最左
 95             }
 96             else                         //否则,访问栈顶结点并弹出
 97             {
 98                 cout<<p->data<<" ";
 99                 r=p;                     //记录该结点
100                 s.pop();
101                 p=NULL;                     //结点访问完后,重置p指针
102             }
103         }
104     }
105 }
106 //思路2:在结点中增加标志域,记录是否已被访问。
107 void SqlPostOrder2(BiTree T)//后序非递归遍历2
108 {
109     stack<BiTree> s;
110     BiTree p=T;
111     while(p || !s.empty())
112     {
113         if(p && p->lvisited==0)                     //左走,且左子树未被访问
114         {
115             p->lvisited=1;
116             s.push(p);
117             p=p->lchild;
118         }
119         else
120         {
121             p=s.top();
122             if(p->rchild!=NULL && p->rvisited==0)//右子树未被访问,右走一步
123             {
124                 p->rvisited=1;
125                 p=p->rchild;
126             }
127             else                                 //访问栈顶元素并弹栈
128             {
129                 cout<<p->data<<" ";
130                 s.pop();
131                 if(!s.empty())
132                     p=s.top();
133                 else                             //当最后一个元素弹栈出去后,结束
134                     return ;
135             }
136         }
137     }
138 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树的先序,中序,后序遍历 的相关文章

  • 在 Spring Boot 中重新加载/刷新缓存

    我正在使用 Spring Boot 对于缓存 我使用 Ehcache 到目前为止一切正常 但现在我必须重新加载 刷新 那么我该如何执行此操作 以便我的应用程序不会出现任何停机时间 我在Spring Ehcache中尝试了很多方法 但它不起作
  • SWIG 类型映射 uint8_t* 从 C/C++ 到 java.nio.ByteBuffer

    我正在尝试将输入和输出缓冲区从 C 传递给 java 类 出于效率原因 我需要使用 ByteBuffer 这两个缓冲区都是在 C 部分中分配的 我需要将它们传递给一个 java 函数 该函数将使用输入缓冲区进行一些计算并将结果写入输出缓冲区
  • TestNG 启动期间发生内部错误

    我创建了一个 TestNG 类 FirstTest java 当我将测试用例作为 TestNG Test 运行时 出现以下错误 期间发生内部错误 启动 FirstTest java lang NullPointerException Ecl
  • 在游戏框架中编写功能测试的正确方法

    在为基于 play1 2 4 的 web 应用程序编写功能测试时 我对如何正确编码感到有点困惑 困惑在于所涉及的事务边界 我在某处读到每个测试都有自己的事务 在我的应用程序中 用户可以登录并向购物车添加一些商品 然后他可以提供一个地址 以便
  • 如何在 Android 中恢复我的音频?

    我必须实现用于创建具有暂停和恢复状态的音频的应用程序 当我的应用程序作为启动时音频启动 当我按下模拟器上的后退按钮时 音频音乐处于暂停状态 但是当我的活动回来时从停止状态到前台我的音频音乐未恢复 这是我的代码 public class Au
  • 如何向 OkHttp 请求拦截器添加标头?

    我将这个拦截器添加到我的 OkHttp 客户端 public class RequestTokenInterceptor implements Interceptor Override public Response intercept C
  • 使用不同的组合器和累加器进行流缩减的示例

    问题是关于java util stream Stream reduce U identity BiFunction
  • Spring boot 404错误自定义错误响应ReST

    我正在使用 Spring boot 来托管 REST API 即使浏览器正在访问 URL 以及自定义数据结构 我也希望始终发送 JSON 响应 而不是使用标准错误响应 我可以使用 ControllerAdvice 和 ExceptionHa
  • Java - 了解 PrintWriter 和刷新的需要

    好吧 首先我对所有代码表示歉意 但我觉得代码太多总比代码不够好 我正在制作一个简单的聊天客户端和印刷机 尤其是我正在努力解决的问题 使用现在的代码 它将与服务器类交互 并且完美地打印我想要打印的内容 但是 当我删除 writer flush
  • BigDecimal 中 Divide 方法的 Scale()

    new BigDecimal 37146555 53880000 divide new BigDecimal 1000000 scale 这返回10 但根据API divide method 返回一个 BigDecimal 其值为 这个 除
  • IntelliJ 建议错误的 @NotNull 注释

    IntelliJ 建议导入com sun istack internal NotNull以下程序中的 NotNull 注释 这是错误的 public class Test implements Comparable
  • Android Google 地图:隐藏整个地图的多边形或形状

    我试图隐藏除一个区域之外的整个地图 因为我使用的多边形在我想要显示的区域中有一个洞 问题在于 根据缩放的不同 空白区域会被多边形的颜色覆盖 或者多边形会失去其颜色 这是代码 polygon hide all world map float
  • 为什么 Cassandra 客户端在生产中没有 epoll 时会失败? [复制]

    这个问题在这里已经有答案了 当我在本地运行服务时 我收到一条警告 指出 epoll 不可用 因此它使用 NIO 很公平 当我将其部署到 Kubernetes 中时 我得到了以下信息 这导致服务无法运行 2017 03 29T19 09 22
  • 错误:列“this_.phitorsionangle”必须出现在 GROUP BY 子句中或在聚合函数中使用

    我在执行 sql 查询时遇到了一些问题 我正在使用 Hibernate Criteria 来构建查询 我通过按一定间隔 binSize 舍入值然后对它们进行分组来从数据库创建一些容器 当我直接在 SQL 中使用查询尝试时 效果非常好 SEL
  • JavaFX 8 默认消息图标

    随着 JavaFX 的最近几次更新 我们收到了警报 我想获取消息的默认图标 错误 警告 在Swing中 我可以通过一些方式获取L F消息图标UIManager的属性 如何在 JavaFX 中获取消息的默认图标 它们是包含在属性中 还是由 C
  • 飞碟 - html 实体未呈现

    我正在使用 Flying saucer lib 生成 pdf 但我对一些 html 实体有问题 我已经在寻找解决方案 我在这个论坛和其他地方找到了很多提示 但仍然存在问题 我尝试过这种方法 http sdtidbits blogspot c
  • 使用 OpenNLP 获取句子的解析树。陷入困境。

    OpenNLP 是一个关于自然语言处理的 Apache 项目 NLP 程序的目标之一是解析一个句子 并给出其语法结构的树 例如 天空是蓝色的 这句话 可能会被解析为 S NP VP The sky is blue where S是句子 NP
  • 从 IntelliJ 运行 JavaFX 应用程序

    Versions openjdk版本 11 0 11 2021 04 20 OpenJDK 运行时环境 build 11 0 11 9 Ubuntu 0ubuntu2 20 10 OpenJDK 64 位服务器虚拟机 内部版本 11 0 1
  • JavaFX 中的 MVC 模式与场景生成器

    我是 JavaFX 新手 根据我当前的设置 正在努力创建合适的 MVC 架构 我使用 Scene Builder 单击了一个 UI 并指定了一个 Controller 类 Startup public class Portal extend
  • 是什么让热部署成为“难题”?

    在工作中 我们经常遇到这样的问题 永久代内存不足 http www jroller com agileanswers entry preventing java s java lang例外 团队负责人认为这是 JVM 中的一个错误 与代码的

随机推荐

  • cgo+gSoap+onvif学习总结:1、方案初衷、资料收集及cgo实现helloworld

    cgo gSoap onvif学习总结 1 方案初衷 资料收集及cgo实现helloworld 文章目录 cgo gSoap onvif学习总结 1 方案初衷 资料收集及cgo实现helloworld 1 前言 2 资料收集 3 cgo h
  • Keil转STM32CubeIDE工程移植问题记录

    Keil转STM32CubeIDE工程移植问题记录 1 编译报错问题处理 2 工程相关配置问题 3 调试器配置 从Keil软件转战STM32CubeIDE 转换的过程中遇到了不少问题 在此记录一下 防止以后再踩坑 也给同样有转软件需求的朋友
  • 老派程序员——徒手实现伟大成就

    原文地址 http www csdn net article 2012 08 06 2808178 摘要 本文介绍了三位非常著名的程序员 Ken Thompson Joe Armstrong 和 Jamie Zawinski 他们是如何发明
  • Java中的Set集合接口实现插入对象不重复的原理

    java lang Object中对hashCode的约定 1 在一个应用程序执行期间 如果一个对象的equals方法做比较所用到的信息没有被修改的话 则对该对象调用hashCode方法多次 它必须始终如一地返回同一个整数 2 如果两个对象
  • litemall项目部署,启动后台前端cnpm install报错

    在命令窗口切换到C test file litemall litemall admin目录输入cnpm install 出现报错 1 将node modules 文件删除 2 在命令窗口切换到C test file litemall lit
  • 局域网下远程唤醒主机

    Linux下远程唤醒 Linux下唤醒远程主机使用的命令主要是 wakeonlen 安装 apt get install wakeonlen 使用命令为 wakeonlen AC 48 11 Windows下远程唤醒 Windows下主要的
  • 配置Nginx以隐藏访问端口

    进入usr local nginx conf 编辑nginx conf文件 在http模块中加入下句 include vhost conf 进入usr local nginx conf vhost xxx conf 编写如下内容 nginx
  • Maven依赖仓库

    Maven依赖仓库
  • Linux的目录切换和用户管理

    切换目录 在使用linux系统的时候 会用cd来切换目录 cd 切换到根目录 cd 切换到主目录 cd 切换到之前工作目录 cd 虽然很方便但只能保存一次目录 pushd命令使用目录堆栈可以把多个目录存放起来 配套使用pushd popd
  • android实现共享数据

    计划是在后台开个service定位服务 前台需要经纬度的时候 从service获取 实现过程如下 public GPSService minTime UnTaskCheckingActivity minTime minDistance Un
  • mpc模型预测控制从原理到代码实现 mpc模型预测控制详细原理推导 matlab和c++两种编程实现

    mpc模型预测控制从原理到代码实现 mpc模型预测控制详细原理推导 matlab和c 两种编程实现 四个实际控制工程案例 双积分控制系统 倒立摆控制系统 车辆运动学跟踪控制系统 车辆动力学跟踪控制系统 包含上述所有的文档和代码 ID 564
  • 接口自动化平台(三):Promise简介 + 前端 + 后端 + 联调

    目录 1 Promise 2 接口自动化平台前端开发 2 1 前端环境搭建 2 2 新建用例页 CreateCase 2 2 1 增加路由信息 config routes ts 2 2 2 增加对应后端接口的信息 config proxy
  • 启动项

    size medium 1 imjpmig exe是微软Microsoft输入法编辑器程序 是微软Microsoft输入法编辑器程序 我给禁用了 每什么影响似乎 2 ctfmon exe是Microsoft Office产品套装的一部分 提
  • Docker运行MySQL5.7

    步骤如下 1 获取镜像 docker pull mysql 5 7 2 创建挂载目录 mkdir home mydata data mkdir home mydata log mkdir home mydata conf 3 先启动dock
  • FreeRTOS笔记(二)

    FreeRTOS笔记 二 静态任务 文章目录 FreeRTOS笔记 二 静态任务 一 任务定义 二 任务创建 2 1 定义任务栈 2 2 定义任务函数 2 3 定义任务控制块 2 4 实现任务创建函数 三 实现就绪列表 3 1 定义就绪列表
  • PCL去除地面

    如图所示 分别是 原图 gt 直通滤波后 gt 取地面的图 gt 取地面的凹凸四边行加地面上的物体图
  • C++初学知识点总结

    C 学习笔记 1 namespace 所谓的namespace就是指标识符的各种可见范围 C 标准程序中的所有标识符都被定义于一个名为std的namespace中 2 iostream与iostream h的差别 差别当然不只是一个带后缀
  • redis做计数器相关

    最近在准备晋升PPT 发现品牌粉丝数和新浪微博的计数本质一样 哎 之前就发现了 就是没深入 要深入啊 品牌粉丝数设计相关 a Redis在计数器场景上的应用 http www searchdatabase com cn showconten
  • Unity SpriteAtlas实战使用

    前言 图集计划使用sprite atlas 但是看了网上资料用于实战的有点少 自己总结下 Unity 版本2019 4 9f1 图集设置 Sprite Packer Mode Disabled 就是不会生成图集 Enable For Bui
  • 二叉树的先序,中序,后序遍历

    java 二叉树的先序 中序 后序遍历 一 前序遍历 访问顺序 先根节点 再左子树 最后右子树 上图的访问结果为 GDAFEMHZ 1 递归实现 public void preOrderTraverse1 TreeNode root if