• 数据结构--树的非递归遍历


        树的递归遍历代码非常简单易懂,但是由于递归会占用非常多的栈空间,因此非递归的遍历树也是必须要掌握的。因此最近仔细分析了很多的代码以及理解了遍历的过程,最后敲一遍并在这里记录一下,以后可以快速回顾。一般来说,递归可以解决的问题也一定可以用栈加循环的方式解决,毕竟递归实质上就是利用了栈嘛。

    树从根节点开始对每个结点进行遍历,每个结点必定被访问三次,如上图。

    第一次碰到就访问就是先序,第二次碰到访问就是中序,第三次碰到访问就是后序。

    public class TreeReader {
    
        public void preOrder(TreeNode t) {  //先序遍历
            Stack<TreeNode> s = new Stack<>();
            while(t != null || !s.isEmpty()) {
                while(t != null) {
                    System.out.println(t.val);  //第一次碰到就访问结点
                    s.push(t);                //压栈保存,以便左边访问完了,之后可以弹出它得到它的右节点
                    t = t.left;
                }
                if(!s.isEmpty()) {
                    t = s.pop();
                    t = t.right;      //当上述循环退出,说明左子树全访问完了,则把父结点弹出,准备访问右子树
                }
            }
        }
    
        public void inOrder(TreeNode t) {  //中序,与先序很像,只是在第二次碰到结点才访问
            Stack<TreeNode> s = new Stack<>();
            while(t != null || !s.isEmpty()) {
                while(t != null) {
                    s.push(t);      //第一次碰到不访问,只保存
                    t = t.left;
                }
                if(!s.isEmpty()) {
                    t = s.pop();
                    System.out.println(t.val);    //左子树访问完了,弹出父结点,第二次碰到则访问
                    t = t.right;            //准备访问右子树
                }
            }
        }
    
        public void lastOrder(TreeNode t) {  //后序与上述两种方式有区别,只有左右结点都被访问,当前结点才能被访问
            TreeNode preNode = null;         //记录上一次访问结点
            Stack<TreeNode> s = new Stack<>();
            s.push(t);    //压入根节点,这货铁定最后访问,万年栈底元素
            while(!s.isEmpty()) {
                TreeNode current = s.peek(); //获取栈顶元素
    
                //当前结点左右结点均为空,或左右结点不都为空但已经都被访问则当前结点可以访问了(即上次访问结点preNode == 左/右结点)
                //由于压栈顺序是先右后左,所以当前结点的孩子们访问时必然是先左后右. preNode == left说明当前结点只有左孩子且已被访问,==right说明有两个孩子且左右均已访问
                if((current.left==null&&current.right==null)||(preNode!=null&&(preNode==current.left||preNode==current.right))){
                    System.out.println(current.val);
                    s.pop();  
                    preNode = current;  //每访问一个结点都记录一下,以便下次判断结点的左右孩子是否已被访问
                }
                else {
             if(current.right != null) //若不满足上述条件,则把当前结点的孩子以先右后左的顺序压栈,这样访问时就是先左后右了   s.push(current.right);   if(current.left != null)   s.push(current.left);
           } } } }
    class TreeNode { TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; } }
  • 相关阅读:
    2017(秋)软工作业: (2)硬币游戏—— 代码分析与改进
    软工作业(1)课程学习热身
    用户体验分析:以 “师路南通网站” 为例
    用户体验分析: 以 “南通大学教务管理系统微信公众号” 为例
    软件工程第二次作业:硬币游戏—— 代码分析与改进
    自我介绍
    用户体验分析---以师路南通为例
    用户体验分析---七八点照相馆
    硬币游戏—— 代码分析与改进
    About me
  • 原文地址:https://www.cnblogs.com/shen-qian/p/11430923.html
Copyright © 2020-2023  润新知