二叉树遍历

首先二叉树的基本结构:

public class BinaryTree<E> {
    private TreeNode<E> root; //根节点

    public BinaryTree(){

    }
    public BinaryTree(TreeNode<E> root){
        this.root = root;
    }
   
}

class TreeNode<E>{
    private E value;
    private TreeNode left; //左孩子
    private TreeNode right; //右孩子
    private boolean visited = false;  //是否访问过,遍历器用

    public TreeNode(){}
    public TreeNode(E value){
        this.value = value;
    }
    ...省略get,set方法
}

先序遍历(先根遍历)

    递归算法:

     //前序遍历(递归)
    public List<TreeNode> preOrder(TreeNode treeNode){
        ArrayList<TreeNode> list = new ArrayList<>();
        if(treeNode==null){
            return list;
        }
        list.add(treeNode);
        list.addAll(preOrder(treeNode.getLeft()));
        list.addAll(preOrder(treeNode.getRight()));
        return list;
    }
  

    栈实现算法:

栈实现前序遍历较简单,由于每次先输出根节点,再输出左节点随后是右节点。因此处理逻辑是:
1、若栈非空则输出根节点,并出栈
2、如果存在右节点,右节点入栈
3、如果存在左节点,左节点入栈
4、重复第1步,直至栈空
代码:
//栈实现前序遍历
    public List<TreeNode> preOrderByStack(TreeNode treeNode){
        ArrayList<TreeNode> list = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList();
        if(root == null){
            return list;
        }
        stack.push(treeNode);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            list.add(node);
            if(node.getRight()!=null){
                stack.push(node.getRight());
            }
            if(node.getLeft()!=null){
                stack.push(node.getLeft());
            }
        }
        return list;
    }

中序遍历

    递归算法:

     //中序遍历(递归)
    public List<treenode>> inOrder(TreeNode treeNode){
        ArrayList<TreeNode>> list = new ArrayList<>();
        if(treeNode==null){
            return list;
        }

        list.addAll(inOrder(treeNode.getLeft()));
        list.add(treeNode);
        list.addAll(inOrder(treeNode.getRight()));
        return list;
    }

    栈实现算法:

栈的中序遍历需要套两层循环,由于需要先输出左节点,因此必须向下查找直到左节点为空才能输出。处理逻辑如下:
1、如果栈顶元素非空且左节点存在,将其入栈,重复该过程。若不存在则进入第2步
2、若栈非空,输出栈顶元素并出栈。判断刚出栈的元素的右节点是否存在,不存在重复第2步,存在则将右节点入栈,跳至第1步
代码:
   //栈实现中序遍历
    public List<TreeNode> inOrderByStack(TreeNode treeNode){
        ArrayList<TreeNode> list = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if(treeNode == null){
            return list;
        }
        TreeNode curr = treeNode;
        while(curr!=null || !stack.isEmpty()){
            while(curr!=null){
                stack.push(curr);
                curr = curr.getLeft();
            }
                curr = stack.pop();
                list.add(curr);
                curr = curr.getRight();
        }
        return list;
    }
   //栈实现中序遍历2
    public List<TreeNode> inOrderByStack2(TreeNode treeNode) {
        ArrayList<TreeNode> list = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if (treeNode == null) {
            return list;
        }
        stack.push(treeNode);
        while(!stack.isEmpty()){
            while(treeNode.getLeft()!=null){
                treeNode = treeNode.getLeft();
                stack.push(treeNode);
            }

            TreeNode pop = stack.pop();
            list.add(pop);

            if(pop.getRight()!=null){
                treeNode = pop.getRight();
                stack.push(treeNode);
                continue;
            }
        }

        return list;
    }

后序遍历

    递归算法:

 //后序遍历(递归)
    public List<TreeNode> postOrder(TreeNode treeNode){
        ArrayList<TreeNode>> list = new ArrayList<>();
        if(treeNode==null){
            return list;
        }
        list.addAll(postOrder(treeNode.getLeft()));
        list.addAll(postOrder(treeNode.getRight()));
        list.add(treeNode);
        return list;
    }

    栈实现算法:

后序遍历在中序的双层循环的基础上需要加入一个记录,专门记录上一次出栈的节点。步骤如下:
1、如果栈顶元素非空且左节点存在,将其入栈,重复该过程。若不存在则进入第2步(该过程和中序遍历一致)
2、判断上一次出栈节点是否当前节点的右节点,或者当前节点是否存在右节点,满足任一条件,将当前节点输出,并出栈。否则将右节点压栈。跳至第1步
代码
     //栈实现后序遍历
    public List<TreeNode> postOrderByStack(TreeNode treeNode) {
        ArrayList<TreeNode> list = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if (treeNode == null) {
            return list;
        }
        stack.push(treeNode);
        TreeNode lastPop = null;
        while(!stack.isEmpty()){
            while(treeNode.getLeft()!=null){
                treeNode = treeNode.getLeft();
                stack.push(treeNode);
            }
            TreeNode curr = stack.peek();
            if(curr!=null && lastPop!=null && lastPop == curr.getRight()) {
                TreeNode pop = stack.pop();
                pop.setVisited(true);
                list.add(pop);
            }
            curr = stack.peek();
            //如果没有isVisited属性,那么可以将访问过的节点放到一个统一的hashset(或hashmap)中,用!set.contains(curr.getRight())来代替curr.getRight().isVisited()==false
            if(curr!=null && curr.getRight() != null && curr.getRight().isVisited()==false){
                stack.push(curr.getRight());
                treeNode = curr.getRight();
                continue;
            }
            if(!stack.isEmpty()) {
                lastPop = stack.pop();
                lastPop.setVisited(true);
                list.add(lastPop);
            }

        }
        return list;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值