二叉树复习

这篇博客介绍了二叉树的相关知识点,包括前驱和后继的概念、满二叉树的节点数量、二叉树的性质以及完全二叉树的深度计算。重点讲解了如何根据前序和中序遍历构建二叉树,以及如何找到二叉树的最近公共祖先。此外,还讨论了将搜索二叉树转化为双向链表的方法。内容涵盖递归和栈的应用,适合巩固数据结构与算法的学习。
摘要由CSDN通过智能技术生成

知识点:


1.前驱只有一个,后继有N个
2.满二叉树,k层,结点总数2^k-1个
3.性质:
    1) 一棵二叉树,叶结点数n0个,度为2的非叶结点数n2个 => n0 = n2+1
    完全二叉树
    2)n个结点的完全二叉树的深度k 为log(n+1) 上取整
    3)从上至下,从左至右,的顺序 对所有结点从0开始编号:
        `父亲节点为下标 -> 左孩子2i+1,右孩子2i+2
        `孩子(左/右)节点下标i -> 父亲(i-1)/2
4.根据前序,中序创建一棵树(后面有一道相关编程题):
    通过前序来找根节点,中序找前序找的根节点的下标,左边为左树,右边为右树
5.二叉树是非线性数据结构

相关习题:


1.遍序递归:
    子问题思路,遍历思路.注意list创建问题. 比较简单,不多说

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


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

public class Main {

    List<Integer> list = new ArrayList<Integer>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null){
            return list;
        }
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return list;
    }

    public List<Integer> preorderTraversal1(TreeNode root) {
        List<Integer> list1 = new ArrayList<>();
        if(root == null){
            return list1;
        }
        list1.add(root.val);
        List<Integer> leftNode = preorderTraversal(root.left);
        list1.addAll(leftNode);
        List<Integer> rightNode = preorderTraversal(root.right);
        list1.addAll(rightNode);
        return list1;
    }
}


2.二叉树的最近公共祖先:
    方法一:列出公共祖先的几种情况:1.一个为root -> root. 2.左树两个->左树 3.右树两个 -> 右树 4.左树一个,右树一个->公共祖先root
    方法二: 用栈,把 p的所有路径存一份 q的所有路径存一份 让size相等,再一起出栈,值相同的时候,就是公共祖先
        难点-怎么存入栈?--不空则入栈,比较值是否为p/q是返回true,递归左,递归右,若是true`返回,最后真的不是,让它出栈,返回false

import java.util.Stack;

class TreeNode{
    char val;
    TreeNode left;
    TreeNode right;

    public TreeNode(char val){
        this.val = val;
    }
}

public class Main {


    //方法一:公共祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null){
            return null;
        }
        if (root == p || root == q){
            return root;
        }

        TreeNode rootLeft = lowestCommonAncestor(root.left,p,q);
        TreeNode rootRight = lowestCommonAncestor(root.right,p,q);

        if(rootLeft != null && rootRight != null){
            return root;
        }else if(rootLeft != null){
            return rootLeft;
        }else{
            return rootRight;
        }
    }


    //方法二:公共祖先 利用栈
    public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || p == null || q == null){
            return null;
        }
        Stack<TreeNode> s1 = new Stack<>();
        getPath(root,p,s1);

        Stack<TreeNode> s2 = new Stack<>();
        getPath(root,q,s2);

        int size1 = s1.size();
        int size2 = s2.size();

        if(size1>size2){
            int tmp = size1-size2;
            while (tmp > 0){
                s1.pop();
                tmp--;
            }
        }else{
            int tmp = size2-size1;
            while (tmp > 0){
                s2.pop();
                tmp--;
            }
        }

        while (!s1.isEmpty() && !s2.isEmpty()){
            if(s1.peek() == s2.peek()){
                return s1.peek();
            }else{
                s1.pop();
                s2.pop();
            }
        }
        return null;

    }
    public static boolean getPath(TreeNode root, TreeNode node, Stack<TreeNode> s){
        if(root == null || node == null){
            return false;
        }
        s.push(root);
        if(root == node){
            return true;
        }
        boolean ret1 = getPath(root.left,node,s);
        if(ret1){
            return true;
        }

        boolean ret2 = getPath(root.right,node,s);
        if(ret2){
            return true;
        }

        s.pop();
        return false;

    }

}


3.输入一棵搜索二叉树,将该二叉树转化为一个双向链表:
    第一步:排序:利用中序遍历
    第二步:双向链表: 用pre 将他们串起来

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

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


public class Main {

    public TreeNode prev;

    public void ConvertChild(TreeNode root) {

        if(root == null) return;

        ConvertChild(root.left);

        root.left = prev;
        if(prev != null){
            prev.right = root;
        }
        prev = root;

        ConvertChild(root.right);

    }


    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null){
            return null;
        }
        ConvertChild(pRootOfTree);
        TreeNode head = pRootOfTree;
        while(head.left != null){
            head = head.left;
        }
        return head;
    }
}


4.根据一棵树的前序遍历和中序遍历构造二叉树
    第一步:把前序遍历的值先构建根节点
    第二步:在中序遍历数组,找到根节点的位置i,有begin,end控制遍历长度
    第三步:分别构建左树和右树

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

    TreeNode(int val) { this.val = val; }

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

public class Solution {

    public int indix;

    public int findRootIndix(int val, int[] inorder, int begin, int end){
        for (int i = begin; i <= end ; i++) {
            if(val == inorder[i]){
                return i;
            }
        }
        return -1;

    }

    public TreeNode buildTreeChild(int[] preorder, int[] inorder, int begin, int end) {
        if(begin > end){
            return null;
        }
        TreeNode root = new TreeNode(preorder[indix]);
        int rootIndix = findRootIndix(preorder[indix],inorder,begin,end);
        indix++;
        root.left = buildTreeChild(preorder,inorder,begin,rootIndix-1);
        root.right = buildTreeChild(preorder,inorder,rootIndix+1, end);

        return root;
    }



    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }

}

这些题都挺经典的,可以去力扣啊,牛客啊 找一找 坐一坐 冲啊!!!小伙伴们,一起为梦想努力吧

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值