链式存储结构存储的二叉树,对树中结点进行逐个遍历时,由于是非线性结构,需要找到一种合适的方式遍历树中的每个结点。

递归思想遍历二叉树

之前讲过,树是由根结点和子树部分构建的,对于每一棵树来说,都可以分为 3 部分:左子树、根结点和右子树。所以,可以采用递归的思想依次遍历每个结点。

根据访问结点时机的不同,分为三种遍历方式:

  • 先访问根结点,再遍历左右子树,称为“先序遍历”;
  • 遍历左子树,之后访问根结点,然后遍历右子树,称为“中序遍历”;
  • 遍历完左右子树,再访问根结点,称为“后序遍历”。

图1 二叉树

三种方式唯一的不同就是访问结点时机的不同,给出一个二叉树,首先需要搞清楚三种遍历方式下访问结点的顺序。


图2 二叉树遍历示意图

图2 中,箭头线条的走势为遍历结点的过程:

先序遍历是只要线条走到该结点的左方位置时,就操作该结点。所以操作结点的顺序为:

1 2 4 5 3 6 7

中序遍历是当线条越过结点的左子树,到达该结点的正下方时,才操作该结点。所以操作结点的顺序为:

4 2 5 1 6 3 7

后序遍历是线条完全走过结点的左右子树,到达该结点的右方范围时,就开始操作该结点。所以操作结点的顺序为:

4 5 2 6 7 3 1

三种遍历方式的完整代码实现

#include <stdio.h>
#include <string.h>
#define TElemType int
//构造结点的结构体
typedef struct BiTNode{TElemType data;  //数据域struct BiTNode *lchild, *rchild;  //左右孩子指针
}BiTNode, *BiTree;//初始化树的函数
void CreateBiTree(BiTree *T){*T = (BiTNode*)malloc(sizeof(BiTNode));(*T)->data = 1;(*T)->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->data = 2;(*T)->lchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->lchild->rchild->data = 5;(*T)->lchild->rchild->lchild = NULL;(*T)->lchild->rchild->rchild = NULL;(*T)->rchild->data = 3;(*T)->rchild->lchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild->lchild->data = 6;(*T)->rchild->lchild->lchild = NULL;(*T)->rchild->lchild->rchild = NULL;(*T)->rchild->rchild = (BiTNode*)malloc(sizeof(BiTNode));(*T)->rchild->rchild->data = 7;(*T)->rchild->rchild->lchild = NULL;(*T)->rchild->rchild->rchild = NULL;(*T)->lchild->lchild->data = 4;(*T)->lchild->lchild->lchild = NULL;(*T)->lchild->lchild->rchild = NULL;
}//模拟操作结点元素的函数,输出结点本身的数值
void displayElem(BiTNode* elem){printf("%d ", elem->data);
}//先序遍历
void PreOrderTraverse(BiTree T){if (T)   {displayElem(T);//调用操作结点数据的函数方法PreOrderTraverse(T->lchild);//访问该结点的左孩子PreOrderTraverse(T->rchild);//访问该结点的右孩子}//如果结点为空,返回上一层return;
}//中序遍历
void INOrderTraverse(BiTree T){if (T)   {INOrderTraverse(T->lchild);//遍历左孩子displayElem(T);//调用操作结点数据的函数方法INOrderTraverse(T->rchild);//遍历右孩子}//如果结点为空,返回上一层return;
}//后序遍历
void PostOrderTraverse(BiTree T){if (T)   {PostOrderTraverse(T->lchild);  //遍历左孩子PostOrderTraverse(T->rchild);  //遍历右孩子displayElem(T);  //调用操作结点数据的函数方法}//如果结点为空,返回上一层return;
}int main() {BiTree Tree;CreateBiTree(&Tree);printf("前序遍历: \n");PreOrderTraverse(Tree);printf("\n中序遍历算法: \n");INOrderTraverse(Tree);printf("\n后序遍历: \n");PostOrderTraverse(Tree);
}

运行结果:
前序遍历:
1 2 4 5 3 6 7
中序遍历算法:
4 2 5 1 6 3 7
后序遍历:
4 5 2 6 7 3 1

总结

由于二叉树就是由根结点和左右子树构成的,所以很容易想到使用递归的思想。而递归算法的低层实现实际上使用的是栈的数据结构,所以二叉树的先序、中序和后序遍历同样可以使用非递归的算法实现。

非递归算法的具体实现可以查看下一节的内容。

转载于:https://www.cnblogs.com/ciyeer/p/9044259.html

数据结构34:二叉树前序遍历、中序遍历和后序遍历相关推荐

  1. 数据结构之---二叉树前序,中序,后序

    转载:https://blog.csdn.net/u013834525/article/details/80421684

  2. 二叉树前序,中序,后序遍历的迭代实现,实现思路及代码

    用Java描述数据结构之二叉树,前序遍历,中序遍历,后序遍历这篇博客中我介绍了二叉树的相关概念和递归实现的二叉树的前中后序遍历.今天来介绍非递归迭代版遍历的思路及实现代码. 首先我们要明白所谓遍历就是 ...

  3. 二叉树(前序,中序,后序,层序)遍历递归与循环的python实现

    二叉树的遍历是在面试使比较常见的项目了.对于二叉树的前中后层序遍历,每种遍历都可以递归和循环两种实现方法,且每种遍历的递归实现都比循环实现要简洁.下面做一个小结. 一.中序遍历 前中后序三种遍历方法对 ...

  4. 二叉树前序、中序、后序遍历求法

    二叉树前序.中序.后序遍历相互求法 二叉树的三种遍历方法: 前序遍历: 1.访问根节点 2.前序遍历左子树 3.前序遍历右子树 中序遍历: 1.中序遍历左子树 2.访问根节点 3.中序遍历右子树 后序 ...

  5. 二叉树前序、中序、后序遍历非递归写法的透彻解析

    前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历.递归写法,只要理解思想,几行代码.可是非递归写法却很不容易.这里特地总结下,透彻解析它们的非递归写法.其中,中序遍历的非递归写法最简 ...

  6. 数据结构之二叉树的前中后序遍历以及层序遍历

    学习目标:读完这篇博客搞定二叉树的前中后序以及层序遍历 首先:你应该明白什么是二叉树,下面这幅图就是一个完全二叉树 其实所谓的二叉树就是一个节点有小于等于二个分支的树,可以没有分支,可以有1条分支,可 ...

  7. 二叉树前序、中序、后序遍历-1

    目录 一.前序遍历: 二.中序遍历: 三.后序遍历: 四.使用递归方法进行遍历的代码: 五.使用非递归方法进行后序遍历 一.前序遍历: 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树.在遍历左. ...

  8. Python 递归式实现二叉树前序、中序、后序遍历

    记忆点: 前序:VLR 中序:LVR 后序:LRV 举例: 一颗二叉树如下图所示 则它的前序.中序.后序遍历流程如下图所示 前序遍历 class Solution:def preorderTraver ...

  9. 由前序序列与中序序列实现后序遍历

    二叉树是一种特殊的树,二叉树只有两个分支,分别是该节点的左儿子和右儿子. 前序遍历:就是先遍历根节点,然后再访问左子树与右子树.遍历子树的时候同样也是先遍历根节点然后在遍历他的左子树与右子树. 中序遍 ...

  10. 二叉树——前序和中序得到后序

    由二叉树的前序和中序如何得到二叉树的后序呢?要给出答案,首先得明白什么是前序.中序.后序. 二叉树前序:遍历顺序为,根节点.左子树.右子树:中序:遍历顺序为,左子树.根节点.右子树:后序:遍历顺序为, ...

最新文章

  1. Redis 笔记(11)— 文本协议 RESP(单行、多行字符串、整数、错误、数组、空值、空串格式、telnet 登录 redis)
  2. Xcode消除编译器警告
  3. [模拟]纺车的轮子 Spinning Wheels
  4. 2.2 Logistic 回归-深度学习-Stanford吴恩达教授
  5. c语言使用函数累加由n个a构成的整数之和,c 语言使用函数累加由n个a构成的整数之和...
  6. 【python零基础入门学习】Python入门,带你快速学习,Python 环境搭建
  7. Python抖音机器人制作!让你有看不完的小姐姐
  8. visualboyadvance滤镜_研究VisualBoyAdvance的请进
  9. python flask面试题_Flask面试题
  10. java面试基础篇--hashMap中如何解决hash冲突
  11. 网络安全商业模式分析
  12. linux 进程 清理,linux 如何清理僵尸进程
  13. 【Linux】返回上级目录
  14. FREQCON OVERSPEED 1.2 368U4 204S
  15. rono在oracle的作用_Oracle服务的作用
  16. 爬虫学习日记1-豆瓣top250电影信息爬取
  17. 正点原子mysql_正点原子战舰开发板硬件原理图与PCB
  18. python break怎么跳出两层循环(多层循环)?添加标志量
  19. 根据两个坐标系对应点计算转换关系(旋转和平移)
  20. 十进制有限小数如何以二进制保存而不会变成无限小数

热门文章

  1. Spark广播变量实现原理及基础编程
  2. Ansible roles角色详解
  3. k8s kubesphere安装在k8s中的基础环境准备(前提条件)
  4. intel lock汇编指令保障有序性
  5. Linux 管道使用示例
  6. Spring Cloud Stream如何消费自己生产的消息
  7. centos7.3安装tomcat报Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
  8. Qt QML实现阴影字体
  9. Linux 查看端口占用情况 并 结束进程
  10. 28 March 2019