二叉树的遍历

Posted kingli1024

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的遍历相关的知识,希望对你有一定的参考价值。

1.前序遍历

前序遍历(DLR,lchild,data,rchild),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。

前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。                                                              技术图片
若二叉树为空则结束返回,否则: 
(1)访问根结点。
(2)前序遍历左子树。
(3)前序遍历右子树 。前序遍历                           
需要注意的是:遍历左右子树时仍然采用前序遍历方法。
如图所示二叉树

技术图片

 


前序遍历结果:ABDECF
已知后序遍历和中序遍历,就能确定前序遍历。
    其实在遍历二叉树的时候有三次遍历, 比如前序遍历:A->B->D->D(D左子节点并返回到D)->D(D右子节点并返回到D)->B->E->E(左)->E(右)->->B->A->C->F->F(左)->F(右)->C->C(右),所以可以用栈结构,把遍历到的节点压进栈,没子节点时再出栈。也可以用递归的方式,递归的输出当前节点,然后递归的输出左子节点,最后递归的输出右子节点。直接看代码更package test//前序遍历的递归实现与非递归实import java.util.Stack;public class Test 


    public static void main(String[] args)
    
        TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
        for(int i = 0; i < 10; i++)
        
            node[i] = new TreeNode(i);
        
        for(int i = 0; i < 10; i++)
        
            if(i*2+1 < 10)
                node[i].left = node[i*2+1];
            if(i*2+2 < 10)
                node[i].right = node[i*2+2];
        
        
        preOrderRe(node[0]);
    
    
    public static void preOrderRe(TreeNode biTree)
    //递归实现
        System.out.println(biTree.value);
        TreeNode leftTree = biTree.left;
        if(leftTree != null)
        
            preOrderRe(leftTree);
        
        TreeNode rightTree = biTree.right;
        if(rightTree != null)
        
            preOrderRe(rightTree);
        
    
    
    public static void preOrder(TreeNode biTree)
    //非递归实现
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(biTree != null || !stack.isEmpty())
        
            while(biTree != null)
            
                System.out.println(biTree.value);
                stack.push(biTree);  【节点入栈的目的:1.为了左子树向右子数的转移】
                biTree = biTree.left;
            
            if(!stack.isEmpty())
            
                biTree = stack.pop();
                biTree = biTree.right;
            
        
    


在非递归遍历的时候,过程是这样的:A入栈,判断A的左子树是否为空,不为空的话,B入栈,同理,D入栈,D的左子树为空,D的右子树为空,此时D节点遍历完成,B的左子树遍历完成,
现在开始遍历B节点的右子树,F入栈,F左子树E入栈,F右子树为空,此时F节点遍历完成。A的右子树C入栈,C的左子树入栈,G的右子树H入栈,I入栈。此时整个二叉树遍历完毕。

class TreeNode//节点结构 int value; TreeNode left; TreeNode right; TreeNode(int value) this.value = value;

2.中序遍历

中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。在二叉树中,先左后根再右。巧记:左根右。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树
若二叉树为空则结束返回,
否则:


(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树
如右图所示二叉树
中序遍历结果:DBEAFC

import java.util.Stack;
public class Test 

    public static void main(String[] args)
    
        TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
        for(int i = 0; i < 10; i++)
        
            node[i] = new TreeNode(i);
        
        for(int i = 0; i < 10; i++)
        
            if(i*2+1 < 10)
                node[i].left = node[i*2+1];
            if(i*2+2 < 10)
                node[i].right = node[i*2+2];
        
        
        midOrderRe(node[0]);
        System.out.println();
        midOrder(node[0]);
    
    
    public static void midOrderRe(TreeNode biTree)
    //中序遍历递归实现
        if(biTree == null)
            return;
        else
        
            midOrderRe(biTree.left);
            System.out.println(biTree.value);
            midOrderRe(biTree.right);
        
    
    
    
    public static void midOrder(TreeNode biTree)
    //中序遍历费递归实现
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(biTree != null || !stack.isEmpty())
        
            while(biTree != null)
            
                stack.push(biTree);
                biTree = biTree.left;
            
            if(!stack.isEmpty())
            
                biTree = stack.pop();
                System.out.println(biTree.value);
                biTree = biTree.right;
            
        
    

 
class TreeNode//节点结构

    int value;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int value)
    
        this.value = value;
    


3.后序遍历(难点)后序遍历(LRD)是二叉树遍历的一种,也叫做后根遍历、后序周游,可记做左右根。后序遍历有递归算法和非递归算法两种。在二叉树中,先左后右再根。巧记:左右根。后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:若二叉树为空则结束返回,
否则:(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点
后序遍历结果:DEBFCA
已知前序遍历和中序遍历,就能确定后序遍历。
算法核心思想:
    首先要搞清楚先序、中序、后序的非递归算法共同之处:用栈来保存先前走过的路径,以便可以在访问完子树后,可以利用栈中的信息,回退到当前节点的双亲节点,进行下一步操作。
    后序遍历的非递归算法是三种顺序中最复杂的,原因在于,后序遍历是先访问左、右子树,再访问根节点,而在非递归算法中,利用栈回退到时,并不知道是从左子树回退到根节点,还是从右子树回退到根节点,如果从左子树回退到根节点,此时就应该去访问右子树,而如果从右子树回退到根节点,此时就应该访问根节点。所以相比前序和后序,必须得在压栈时添加信息,以便在退栈时可以知道是从左子树返回,还是从右子树返回进而决定下一步的操作。

import java.util.Stack;
public class Test 

    public static void main(String[] args)
    
        TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
        for(int i = 0; i < 10; i++)
        
            node[i] = new TreeNode(i);
        
        for(int i = 0; i < 10; i++)
        
            if(i*2+1 < 10)
                node[i].left = node[i*2+1];
            if(i*2+2 < 10)
                node[i].right = node[i*2+2];
        
        
        postOrderRe(node[0]);
        System.out.println("***");
        postOrder(node[0]);
    
    
    
    
    public static void postOrderRe(TreeNode biTree)
    //后序遍历递归实现
        if(biTree == null)
            return;
        else
        
            postOrderRe(biTree.left);
            postOrderRe(biTree.right);
            System.out.println(biTree.value);
        
    
    
    public static void postOrder(TreeNode biTree)
    //后序遍历非递归实现
        int left = 1;//在辅助栈里表示左节点
        int right = 2;//在辅助栈里表示右节点
        Stack<TreeNode> stack = new Stack<TreeNode>();
        Stack<Integer> stack2 = new Stack<Integer>();//辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。
        
        while(biTree != null || !stack.empty())
        
            while(biTree != null)
            //将节点压入栈1,并在栈2将节点标记为左节点
                stack.push(biTree);
                stack2.push(left);
                biTree = biTree.left;
            
            
            while(!stack.empty() && stack2.peek() == right)
            //如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
                stack2.pop();
                System.out.println(stack.pop().value);
            
            
            if(!stack.empty() && stack2.peek() == left)
            //如果是从左子节点返回父节点,则将标记改为右子节点
                stack2.pop();
                stack2.push(right);
                biTree = stack.peek().right;
            
                
        
    

 
class TreeNode//节点结构

    int value;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int value)
    
        this.value = value;
    

 
 

转载自:https://blog.csdn.net/coder__666/article/details/80349039

      https://blog.csdn.net/justinzengTM/article/details/80056106(中序遍历讲解的非常详细)

 

 


-

以上是关于二叉树的遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的遍历

讲透学烂二叉树:二叉树的遍历图解算法步骤及JS代码

二叉树(2.二叉树的遍历和实现)

根据二叉树的前序遍历和中序遍历构建二叉树的c语言完整代码

通过遍历序列构造二叉树(扩展二叉树的先序先序和中序后序和中序层序和中序)附可执行完整代码

代码题— 二叉树的层次遍历