zoukankan      html  css  js  c++  java
  • 二叉树的遍历

    一、递归方式遍历

    递归方法完成二叉树的遍历,每一个节点都能回去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
     */
  • 相关阅读:
    JSP基础学习
    opnet仿真过程中SEED的概念问题 分类: opnet 2014-11-02 15:25 69人阅读 评论(0) 收藏
    strtok函数 分类: c++ 2014-11-02 15:24 214人阅读 评论(0) 收藏
    无线网络中常用的路由算法 分类: 协议 2014-10-08 19:40 86人阅读 评论(0) 收藏
    cin问题 分类: c++ 2014-08-02 21:13 38人阅读 评论(0) 收藏
    opnet点对点通信模型 分类: opnet 2014-05-26 22:15 246人阅读 评论(3) 收藏
    opnet的sink模块学习 分类: opnet 2014-05-18 10:28 161人阅读 评论(0) 收藏
    opnet的simple_source模块学习 分类: opnet 2014-05-18 09:50 170人阅读 评论(0) 收藏
    OPNET中FIN,FOUT以及FRET的作用 分类: opnet 2014-05-12 16:07 144人阅读 评论(0) 收藏
    opnet安装及安装中出现问题的解决办法 分类: opnet 2014-04-06 21:50 397人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/15130513.html
Copyright © 2011-2022 走看看