二叉树的前序,中序,后序遍历(递归和非递归写法)

一、前序遍历

        前序遍历是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右

        前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根节点,然后遍历左子树,最后遍历右子树。

        若二叉树为空则结束返回,否则:

        (1)访问根结点。

        (2)前序遍历左子树

        (3)前序遍历右子树 。

        如图所示,前序遍历的结果为:ABDECFG

 

递归实现:

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }
    //递归前序
    public void preOrder(TreeNode root){
        if(root != null){
            System.out.print(root.v);//打印根节点
            preOrder(root.leftnode);//访问左节点
            preOrder(root.rightnode);//访问右节点
        }
    }
}

测试代码,下同

public class Test {
    public static void main(String[] args) {
        TreeNode n1=new TreeNode("A");
        TreeNode n2=new TreeNode("B");
        TreeNode n3=new TreeNode("C");
        TreeNode n4=new TreeNode("D");
        TreeNode n5=new TreeNode("E");
        TreeNode n6=new TreeNode("F");
        TreeNode n7=new TreeNode("G");
        n1.leftnode=n2;
        n1.rightnode=n3;
        n2.leftnode=n4;
        n2.rightnode=n5;
        n3.leftnode=n6;
        n3.rightnode=n7;
        n1.preOrder(n1);

    }
}

测试结果:

非递归实现:

        根节点存入栈中打印根节点,然后访问这个根节点的左子树,左子树也是将左子树的根存入栈中打印根节点,依次往下直到左子树为空,再取出栈顶元素,栈顶元素(访问完左子树的根节点)作为新的根节点去访问右子树。

 

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }
    //非递归前序
    public void preOrder(TreeNode root){
        Stack<TreeNode> stack =new Stack<>();//定义一个栈用于存放节点
        while (root!=null || !stack.isEmpty()){//判断二叉树是否遍历完
            while (root!=null){//往左走
                stack.push(root);//根节点入栈
                System.out.print(root.v);//打印根节点
                root=root.leftnode;//访问根节点的左节点
            }
            root=stack.pop();//取出根节点
            root=root.rightnode;//访问根节点的右节点
        }
    }
}

测试结果:

二、中序遍历 

        中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。可记作左跟右

        中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。

        若二叉树为空则结束返回,否则:

        (1)中序遍历左子树

        (2)访问根结点

        (3)中序遍历右子树

如图所示,中序遍历的结果为:DBEAFCG

递归实现:

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }

        //递归中序
    public void preOrder(TreeNode root){
        if(root != null){
            preOrder(root.leftnode);//访问左节点
            System.out.print(root.v);//打印根节点
            preOrder(root.rightnode);//访问右节点
        }
    }
}

 测试结果:

 非递归方式

        与前序方式基本相同,不同的是不先打印根节点,而是先访问左子树,在打印根节点,在访问右子树。

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }
    //非递归中序
    public void preOrder(TreeNode root){
        Stack<TreeNode> stack =new Stack<>();//定义一个栈用于存放节点
        while (root!=null || !stack.isEmpty()){//判断二叉树是否遍历完
            while (root!=null){//往左走
                stack.push(root);//根节点入栈
                root=root.leftnode;//访问根节点的左节点
            }
            root=stack.pop();//取出根节点
            System.out.print(root.v);//打印根节点
            root=root.rightnode;//访问根节点的右节点
        }
    }
}

测试结果:

 

后序遍历

        后序遍历(LRD)是二叉树遍历的一种,也叫做后根遍历、后序周游,可记做左右根。  

        后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。即:

若二叉树为空则结束返回,否则:

        (1)后序遍历左子树

        (2)后序遍历右子树

        (3)访问根结点

 如图所示,中序遍历的结果为:DEBFGCA\

 递归方法

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }
            //递归后序
    public void preOrder(TreeNode root){
        if(root != null){
            preOrder(root.leftnode);//访问左节点
            preOrder(root.rightnode);//访问右节点
            System.out.print(root.v);//打印根节点
        }
    }
}

 测试结果:

非递归方法 

public class TreeNode {//定义二叉树节点
    TreeNode leftnode;
    TreeNode rightnode;
    String v;
    public TreeNode(String v){
        this.v=v;
    }

        //非递归后序
    public void preOrder(TreeNode root){
        Stack<TreeNode> stack =new Stack<>();//定义一个栈用于存放节点
        TreeNode node =root;
        TreeNode p=null;
        while (node!=null || !stack.isEmpty()){//判断二叉树是否遍历完
            while (node!=null){//往左走
                stack.push(node);//根节点入栈
                node=node.leftnode;//访问根节点的左节点
            }
            node=stack.peek();//判断栈顶元素

            if (node.rightnode==null || node.rightnode==p){
                node=stack.pop();//打印根节点,并出栈,将打印过的节点从栈中删除
                System.out.print(node.v);
                p=node;//记录prev,表示以当前prev为根的子树已经访问过了
                node=null;//node置null就不会再次访问以node为根节点的左右子树,这里的node既然已经打印,说明它的左右子树早已访问完毕
            }else {
                node=node.rightnode;//访问右子树
            }

        }
    }
}

测试结果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值