二叉树前、中、后、层序遍历(递归和循环实现)

2 篇文章 0 订阅
订阅专栏
2 篇文章 0 订阅
订阅专栏

给定如下一棵二叉查找树(二叉排序树)
在这里插入图片描述
树结构:

public class Tree {
    public int data;
    //左孩子
    public Tree lchild;
    //右孩子
    public Tree rchild;
 }

下面的分别通过递归循环两种方法实现二叉树的前序、中序、后序、层序遍历。
注意:前、中、后序遍历都是针对根结点而言。

(1)前序遍历

遍历顺序
  1. 访问根节点;
  2. 前序遍历左子树;
  3. 前序遍历右子树。

特点:(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 )

递归实现:
/**
 * 前序遍历,递归实现
 * @param root
 * @return
 */
public void preorderTraversal(Tree root) {
    if (root == null) {
        return;
    }

    System.out.print(root.data + " ");
    preorderTraversal(root.lchild);
    preorderTraversal(root.rchild);
}
循环实现:

用栈来保存先前走过的路径,以便可以在访问完子树后,
可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作。

public void preorderTraversalIteration(Tree root) {
     Stack<Tree> stack = new Stack<>();
     while (root != null || !stack.isEmpty()) {
         while (root != null) {
             System.out.print(root.data + " ");
             stack.push(root);
             root = root.lchild;
         }
         if (!stack.isEmpty()) {
             root = stack.pop();
             root = root.rchild;
         }
     }
}
图解说明:

在这里插入图片描述
输出结果:4 2 1 3 6 5 7

(2)中序遍历

遍历顺序
  1. 中序遍历左子树;
  2. 访问根节点;
  3. 中序遍历右子树。

特点:(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)

递归实现:
/**
 * 中序遍历,递归实现
 * @param root
 */
public void inOrderTraversal(Tree root) {
    if (root == null) {
        return;
    }

    inOrderTraversal(root.lchild);
    System.out.print(root.data + " ");
    inOrderTraversal(root.rchild);
}
循环实现:
public void inOrderTraversalIteration(Tree root) {
    Stack<Tree> stack = new Stack<>();
    while (root != null || !stack.isEmpty()) {
        while (root != null) {
            stack.push(root);
            root = root.lchild;
        }
        if (!stack.isEmpty()) {
            root = stack.pop();
            System.out.print(root.data + " ");
            root = root.rchild;
        }
    }
}
图解说明:

在这里插入图片描述
输出结果:1 2 3 4 5 6 7

(3)后序遍历

遍历顺序
  1. 后序遍历左子树;
  2. 后续遍历右子树;
  3. 访问根节点。

特点:(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)

递归实现:
/**
 * 后序遍历,递归实现
 * @param root
 */
public void postOrderTraversal(Tree root) {
    if (root == null) {
        return;
    }

    postOrderTraversal(root.lchild);
    postOrderTraversal(root.rchild);
    System.out.print(root.data + " ");
}
循环实现:

    后序遍历的非递归算法是三种顺序中最复杂的
原因在于:
    后序遍历是先访问左、右子树,再访问根节点,而在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点,如果从左子树回退到根节点,此时就应该去访问右子树,而如果从右子树回退到根节点,此时就应该访问根节点。
    所以相比前序和后序,必须得在压栈时添加信息,以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作。

public void postOrderTraversalIteration(Tree root) {
   //用于表示是从左子树返回到父结点
   int left = 1;
   //用于表示是从右子树返回到父结点
   int right = 2;
   //用于存放树结点
   Stack<Tree> treeStack = new Stack<>();
   //用于存放是从左子结点还是右子结点返回父结点的标记
   Stack<Integer> markStack = new Stack<>();

   while (root != null || !treeStack.empty()) {
       while (root != null) {
           //将结点压栈并标记为左节点
           treeStack.push(root);
           markStack.push(left);
           root = root.lchild;
       }

       while (!treeStack.empty() && markStack.peek() == right) {
           //如果是从右子结点返回到父结点,直接输出
           markStack.pop();
           System.out.print(treeStack.pop().data + " ");
       }
       if (!treeStack.empty() && markStack.peek() == left) {
           //如果是从左子结点返回到父结点,标记为右结点,并对右结点进行操作
           markStack.pop();
           markStack.push(right);
           root = treeStack.peek().rchild;
       }
   }
}
图解说明:

在这里插入图片描述
输出结果:1 3 2 5 7 6 4

(4)层序遍历

遍历顺序

    由根结点向下,从左到右一层一层的遍历;

递归实现:
public void sequenceTraversal(Tree root) {
    if (root == null) {
        return;
    }
    int deep = deep(root);
    for (int i = 1; i <= deep; i++) {
        seqTraversal(root, i);
    }
}

private void seqTraversal(Tree root, int level) {
    if (root == null || level < 1) {
        return;
    }

    if (level == 1) {
        System.out.print(root.data + " ");
        return;
    }
    //左子树
    seqTraversal(root.lchild, level - 1);
    //右子数
    seqTraversal(root.rchild, level - 1);
}

/**
 * 计算树的深度
 * @param root
 * @return
 */
public int deep(Tree root) {
    if (root == null) {
        return 0;
    }

    int left = deep(root.lchild);
    int right = deep(root.rchild);

    return (left > right) ? (left + 1) : (right + 1);
}
循环实现:

通过队列辅助实现

  • 1.对于不为空的结点,先把该结点加入到队列中
  • 2.从队中拿出结点,如果该结点的左右结点不为空,就分别把左右结点加入到队列中
  • 3.重复以上操作直到队列为空
/**
 * 层序遍历,迭代实现
 * @param root
 */
public void sequenceTraversalIteration(Tree root) {
    if (root == null) {
        return;
    }
    LinkedList<Tree> treeQueue = new LinkedList<>();
    treeQueue.add(root);
    Tree currentNode = null;
    while (!treeQueue.isEmpty()) {
        //移除并返问队列头部的元素
        currentNode = treeQueue.poll();
        System.out.print(currentNode.data + " ");
        if (currentNode.lchild != null) {
            treeQueue.add(currentNode.lchild);
        }
        if (currentNode.rchild != null) {
            treeQueue.add(currentNode.rchild);
        }
    }
}

图解说明:
在这里插入图片描述
输出结果:4 2 6 1 3 5 7

总结

  1. 前序、中序、后序遍历都是基于==DFS(深度优先)==思想,所以在用循环实现的时候借助辅助空间栈来解决。
  2. 层序遍历基于==BFS(广度优先)==思想,所以在循环实现的时候借助队列来实现。
层次遍历的递归实现 Java
r'q'x't 的博客
05-13 2652
定义一个全局的二维列表。 二维列表的索引就是该元素所位于的层数。例如:索引 0,代表位于第0层(即根节点所在层)。 递归的时候,多加一个参数(当层+1)即可。
二叉树后序以及层序遍历递归与非递归方法实现
tensor329的博客
04-01 672
1.序遍历 序遍历是二叉树遍历的一种方式,也称做先序遍历。其遍历规则为:根节点→左子树→右子树。以下分别以递归和非递归的方法实现二叉树序遍历。 1.1 递归方法 class Solution { List<Integer> res=new ArrayList<>(); public List<Integer> preorderTraversal(TreeNode root) { if(root!=null){
二叉树层序遍历递归与非递归_二叉树层序遍历及应用
weixin_39696518的博客
11-24 205
二叉树的遍历实质问题就是,将二维结构线性化。深度优先遍历对应的是序、序、后续遍历;广度优先对应的是层序遍历。看完后闭着眼写出二叉树的四种遍历结果 这篇文章从形象化方面描述了深度优先遍历;当我们说递归时,到底是在说什么 这篇文章则详细分析了序遍历对栈的使用过程。今天深入学习一下层序遍历层序遍历也是面试出现频率较多的一个知识点。如下二叉树,它的层序遍历结果为:1 - 2 - 5 - 3 - ...
数据结构(六)—— 二叉树(下)
最新发布
weixin_72703349的博客
09-09 407
层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。NLR:序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。LRN:后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点。LNR:序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树。
二叉树遍历-层序-递归
he_xin2009的专栏
04-14 2469
二叉树遍历、层序遍历:从上往下,从左到右。使用广度优先搜索算法
LeetCode--树的层序遍历递归法dfs 队列 BFS)
weixin_41563161的博客
10-20 728
树的层序遍历 目录 树的层序遍历 1N叉树的层序遍历递归法) 代码 队列(广度优先遍历) 2二叉树的锯齿形层次遍历(dfs 队列 BFS)...
二叉树的锯齿形层序遍历[分层遍历方式之一 -> 序遍历+level]
qq_43164662的博客
06-28 355
层次遍历是操作树的基础,而分层遍历就是层次遍历的变体,一般可用队列+层size来分层,也可以递归遍历+level来分层。通过锯齿形分层遍历二叉树来练习序遍历+level来分层。
Java实现二叉树常用操作【序建树,递归递归遍历及层序遍历
08-28
Java实现二叉树常用操作是指使用Java语言来实现二叉树的各种操作,包括序建树、递归递归遍历、层序遍历等。下面我们将详细介绍这些操作的实现方法。 一、序建树 序建树是指从一个数组构建一个...
二叉树遍历算法(递归实现+层次遍历)
irabbit756的博客
08-23 3972
二叉树遍历算法 二叉树的存储结构 typedef struct BTNode { char data; //这里默认结点data为char型 struct BTNode *lchild; struct BTNode *rchild; }BTNode; 二叉树的遍历算法 1 先序遍历 先序遍历的操作如下。 如果二叉树为空树,则什么都不做;否则: 1)访问根节点 2)先序遍历左子树 3)先序遍历右子树 描述如下: void preorder(BTNode *p) { if(p
二叉树及其基本操作(一)(C语言递归实现层序遍历
小心眼儿猫的博客
04-30 1717
树的概念: 由N(N&gt;=0)个节点构成的集合,对于N&gt;1的树,有: 1、有一个特殊的节点,称为根节点,根节点没有驱节点 2、除根节点外其余节点被分成M(M&gt;0)个互不相交的集合T1,T2……Tm,其每一个集合Ti(1&lt;=i&lt;=m) 是一棵结构与树类似的子树,每棵子树的根节点有且只有一个驱,可以有0个或多个后继 因此,树是递归定义的。 ...
C++二叉树递归实现各种遍历
qq_63058205的博客
11-12 1173
C++实现二叉树的如下操作: (1)初始化二叉链表:理解扩展二叉树及其序遍历序列; (2)序遍历二叉链表(递归实现); (3)序遍历二叉链表(递归实现); (4)后序遍历二叉链表(递归实现); (5)层序遍历二叉链表; (6)销毁二叉链表(递归实现)。
图解循环实现二叉树序遍历
圆圆的汤圆的博客
05-30 3175
01 二叉树序遍历回顾 我们知道,二叉树有三类节点,父节点,左孩子节点,右孩子节点。序遍历的意思就是先遍历父节点,之后左孩子节点,右孩子节点。 补充:序和后序遍历都是针对父节点的说法,父节点间遍历,父节点最后遍历。左右孩子节点的便利顺序大体上不变。 02 图解遍历过程 如果已经了解序遍历的过程,可以跳过这个部分。 (1)如下图,遍历节点0 (2)如下图,...
使用循环的方式遍历二叉树
yrc_Note的博客
09-26 3238
一、基本概念每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。 性质: 1、非空二叉树的第n层上至多有2^(n-1)个元素。 2、深度为h的二叉树至多有2^h-1个结点。 满二叉树:所有终端都在同一层次,且非终端结点的度数为2。 在满二叉树若其深度为h,则其所包含的结点数必为2^h-1。 完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集在左面
循环实现二叉树的后序遍历
圆圆的汤圆的博客
06-02 2663
01 二叉树的后序遍历回顾 遍历顺序是左孩子节点,右孩子节点,根节点,遍历结果是 3,4,1,7,5,6,2,0 如果你不理解树结构的遍历过程,可以这么想象下 (1)0来说它的左孩子和右孩子分别是如下图: 0的左孩子A 0的右孩子B 左、右孩子又是一颗单独的树A,B (2)后续遍历A得:3,4,1 (3)B的左子树,还可以再次拆分为C C (4)遍历C...
循环遍历二叉树
Tybyqi的博客
11-05 904
序遍历 struct Node { Node*left; Node*right; int data; Node(){ func; } }; Node* create(Node*p, int depth) { if (p &amp;&amp; depth) { p-&gt;left = new Node; p-&gt;right = new Node; p-&...
递归层序遍历
m0_37635053的博客
04-26 287
递归层序遍历
二叉树层序遍历分层[递归迭代两种思想+三种解法]
qq_43164662的博客
05-03 1386
层序遍历作为二叉树遍历的基本遍历,一般来说只能用迭代来解。但是分层输出则既可用迭代,又可配合level用序遍历来解。
二叉树、后、层次遍历(递归算法)
weixin_61756086的博客
01-01 106
一、序遍历递归算法 struct Tree{ int data; Tree *lchild,*rchild; } int pretree(Tree T){ if(T==NULL) return 0; cout<<T->data; pretree(T->lchild); pretree(T->rchild); return 0; } 二、序遍历递归算法 int mintree(Tree T){
二叉树循环遍历
Maple1997的博客
03-06 739
下面是基于栈的二叉树循环遍历代码:#include &lt;stack&gt; #include &lt;queue&gt; #define New(type) (type*)malloc(sizeof(type)) struct BinaryTreeNode { int value; struct BinaryTreeNode *left; struct BinaryTreeNode *r...
C语言非递归的方法实现对给定二叉树的先序和层序遍历算法。
03-29
先序遍历:使用栈来实现递归的先序遍历,从根节点开始,先将根节点入栈,然后进入循环,每次从栈弹出一个节点,打印该节点的值,并将其右子节点和左子节点依次入栈(注意先入右子节点再入左子节点),直到栈为空。 层序遍历:使用队列来实现递归层序遍历,从根节点开始,先将根节点入队列,然后进入循环,每次从队列弹出一个节点,打印该节点的值,并将其左子节点和右子节点依次入队列,直到队列为空。 代码实现如下: 先序遍历: ```c void PreOrderTraversal(BiTree T) { if(T == NULL) return; Stack S; InitStack(&S); Push(&S, T); while(!StackEmpty(&S)) { BiTree p; Pop(&S, &p); printf("%c ", p->data); if(p->rchild) Push(&S, p->rchild); if(p->lchild) Push(&S, p->lchild); } } ``` 层序遍历: ```c void LevelOrderTraversal(BiTree T) { if(T == NULL) return; Queue Q; InitQueue(&Q); EnQueue(&Q, T); while(!QueueEmpty(&Q)) { BiTree p; DeQueue(&Q, &p); printf("%c ", p->data); if(p->lchild) EnQueue(&Q, p->lchild); if(p->rchild) EnQueue(&Q, p->rchild); } } ```
96
原创
79
点赞
324
收藏
47
粉丝
关注
私信
写文章

热门文章

  • Java计时器 26698
  • SQL语句判断奇偶数 23135
  • GitHub创建项目的流程 10701
  • SQL时间和修改操作 7735
  • 用npm安装css-loader和style-loader出错 5247

分类专栏

  • 前端
  • webpack 2篇
  • JavaScript 1篇
  • 框架 3篇
  • SpringCloud 7篇
  • SpringBoot 5篇
  • Git 2篇
  • 大数据 1篇
  • 操作系统 6篇
  • 数据库 4篇
  • 中间件
  • 微服务 13篇
  • IDEA 2篇
  • 摘录
  • 数据结构 2篇
  • 算法 61篇
  • 2篇
  • 链表 4篇
  • 二分法 3篇
  • 递归 5篇
  • 回溯算法 5篇
  • 动态规划 3篇
  • 错误记录 6篇
  • Nginx 1篇
  • Java 24篇

最新评论

  • IDEA源码下载失败问题

    qq_39683071: 感谢,帮大忙,

  • 查询结果不存在返回NULL

    汤姆的猫与狗: 没太理解,什么情况下聚合函数会返回NULL呢,结果集为空还是什么?原理是什么?

  • 查询结果不存在返回NULL

    一只茶壶: 使用聚合函数对结果集进行聚合就会返回NULL

  • 查询结果不存在返回NULL

    汤姆的猫与狗: 是因为没limit?

  • 查询结果不存在返回NULL

    汤姆的猫与狗: 所以是为什么呢

最新文章

  • CountDownLatch 和 CyclicBarrier的区别与详解
  • IDEA源码下载失败问题
  • UML基础模型
2023年7篇
2022年17篇
2021年54篇
2020年17篇
2019年13篇
2018年2篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家春节商场美陈江苏秋季商场美陈市场报价成都玻璃钢雕塑厂家工厂商丘玻璃钢卡通雕塑生产厂家仿真玻璃钢雕塑代理价格泰州灰色玻璃钢花盆河南多彩玻璃钢雕塑图片浮雕红砂玻璃钢雕塑深圳熊猫玻璃钢卡通雕塑广州猪玻璃钢雕塑玻璃钢革命人物雕塑价格商场美陈彩球玻璃钢爆笑虫子雕塑商场活动室外美陈玻璃钢果篮雕塑报价玻璃钢跟树脂做的雕塑那个好嘉兴玻璃钢仿铜雕塑定制价格促销山羊玻璃钢雕塑出口玻璃钢形象雕塑镇江球形玻璃钢花盆佳木斯玻璃钢商场美陈玻璃钢白胚雕塑玻璃钢仿铜天鹅雕塑安徽户外长方形玻璃钢花盆四川商场节庆美陈雕塑定制玻璃钢花盆会碎吗扬州室内玻璃钢雕塑河南商场美陈厂家供应成套玻璃钢花盆图片大全 室外十二生肖玻璃钢雕塑品牌香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化