三种非递归遍历二叉树的方法

在这里插入图片描述
   就以这个树为例,来讲讲二叉树的非递归遍历。

先序遍历: 先序遍历结果为3 4 6 5 8 9,就拿树的左枝为例,3是根,打印,4是3的左孩子,打印,6是4的左孩子,打印,6的左孩子为空,所以返回到4,然后去找4的右孩子,4的右孩子也为空,返回到3,这就是左子树遍历的过程。然后非递归主要用到栈来存储结点,栈先进后出,所以应该是右孩子先入栈,左孩子后入栈,这样pop就能先得到左孩子。先将根结点3入栈,接下来就是开始循环,循环结束的条件就是栈为空,先弹出栈顶,再打印栈顶,如果栈顶的右孩子不为null,就把右孩子放进栈中,如果栈顶的左孩子不为null,就把左孩子放入栈中。
用下面一幅图来说明整个过程
在这里插入图片描述

void pretravel2(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> s = new Stack<TreeNode>();
        s.push(root);
        while (!s.isEmpty()) {
            TreeNode node = s.pop();
            System.out.print(node.val+" ");
            if (node.right != null) {
                s.push(node.right);
            }
            if (node.left != null) {
                s.push(node.left);
            }
        }
    }

中序遍历:中序遍历的结果为6 4 3 8 5 9,其实就是左遍历完了,弹出根,找根的右结点,整个过程是先一路找左结点,找到左结点为null的6,然后找6的根4,接着找4的右,为null,接着找4的根3,接着一路找3的左,直到结点的左孩子为null,这就找到了8,然后找8的根5,再找5的右9,这样就找完了。他们的入栈出栈顺序:根结点入栈,左孩子直接入栈,并且标记这个结点已经走过,以防后面再走,当发现哪个结点的左孩子为null的时候,就打印这个结点,并且将这个结点出栈,让他的右孩子入栈
在这里插入图片描述

 void intravel2(TreeNode root) {
        if(root==null)
            return ;
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        //使用list来标记结点是否走过
        List<TreeNode> list=new ArrayList<>();
        while(!stack.isEmpty()) {
        	//只需要拿到根结点,不需要pop出来
            TreeNode peek = stack.peek();
            //如果左孩子不为null并且左孩子没有被走过,就把他放到栈里,并且标记为走过
            if(peek.left!=null&& !list.contains(peek.left)) {
                stack.push(peek.left);
                list.add(peek.left);
            }
            else {//左孩子为空,打印根结点,根结点出栈,右孩子进栈
                TreeNode pop = stack.pop();
                System.out.print(pop.val+" ");
                if(pop.right!=null)
                    stack.push(pop.right);
            }
        }
    }

中序遍历还有另外一种写法:

 void intravel3(TreeNode root) {
        Stack<TreeNode> stack=new Stack<>();
        TreeNode p=root;
        while(p!=null||!stack.isEmpty()) {
            while(p!=null) {
                stack.push(p);
                p=p.left;
            }
            //左孩子遍历完了,根结点弹出,打印根结点,遍历右孩子
            if(!stack.isEmpty()) {
                TreeNode temp=stack.pop();
                System.out.print(temp.val+" ");
                p=temp.right;
            }
        }
    }

后序遍历: 后序遍历的结果为6 4 8 9 5 3,一路找左结点到6,然后找到右孩子为null,退到根4,4的右为null,然后3的左孩子遍历完了,到右孩子,一路找左孩子到8,右孩子9,根5,右孩子遍历完,最后到4。他们的进栈出栈顺序为:根结点入栈,左孩子一路入栈,当有个结点的左孩子为null的时候,就将它的右孩子入栈,如果右孩子也为null,才打印根结点。
在这里插入图片描述

void postrval2(TreeNode root) {
        if(root==null)
            return ;
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        List<TreeNode> list=new ArrayList<>();
        while(!stack.isEmpty()) {
            TreeNode peek=stack.peek();
            //先一路走左,左走完了才到右
            if(peek.left!=null&&!list.contains(peek.left)) {
            //如果左结点不为null并且左结点没有走过
            //就将其压入栈中,并且标记已经走过
                stack.push(peek.left);
                list.add(peek.left);
            }
            else {
               if(peek.right!=null&&!list.contains(peek.right)) {
               //如果右结点为不为null并且右结点没有走过
               //就将右结点压入栈中,标记已经走过
                   stack.push(peek.right);
                   list.add(peek.right);
               }
               else {
               //如果右孩子为null,就打印根结点
                   TreeNode pop = stack.pop();
                   System.out.print(pop.val+" ");
               }
            }
        }
    }

递归遍历,非递归遍历的代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


import java.util.*;

class TreeNode {
    int val;
    TreeNode left=null;
    TreeNode right=null;
    TreeNode(){}
    TreeNode(int val) {
        this.val=val;
    }
}

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        TreeNode root=null;
        root=main.createTree();
        System.out.println("先序遍历:");
        main.pretravel(root);
        System.out.println("");
        System.out.println("中序遍历:");
        main.intravel(root);
        System.out.println("");
        System.out.println("后序遍历:");
        main.postravel(root);
        System.out.println("");
        System.out.println("迭代先序遍历:");
        main.pretravel2(root);
        System.out.println("");
        System.out.println("迭代中序遍历1(类似于回溯算法):");
        main.intravel2(root);
        System.out.println("");
        System.out.println("迭代中序遍历2:");
        main.intravel3(root);
        System.out.println("");
        System.out.println("迭代后序遍历:");
        main.postrval2(root);
        System.out.println("");
        System.out.println("层序遍历:");
        main.levelOrder(root);
    }
    //建树
    TreeNode createTree(){
        Scanner sc=new Scanner(System.in);
        int temp=sc.nextInt();
        if(temp<=0)return null;
        TreeNode root=new TreeNode();
        root.val=temp;
        root.left=createTree();
        root.right=createTree();
        return root;
    }
    //先序
    void pretravel(TreeNode root){
        if(root==null)return;
        System.out.print(root.val+" ");
        pretravel(root.left);
        pretravel(root.right);
    }
    //中序
    void intravel(TreeNode root){
        if(root==null)return;
        intravel(root.left);
        System.out.print(root.val+" ");
        intravel(root.right);
    }
    //后序
    void postravel(TreeNode root){
        if(root==null)return;
        postravel(root.left);
        postravel(root.right);
        System.out.print(root.val+" ");
    }
    //迭代先序
    void pretravel2(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> s = new Stack<TreeNode>();
        s.push(root);
        while (!s.isEmpty()) {
            TreeNode node = s.pop();
            System.out.print(node.val+" ");
            if (node.right != null) {
                s.push(node.right);
            }
            if (node.left != null) {
                s.push(node.left);
            }
        }
    }
    void intravel2(TreeNode root) {
        if(root==null)
            return ;
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        List<TreeNode> list=new ArrayList<>();
        while(!stack.isEmpty()) {
            TreeNode peek = stack.peek();
            if(peek.left!=null&& !list.contains(peek.left)) {
                stack.push(peek.left);
                list.add(peek.left);
            }
            else {//左孩子为空,打印根结点,根结点出栈,右孩子进栈
                TreeNode pop = stack.pop();
                System.out.print(pop.val+" ");
                if(pop.right!=null)
                    stack.push(pop.right);
            }
        }
    }

    void intravel3(TreeNode root) {
        Stack<TreeNode> stack=new Stack<>();
        TreeNode p=root;
        while(p!=null||!stack.isEmpty()) {
            while(p!=null) {
                stack.push(p);
                p=p.left;
            }
            if(!stack.isEmpty()) {
                TreeNode temp=stack.pop();
                System.out.print(temp.val+" ");
                p=temp.right;
            }
        }
    }
    void postrval2(TreeNode root) {
        if(root==null)
            return ;
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        List<TreeNode> list=new ArrayList<>();
        while(!stack.isEmpty()) {
            TreeNode peek=stack.peek();
            if(peek.left!=null&&!list.contains(peek.left)) {
                stack.push(peek.left);
                list.add(peek.left);
            }
            else {
               if(peek.right!=null&&!list.contains(peek.right)) {
                   stack.push(peek.right);
                   list.add(peek.right);
               }
               else {
                   TreeNode pop = stack.pop();
                   System.out.print(pop.val+" ");
               }
            }
        }
    }
    //层序
    void levelOrder(TreeNode root) {
        List<TreeNode> list=new ArrayList<>();
        list.add(root);
        while(list.size()!=0) {
            TreeNode temp=list.get(0);
            if(temp.left!=null) list.add(temp.left);
            if(temp.right!=null) list.add(temp.right);
            list.remove(0);
            System.out.print(temp.val+" ");
        }
    }
}

输入是按照先序序列输,输一个打一个回车,结点为null的时候输入-1,表示为空,叶子节点要输两个-1,表示左右孩子均为空。
在这里插入图片描述
在这里插入图片描述

  • 20
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非递归遍历二叉树是指在不使用递归函数的情况下,对二叉树进行遍历方法。以下是三种非递归遍历二叉树方法: 1. 非递归中序遍历二叉树 中序遍历二叉树的顺序是:左子树 -> 根节点 -> 右子树。使用栈来保存未被访问的节点,具体步骤如下: 1)从根节点开始,将当前节点入栈。 2)如果当前节点有左子树,则将左子树入栈并进入左子树,重复步骤2,直到左子树为空。 3)从栈中弹出节点,访问该节点。 4)如果该节点有右子树,则将右子树入栈并进入右子树,重复步骤2、3、4。 2. 非递归先序遍历二叉树 先序遍历二叉树的顺序是:根节点 -> 左子树 -> 右子树。使用栈来保存未被访问的节点,具体步骤如下: 1)从根节点开始,将当前节点入栈。 2)从栈中弹出节点,访问该节点。 3)如果该节点有右子树,则将右子树入栈。 4)如果该节点有左子树,则将左子树入栈。 5)重复步骤2、3、4,直到栈为空。 3. 非递归后序遍历二叉树 后序遍历二叉树的顺序是:左子树 -> 右子树 -> 根节点。使用两个栈来实现,具体步骤如下: 1)将根节点入栈1。 2)从栈1中弹出节点,并将该节点入栈2。 3)如果该节点有左子树,则将左子树入栈1。 4)如果该节点有右子树,则将右子树入栈1。 5)重复步骤2、3、4,直到栈1为空。 6)从栈2中依次弹出节点并访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值