当前位置:   article > 正文

数据结构学习——树形结构之递归遍历二叉树

递归遍历二叉树

目录

一. 什么是二叉树

二. 二叉树分类

2.1、完全二叉树

2.2、满二叉树 

2.3、扩充二叉树

2.4、平衡二叉树

三. 二叉树的应用场景

四. 遍历方式

五. 为什么要研究遍历

六. 前序遍历

七. 中序遍历

八. 后序遍历

九. 数据结构专栏


一. 什么是二叉树

二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”。


二. 二叉树分类

2.1、完全二叉树

  • 若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
  • 一维数组可以作为完全二叉树的存储结构,堆排序使用的数据结构就是完全二叉树。

2.2、满二叉树 

  • 国际标准定义是除了叶结点外每一个结点都有左右子结点的二叉树

  • 国内的定义是:除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。很显然,按照这个定义,上面的图示二叉树就不是满二叉树。

2.3、扩充二叉树

  • 扩充二叉树是对已有二叉树的扩充,扩充后的二叉树的节点都变为度数为2的分支节点。也就是说,如果原节点的度数为2,则不变,度数为1,则增加一个分支,度数为0的叶子节点则增加两个分支。

2.4、平衡二叉树

  • 是一棵空树或它的任意节点的左右两个子树的高度差的绝对值不超过1


三. 二叉树的应用场景

  • 普通的二叉树,很难构成现实的应用场景,但因其简单,常用于学习研究,平衡二叉树则是实际应用比较多的。常见于快速匹配、搜索等方面。
  • 常用的树有:AVL树、红黑树、B+树、Trie(字典)树。
    1、AVL树: 最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树。
    2、红黑树: 平衡二叉树,广泛用在C++的STL中。如map和set都是用红黑树实现的。还有Linux文件管理。
    3、B/B+树: 用在磁盘文件组织 数据索引和数据库索引。
    4、Trie树(字典树): 用在统计和排序大量字符串,如自动机、M数据库索引。

四. 遍历方式

  • 前序遍历:root -> left -> right
  • 中序遍历:left -> root -> right
  • 后序遍历:left ->right -> root
  • 已知后序遍历和中序遍历,能确定前序遍历(也就是可以唯一确定一颗二叉树)。
  • 已知前序遍历和中序遍历,能确定后序遍历(也就是可以唯一确定一颗二叉树)。

五. 为什么要研究遍历

        当我们介绍数组、链表时,为什么没有着重研究他们的遍历过程呢?

        二叉树的遍历又有什么特殊之处?

        在计算机程序中,遍历本身是一个线性操作。所以遍历同样具有线性结构的数组或链表,是一件轻而易举的事。反观二叉树,是典型的非线性数据结构,遍历时需要把非线性关联的节点转化成一个线性的序列,以不同的方式来遍历,遍历出的序列顺序也不同。

        那么,二叉树都有哪些遍历方式呢?

        从节点之间位置关系的角度来看,二叉树的遍历分为3种。

  • 前序遍历。
  • 中序遍历。
  • 后序遍历。

六. 前序遍历

        前序遍历(DLR,lchild,data,rchild),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问 根结点,然后遍历左子树,最后遍历右子树。

二叉树为空则结束返回,否则:
(1)访问根结点。
(2)前序遍历左子树 。
(3)前序遍历右子树 。
需要注意的是:遍历左右子树时仍然采用前序遍历方法。

如图所示:

前序遍历结果:ABDECF
     其实在遍历二叉树的时候有三次遍历, 比如前序遍历:A->B->D->D(D左子节点并返回到D)->D(D右子节点并返回到D)->B->E->E(左)->E(右)->->B->A->C->F->F(左)->F(右)->C->C(右),可以用递归的方式,递归的输出当前节点,然后递归的输出左子节点,最后递归的输出右子节点。直接看代码更能理解:

  1. package test0910;
  2. public class Test {
  3. public static void main(String[] args) {
  4. TreeNode[] node = new TreeNode[10];// 以数组形式生成一棵完全二叉树
  5. for (int i = 0; i < 10; i++) {
  6. node[i] = new TreeNode(i);
  7. }
  8. for (int i = 0; i < 10; i++) {
  9. if (i * 2 + 1 < 10)
  10. node[i].left = node[i * 2 + 1];
  11. if (i * 2 + 2 < 10)
  12. node[i].right = node[i * 2 + 2];
  13. }
  14. preOrderRe(node[0]);
  15. }
  16. public static void preOrderRe(TreeNode biTree) {
  17. if (biTree == null)
  18. return;
  19. else {
  20. System.out.print(biTree.value + " ");
  21. preOrderRe(biTree.left);
  22. preOrderRe(biTree.right);
  23. }
  24. }
  25. }
  26. //节点结构
  27. class TreeNode {
  28. int value;
  29. TreeNode left;
  30. TreeNode right;
  31. TreeNode(int value) {
  32. this.value = value;
  33. }
  34. }

七. 中序遍历

        中序遍历(LDR)是 二叉树遍历的一种,也叫做 中根遍历、中序周游。在二叉树中,先左后根再右。巧记:左根右。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树
二叉树为空则结束返回,
否则:
(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树

如图所示:

中序遍历结果:DBEAFC

  1. public class Test {
  2. public static void main(String[] args) {
  3. TreeNode[] node = new TreeNode[10];// 以数组形式生成一棵完全二叉树
  4. for (int i = 0; i < 10; i++) {
  5. node[i] = new TreeNode(i);
  6. }
  7. for (int i = 0; i < 10; i++) {
  8. if (i * 2 + 1 < 10)
  9. node[i].left = node[i * 2 + 1];
  10. if (i * 2 + 2 < 10)
  11. node[i].right = node[i * 2 + 2];
  12. }
  13. midOrderRe(node[0]);
  14. }
  15. public static void midOrderRe(TreeNode biTree) {
  16. // 中序遍历递归实现
  17. if (biTree == null)
  18. return;
  19. else {
  20. midOrderRe(biTree.left);
  21. System.out.print(biTree.value + " ");
  22. midOrderRe(biTree.right);
  23. }
  24. }
  25. }
  26. // 节点结构
  27. class TreeNode {
  28. int value;
  29. TreeNode left;
  30. TreeNode right;
  31. TreeNode(int value) {
  32. this.value = value;
  33. }
  34. }

八. 后序遍历

        后序遍历(LRD)是 二叉树遍历的一种,也叫做 后根遍历、后序周游,可记做左右根。后序遍历有 递归算法和非递归算法两种。在二叉树中,先左后右再根。巧记:左右根。
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:
二叉树为空则结束返回,
否则: 
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点

如图所示:

后序遍历结果:DEBFCA

  1. public class Test {
  2. public static void main(String[] args) {
  3. // 以数组形式生成一棵完全二叉树
  4. TreeNode[] node = new TreeNode[10];
  5. for (int i = 0; i < 10; i++) {
  6. node[i] = new TreeNode(i);
  7. }
  8. for (int i = 0; i < 10; i++) {
  9. if (i * 2 + 1 < 10)
  10. node[i].left = node[i * 2 + 1];
  11. if (i * 2 + 2 < 10)
  12. node[i].right = node[i * 2 + 2];
  13. }
  14. postOrderRe(node[0]);
  15. }
  16. public static void postOrderRe(TreeNode biTree) {
  17. // 后序遍历递归实现
  18. if (biTree == null) {
  19. return;
  20. } else {
  21. postOrderRe(biTree.left);
  22. postOrderRe(biTree.right);
  23. System.out.print(biTree.value + " ");
  24. }
  25. }
  26. }
  27. //节点结构
  28. class TreeNode {
  29. int value;
  30. TreeNode left;
  31. TreeNode right;
  32. TreeNode(int value) {
  33. this.value = value;
  34. }
  35. }

九. 数据结构专栏

https://blog.csdn.net/weixin_53919192/category_11908333.html?spm=1001.2014.3001.5482https://blog.csdn.net/weixin_53919192/category_11908333.html?spm=1001.2014.3001.5482

后文有介绍二叉树以及非递归遍历二叉树的内容,有兴趣的朋友可以去看看:树形结构之非递归遍历二叉树 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/535138
推荐阅读
相关标签
  

闽ICP备14008679号