二叉树的遍历

一、递归方式遍历

递归方法完成二叉树的遍历,每一个节点都能回去3次(虽然某一次回去的时候什么也没干)

 在递归序的基础上,选择打印的时机不同可演变出前序、中序、后续三种遍历方式

前序-打印递归遍历时第1次出现的数字(头左右):1,2,4,5,3,6,7  

中序-打印递归遍历时第2次出现的数字(左头右):4,2,5,1,6,3,7

后续-打印递归遍历时第3次出现的数字(左右头):4,5,2,6,7,3,1

    public static void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " "); //此位置为前序递归
        preOrderRecur(head.left);
        //System.out.print(head.value + " "); //此位置为中序递归
        preOrderRecur(head.right);
        //System.out.print(head.value + " "); //此位置为后序递归
    }
前序递归遍历

 二、非递归方式遍历

 1、前序遍历

先把头节点放入栈中

1)每次在栈中弹出一个节点,记为cur

2)打印(处理)cur

3)如有cur有左右孩子(没有孩子就不操作,继续步骤1),先把cur右孩子压栈,再把cur左孩子压栈

4)循环以上三步操作

   //前序非递归
    public static void preOrderUnRecur(Node head) {
        System.out.print("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.add(head);  //先把头节点压入栈中
            while (!stack.isEmpty()) { //只要栈不是空的,循环3个步骤
                head = stack.pop();
                System.out.print(head.value + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }
前序非递归遍历

2、后续遍历

由前序遍历进行改进而来:

准备两栈(多一个收集栈),先把头节点放入正常栈中

1)每次在正常栈中弹出一个节点,记为cur

2)把cur放入一个收集栈中

3)如有cur有左右孩子(没有孩子就不操作,继续步骤1),先把cur孩子压入正常栈,再把cur孩子压正常栈

循环以上三步操作

4)再把收集栈中的元素依次弹出就是后续遍历结果

//后序非递归
    public static void posOrderUnRecur1(Node head) {
        System.out.print("pos-order: ");
        if (head != null) {
            Stack<Node> s1 = new Stack<Node>(); //正常栈
            Stack<Node> s2 = new Stack<Node>(); //收集栈
            s1.push(head); //先压入头节点
            while (!s1.isEmpty()) { //循环1/2/3
                head = s1.pop(); //1、每次弹出一个元素
                s2.push(head); //2、弹出之后不打印,而是放入收集栈中
                if (head.left != null) {
                    s1.push(head.left); //3、先压左节点
                }
                if (head.right != null) {
                    s1.push(head.right); //3、再压右节点
                }
            }
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().value + " "); //4、最后把收集栈中的元素弹出进行打印
            }
        }       
    }
后续非递归遍历

3、中序遍历

1)把当前节点的所有左节点压栈

2)依次弹出节点的过程中,打印

3)每弹出一个节点,把目标移到弹出节点的右节点上面

循环以上三个操作

 

//中序非递归
    public static void inOrderUnRecur(Node head) {
        System.out.print("in-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) { //1、把当前节点所有的左节点压栈
                    stack.push(head);
                    head = head.left;
                } else { //所有左节点压栈之后
                    head = stack.pop(); //2、弹出一个节点,打印
                    System.out.print(head.value + " ");
                    head = head.right; //3、然后移动到弹出节点的右节点上面,循环以上步骤
                }
            }
        }
    }
中序非递归遍历

 为什么进行以上三步操作就能实现前中后的中序遍历?

整体代码 

package Algorithms;

/**
 * @author : zhang
 * @version : 1.0
 * @date : Create in 2021/8/11
 * @description :
 */

import java.util.Stack;

public class PreInPosTraversal {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    //前序递归
    public static void preOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

    //中序递归
    public static void inOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        inOrderRecur(head.left);
        System.out.print(head.value + " ");
        inOrderRecur(head.right);
    }

    //后序递归
    public static void posOrderRecur(Node head) {
        if (head == null) {
            return;
        }
        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.print(head.value + " ");
    }

    //前序非递归
    public static void preOrderUnRecur(Node head) {
        System.out.print("pre-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.add(head);  //先把头节点压入栈中
            while (!stack.isEmpty()) { //只要栈不是空的,循环3个步骤
                head = stack.pop();
                System.out.print(head.value + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

    //中序非递归
    public static void inOrderUnRecur(Node head) {
        System.out.print("in-order: ");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) { //1、把当前节点所有的左节点压栈
                    stack.push(head);
                    head = head.left;
                } else { //所有左节点压栈之后
                    head = stack.pop(); //2、弹出一个节点,打印
                    System.out.print(head.value + " ");
                    head = head.right; //3、然后移动到弹出节点的右节点上面,循环以上步骤
                }
            }
        }
    }

    //后序非递归
    public static void posOrderUnRecur1(Node head) {
        System.out.print("pos-order: ");
        if (head != null) {
            Stack<Node> s1 = new Stack<Node>(); //正常栈
            Stack<Node> s2 = new Stack<Node>(); //收集栈
            s1.push(head); //先压入头节点
            while (!s1.isEmpty()) { //循环1/2/3
                head = s1.pop(); //1、每次弹出一个元素
                s2.push(head); //2、弹出之后不打印,而是放入收集栈中
                if (head.left != null) {
                    s1.push(head.left); //3、先压左节点
                }
                if (head.right != null) {
                    s1.push(head.right); //3、再压右节点
                }
            }
            while (!s2.isEmpty()) {
                System.out.print(s2.pop().value + " "); //4、最后把收集栈中的元素弹出进行打印
            }
        }
        System.out.println();
    }

    public static void posOrderUnRecur2(Node h) {
        System.out.print("pos-order: ");
        if (h != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(h);
            Node c = null;
            while (!stack.isEmpty()) {
                c = stack.peek();
                if (c.left != null && h != c.left && h != c.right) {
                    stack.push(c.left);
                } else if (c.right != null && h != c.right) {
                    stack.push(c.right);
                } else {
                    System.out.print(stack.pop().value + " ");
                    h = c;
                }
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);


        // recursive
        System.out.println("==============recursive==============");
        System.out.print("pre-order: ");
        preOrderRecur(head);
        System.out.println();
        System.out.print("in-order: ");
        inOrderRecur(head);
        System.out.println();
        System.out.print("pos-order: ");
        posOrderRecur(head);
        System.out.println();

        // unrecursive
        System.out.println("============unrecursive=============");
        preOrderUnRecur(head);
        inOrderUnRecur(head);
        posOrderUnRecur1(head);
        posOrderUnRecur2(head);
    }
}

/**
 * ==============recursive==============
 * pre-order: 1 2 4 5 3 6 7
 * in-order: 4 2 5 1 6 3 7
 * pos-order: 4 5 2 6 7 3 1
 * ============unrecursive=============
 * pre-order: 1 2 4 5 3 6 7
 * in-order: 4 2 5 1 6 3 7
 * pos-order: 4 5 2 6 7 3 1
 * pos-order: 4 5 2 6 7 3 1
 */

 

posted @ 2021-08-12 10:07  zh_小猿  阅读(125)  评论(0编辑  收藏  举报