• 数据结构(4)树形结构——二叉树(概述、前序、中序、后序、层序遍历JAVA实现)


    目录

    4.1.树

    4.2.二叉树

    4.2.1.概述

    4.2.3.存储结构

    4.2.3.遍历

    1.逻辑简介

     2.代码示例


    4.1.树

    树,由n(n≥0)个有限节点和边组成一个具有层次关系的数据结构。树需要满足以下条件:

    • 任何结点的子节点不相交。
    • 任何子结点只有一个父节点。
    • N个结点,N-1条边。

    对于一个非空树(结点数≥0),具有以下性质:

    • 起始结点称为“根”
    • 除根结点外可分为m个互不相交的有限集合,其中每个集合本身也是一棵树,称为原来这棵树的“子树”。

     树的基本术语:

    • 结点的度:节点的子树个数
    • 树的度:树的所有结点中最大的度数
    • 叶结点:度为0的结点
    • 父结点:有子树的结点都是它的子树的根结点
    • 子结点:若A是B的父结点,则B是A的子节点
    • 兄弟结点:具有同一父结点的结点彼此是

    4.2.二叉树

    4.2.1.概述

    二叉树是一种每个结点的度不大于2的树,由根结点和左子树、右子树组成,具有以下五种姿态:

     除了五种基本姿态外,还有三种比较特殊的姿态:

    4.2.3.存储结构

    二叉树可以用两种结构存储,一种是链表,一种是数组。

    数组表示的话第一个位置存储的根结点,挨着根结点的是根结点的左右孩子,接下来是根结点左孩子的左右孩子,右孩子的左右孩子,以此类推:

     数组仅适合完全二叉树(完美二叉树是特殊的完全二叉树),以为当表示非完全而二叉树,会出现大面积内存空间浪费的情况:

    4.2.3.遍历

    1.逻辑简介

    二叉的遍历,本质上是二维结构的线性化,二叉树本来是非线性的,但是其结果最后是线性的。

    二叉树的遍历根据访问当前子树的根结点的顺序分为四种:

    • 先序遍历
    • 中序遍历
    • 后序遍历

    除此之外还有一种特殊的遍历,层序遍历,按照每一层来遍历。

    层序遍历需要用到一个队列来实现:

    首先是根结点入队,然后访问根结点,根结点左右孩子顺序入队,根结点出队,然后队列中的后续结点重复上述的出队入队流程,直到队列为空,整个层序遍历过程就结束。

     2.代码示例

    二树的结点:

    1. public class Node {
    2. //数据域
    3. private int data;
    4. //指针域
    5. private Node left;
    6. private Node right;
    7. //遍历标志
    8. private boolean isOrder;
    9. {
    10. isOrder=false;
    11. }
    12. public Node(){
    13. }
    14. public Node(int data){
    15. this.data=data;
    16. }
    17. public int getData() {
    18. return data;
    19. }
    20. public void setData(int data) {
    21. this.data = data;
    22. }
    23. public Node getLeft() {
    24. return left;
    25. }
    26. public void setLeft(Node left) {
    27. this.left = left;
    28. }
    29. public Node getRight() {
    30. return right;
    31. }
    32. public void setRight(Node right) {
    33. this.right = right;
    34. }
    35. public boolean isOrder() {
    36. return isOrder;
    37. }
    38. public void setOrder(boolean order) {
    39. isOrder = order;
    40. }
    41. }

     各种遍历的实现:

    1. public class BinaryTree {
    2. //判断BT是否为空
    3. public static boolean isEmpty(Node root){
    4. //判断操作
    5. return root==null?true:false;
    6. }
    7. //先序建树
    8. public static Node create(Node node,Scanner scanner){
    9. Integer data=Integer.parseInt(scanner.next());
    10. if(data!=-1){
    11. node=new Node();
    12. node.setData(data);
    13. node.setLeft(create(node,scanner));
    14. node.setRight(create(node,scanner));
    15. }
    16. //以防万一,如果节点为叶节点时,将其左右指针置空
    17. if(data==-1){
    18. node.setLeft(null);
    19. node.setRight(null);
    20. }
    21. return node;
    22. }
    23. //递归先序遍历二叉树
    24. public static void pre(Node node){
    25. //需要给节点增加一个遍历状态标志位
    26. //每次递归回溯时需要判断当前节点的标志位是否为已遍历状态
    27. //否则会徘徊在叶节点,堆栈溢出
    28. if(node!=null&!node.isOrder()){
    29. System.out.println(node.getData());
    30. node.setOrder(true);
    31. pre(node.getLeft());
    32. pre(node.getRight());
    33. }
    34. }
    35. //中序遍历
    36. public static void mid(Node node){
    37. if(node!=null&!node.isOrder()){
    38. node.setOrder(true);
    39. mid(node.getLeft());
    40. System.out.println(node.getData());
    41. mid(node.getRight());
    42. }
    43. }
    44. //后续遍历
    45. public static void post(Node node){
    46. if(node!=null&!node.isOrder()){
    47. node.setOrder(true);
    48. mid(node.getLeft());
    49. mid(node.getRight());
    50. System.out.println(node.getData());
    51. }
    52. }
    53. //层序遍历
    54. public static void level(){
    55. //递归法
    56. if (!queue.isEmpty()) {
    57. //取出队首元素
    58. Node node = queue.exit();
    59. //打印节点数据
    60. System.out.println(node.getData());
    61. //左孩子入队
    62. queue.Enter(node.getLeft());
    63. //右孩子入队
    64. queue.Enter(node.getRight());
    65. level();
    66. }
    67. //循环法
    68. /*while (!queue.isEmpty()) {
    69. //取出队首元素
    70. Node node = queue.exit();
    71. //打印节点数据
    72. System.out.println(node.getData());
    73. //左孩子入队
    74. queue.Enter(node.getLeft());
    75. //右孩子入队
    76. queue.Enter(node.getRight());
    77. }*/
    78. }
    79. }

    需要注意的是,层序遍历的话要用到一个队列来实现,这个队列的话用的就是之前在线性结构里实现的那个队列:

    1. public class queue {
    2. private static Node[] que;
    3. //头指针
    4. private static int first;
    5. //尾指针
    6. private static int last;
    7. //初始化
    8. static{
    9. que=new Node[100];
    10. first=0;
    11. last=-1;
    12. }
    13. //入队
    14. public static void Enter(Node node){
    15. que[++last]=node;
    16. }
    17. //出队
    18. public static Node exit(){
    19. Node node=que[first++];
    20. return node;
    21. }
    22. //判空
    23. public static boolean isEmpty(){
    24. return (que[first]==null&&first==last) ? true:false;
    25. }
    26. }

  • 相关阅读:
    C++11标准模板(STL)- 算法(std::unique_copy)
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    Yolov8引入 清华 ICCV 2023 最新开源移动端网络架构 RepViT | RepViTBlock即插即用,助力检测
    困境添乱:即将开庭的2场离奇诉讼
    JavaScript基础总结---重点
    总结10.15
    2022-07-29 java之异常
    ros-noetic采集单目USB相机数据
    将 RDBMS 恐龙迁移到云端
    计算机网络的标准化工作及相关组织
  • 原文地址:https://blog.csdn.net/Joker_ZJN/article/details/127980537