算法:二叉树相关题型总结

前言

    这个博客会列出常见的有关二叉树的面试题目并给出算法思想。总体目录如下:
  • DFS(深度优先遍历)
        先序遍历
        中序遍历
             1.判断是否是二叉搜索树
             2.根据二叉搜索树构建双向链表
        后序遍历
        三合一非递归

  • BFS(广度优先遍历)
        层序遍历
             1.二叉树的深度
             2.之字形打印二叉树

  • 寻找双亲
        1.单个结点的双亲
        2.两个结点的公共双亲
        3.在二叉搜索树中寻找最近公共祖先

  • 其他
        1.根据传入数组创建树
        2.在二叉树中寻找值
        3.判断二叉树是否对称
        4.返回二叉树的镜像树
        3.判断传入数组是否是某二叉搜索树的后序遍历

DFS的递归写法

     前中后序的递归遍历非常简单,如下:

    public void preOrder(BtNode cur){
   //递归-先序遍历
        if(cur == null)return;
        System.out.print(cur.data+" ");
        preOrder(cur.left);
        preOrder(cur.right);
    }

    public void inOrder(BtNode cur){
   //递归-中序遍历
        if(cur == null)return;
        inOrder(cur.left);
        System.out.print(cur.data+" ");
        inOrder(cur.right);
    }

    public void pastOrder(BtNode cur){
   //递归-后序遍历
        if(cur == null)return;
        pastOrder(cur.left);
        pastOrder(cur.right);
        System.out.print(cur.data+" ");
    }

DFS的非递归写法

先序遍历

     思想:从栈中弹出一个结点,保存当前结点值,并将其左右子树压入栈中。(注意如果要严格遵从先左后右的规则, 需要先压右孩子再压左孩子,这样现出来的才能是左孩子。)很明显上述过程需要进行迭代,用栈不空作为条件。

    public List<Integer> nicePreOrder(){
   //非递归-先序遍历
        List<Integer> list = new ArrayList<>();
        if(root == null)return list;

        Stack<BtNode> stack = new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
   
            BtNode cur = stack.pop();
            list.add(cur.data);
            if(cur.right!= null)stack.push(cur.right);
            if(cur.left != null)stack.push(cur.left);
        }
        return list;
    }

中序遍历

     思想:将当前结点一直朝左下延伸,将一路的结点放入栈,直到当前结点没有左孩子。这一步完成后将栈顶元素出栈,对其进行操作(打印/放入表等),再对右孩子进行迭代。
public List<Integer> niceInOrder(){
   //非递归-中序遍历
        List<Integer> list = new ArrayList<>();
        if(root == null)return list;

        BtNode cur = root;
        Stack<BtNode> stack = new Stack<>();
        while(!stack.isEmpty() || cur != null){
   
            while(cur != null){
   
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur.data);
            cur = cur.right;
        }
        return list;
    }

后序遍历

     思想:同中序遍历,先把一路的左孩子入栈,不同的是需要对右孩子进行标记,操作过右孩子之后才可以操作根节点元素,没有操作过右孩子要把当前结点再次入栈。
public List<Integer> nicePastOrder(){
   //非递归-后序遍历
        List<Integer> list = new ArrayList<>();
        if(root == null)return list;

        BtNode tag = null;
        BtNode ptr = root;
        Stack<BtNode> st = new Stack<>();
        while (!st.empty() || ptr != null) {
   
            //先把左边的一溜都放进去
            while (ptr != null) {
   
                st.push(ptr);
                ptr = ptr.left;
            }
            ptr = st.pop
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值