• Java实现对二叉树前序/中序/后序的递归与非递归算法


    二叉树的前序、中序、后序遍历的定义:
    前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
    中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;

    后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。

    首先创建节点类,并在里面添加了一个创建树的方法,调用后就可以返回一个包含7个节点的二叉树。

    点击(此处)折叠或打开

    1. public class Node {
    2.     // 节点值
    3.     public int value;

    4.     // 左子节点
    5.     public Node left;

    6.     // 右子节点
    7.     public Node right;

    8.     Node(int va) {
    9.         value = va;
    10.     }

    11.     Node(int va, Node le, Node ri) {
    12.         value = va;
    13.         left = le;
    14.         ri = right;
    15.     }

    16.     /**
    17.      * 创建一颗二叉树
    18.      *
    19.      * @return 根节点
    20.      */
    21.     public static Node createTree() {
    22.         Node root = new Node(0);
    23.         Node node1 = new Node(1);
    24.         Node node2 = new Node(2);
    25.         Node node3 = new Node(3);
    26.         Node node4 = new Node(4);
    27.         Node node5 = new Node(5);
    28.         Node node6 = new Node(6);
    29.         Node node7 = new Node(7);

    30.         root.left = node1;
    31.         root.right = node2;
    32.         node1.left = node3;
    33.         node1.right = node4;
    34.         node2.left = node5;
    35.         node2.right = node6;
    36.         node3.left = node7;
    37.         return root;
    38.     }
    39. }

                创建遍历类,在该类里实现各种遍历方法。

    点击(此处)折叠或打开

    1. import java.util.ArrayList;

    2. public class Traverse {

    3.     /**
    4.      * 递归前序遍历
    5.      *
    6.      * @param root
    7.      */
    8.     public void recursiveProOrder(Node root) {
    9.         // 遍历根节点
    10.         if (root != null) {
    11.             System.out.print(root.value);
    12.         }
    13.         // 遍历左子树
    14.         if (root.left != null) {
    15.             recursiveProOrder(root.left);
    16.         }
    17.         // 遍历右子树
    18.         if (root.right != null) {
    19.             recursiveProOrder(root.right);
    20.         }
    21.     }

    22.     /**
    23.      * 前序遍历
    24.      *
    25.      * @param root
    26.      */
    27.     public void proOrder(Node root) {
    28.         // 使用ArrayList作为堆栈
    29.         ArrayList<Node> stack = new ArrayList<Node>();
    30.         // 栈指针
    31.         int top = -1;
    32.         Node current = root;
    33.         while (true) {
    34.             if (current != null) {
    35.                 System.out.print(current.value);
    36.             }
    37.             // 右子节点进栈
    38.             if (current.right != null) {
    39.                 stack.add(current.right);
    40.                 top++;
    41.             }
    42.             // 左子节点进栈
    43.             if (current.left != null) {
    44.                 stack.add(current.left);
    45.                 top++;
    46.             }
    47.             // 如果栈内还有节点,栈顶节点出栈
    48.             if (top > -1) {
    49.                 current = stack.get(top);
    50.                 stack.remove(top--);
    51.             } else {
    52.                 break;
    53.             }
    54.         }
    55.     }

    56.     /**
    57.      * 递归中序遍历
    58.      *
    59.      * @param root
    60.      */
    61.     public void recursiveInOrder(Node root) {
    62.         if (root != null) {
    63.             if (root.left != null) {
    64.                 recursiveInOrder(root.left);
    65.             }
    66.             System.out.print(root.value);
    67.             if (root.right != null) {
    68.                 recursiveInOrder(root.right);
    69.             }
    70.         }
    71.     }

    72.     /**
    73.      * 中序遍历
    74.      *
    75.      * @param root
    76.      */
    77.     public void inOrder(Node root) {
    78.         if (root != null) {
    79.             ArrayList<Node> stack = new ArrayList<Node>();
    80.             int top = -1;
    81.             Node current = root;
    82.             while (current != null || top > -1) {
    83.                 if (current != null) {
    84.                     // 一直深入地寻找左子节点,并将路上的节点都进栈
    85.                     stack.add(current);
    86.                     top++;
    87.                     current = current.left;
    88.                 } else {
    89.                     // 取出栈顶节点,并继续遍历右子树
    90.                     current = stack.get(top);
    91.                     stack.remove(top--);
    92.                     System.out.print(current.value);
    93.                     current = current.right;
    94.                 }
    95.             }
    96.         }
    97.     }

    98.     /**
    99.      * 递归后续遍历
    100.      *
    101.      * @param root
    102.      */
    103.     public void recursivePostOrder(Node root) {
    104.         if (root != null) {
    105.             if (root.left != null) {
    106.                 recursivePostOrder(root.left);
    107.             }
    108.             if (root.right != null) {
    109.                 recursivePostOrder(root.right);
    110.             }
    111.             System.out.print(root.value);
    112.         }
    113.     }

    114.     /**
    115.      * 后序遍历:可以被遍历的节点都要进栈出栈两次,所以添加第二个栈用来标示进栈次数
    116.      *
    117.      * @param root
    118.      */
    119.     public void postOrder(Node root) {
    120.         if (root != null) {
    121.             // 用来保存节点的栈
    122.             ArrayList<Node> stack = new ArrayList<Node>();
    123.             // 用来保存标志位的栈
    124.             ArrayList<Integer> stack2 = new ArrayList<Integer>();
    125.             // 两个栈共用的栈指针
    126.             int top = -1;
    127.             int tag;
    128.             Node current = root;
    129.             do {
    130.                 //将所有左子节点进栈
    131.                 while (current != null) {
    132.                     stack.add(current);
    133.                     stack2.add(0);
    134.                     top++;
    135.                     current = current.left;
    136.                 }
    137.                 //取出栈顶节点,并判断其标志位
    138.                 current = stack.get(top);
    139.                 tag = stack2.get(top);
    140.                 stack2.remove(top);
    141.                 if (tag == 0) {
    142.                     // tag为0,表明该节点第一次进栈,还需要进栈一次,同时修改标志位
    143.                     current = current.right;
    144.                     stack2.add(1);
    145.                 } else {
    146.                     // tag不位0,表明非首次进栈,可以遍历了。
    147.                     stack.remove(top);
    148.                     top--;
    149.                     System.out.print(current.value);
    150.                     current = null;
    151.                 }
    152.             } while (current != null || top != -1);
    153.         }
    154.     }
    155. }
                 实例化遍历类并调用各个遍历方法。
             点击(此处)折叠或打开
    1. public class Algorithm {

    2.     public static void main(String[] args) {

    3.          Node root=Node.createTree();
    4.          System.out.print("前序遍历: ");
    5.          new Traverse().proOrder(root);
    6.          System.out.println();
    7.          System.out.print("前序递归遍历: ");
    8.          new Traverse().recursiveProOrder(root);
    9.          System.out.println();
    10.          System.out.print("中序遍历: ");
    11.          new Traverse().inOrder(root);
    12.          System.out.println();
    13.          System.out.print("中序递归遍历: ");
    14.          new Traverse().recursiveInOrder(root);
    15.          System.out.println();
    16.          System.out.print("后序遍历: ");
    17.          new Traverse().postOrder(root);
    18.          System.out.println();
    19.          System.out.print("后序递归遍历: ");
    20.          new Traverse().recursivePostOrder(root);
    21.     }

    输出结果:
    前序遍历:        01374256
    前序递归遍历: 01374256
    中序遍历:        73140526
    中序递归遍历: 73140526
    后序遍历:        73415620
    后序递归遍历: 73415620

  • 相关阅读:
    [转]C++ Operator Overloading Guidelines
    SICP学习笔记(2.2.1)
    .net中模拟键盘和鼠标操作
    javaScript系列 [17]运算符
    javaScript系列 [24]Math
    javaScript系列 [19]string
    javaScript系列 [22]引用类型
    javaScript系列 [12]Canvas绘图(曲线)
    javaScript系列 [15]Canvas绘图(压缩)
    javaScript系列 [21]Array
  • 原文地址:https://www.cnblogs.com/daichangya/p/12959661.html
Copyright © 2020-2023  润新知