二叉树的回顾(java实现)

1.对二叉树进行简单的复习。

在这里插入图片描述

1.普通二叉树

  • 每个节点至多只有两个子树(即不存在度大于2的节点)。

基本形态

  • 五种
    在这里插入图片描述

A.空二叉树 B.只有根节点 C.只有左子树 D.只有右子树
E.左右子树都有

遍历方式

个人觉得树的遍历或者做关于树的的题目,一定不要陷下去,要从宏观的角度去看待。
不管那颗树多深多长,明确只有根节点,左节点,右节点。

a.先序遍历 本质:根->左->右

在这里插入图片描述
顺序:

左子树右子树
12,34,5,6,7,8,9

宏观上看

在这里插入图片描述

微观上看
在这里插入图片描述

这里的7肯定就在8前面了。
在这里插入图片描述
以下同理

b.中序遍历 本质:左->根->右

在这里插入图片描述

左子树右子树
2,315,4,7,8,6,9

宏观上看

在这里插入图片描述

c.后序遍历 本质:左->右->根

在这里插入图片描述

左子树右子树
3,25,8,7,9,6,41

宏观上看
在这里插入图片描述

d.层序遍历 按树的层数来进行

1,2,4,3,5,6,7,9,8

在这里插入图片描述

e.建立

本质:不断的查找(根)结点,进行插入的过程。

下面是 序遍历加序遍历 建立的二叉树(前序只知道根节点,还需中序确认左右子树大小,这里也可用其他搭配)

private static HashMap<Integer, Integer> indexMap;

public static TreeNode buildTree(int[] pre, int[] in) {
   int n = pre.length;
   indexMap = new HashMap<Integer, Integer>();
   for (int i = 0; i < n; i++) {
   indexMap.put(in[i], i);
          // 1.构造中序哈希映射,帮助我们快速定位根节点
          //2.定位到中序根节点就可求出左右大小
      }
	return Build(pre, in, 0, n - 1, 0, n - 1);
}

public static TreeNode Build(int[] pre, int[] in, int pre_left, int pre_right, int in_left, int in_right) {
   if (pre_left > pre_right) {
   		return null;
   }
   // 前序遍历中的第一个节点就是根节点
   int pre_root = pre_left;
   // 在中序遍历中定位根节点
   int in_root = indexMap.get(pre[pre_root]);

   //本质上建立根节点,然后进行拼接
   TreeNode root = new TreeNode(pre[pre_root]);

   // 得到左子树中的节点数目
   //[->左<-,根,右]
   int size = in_root - in_left;

//root.左树=前:[根,->左<-,右]+ 中:[->左<-,根,右]
root.left = Build(pre, in, pre_left + 1, pre_left + size, in_left, in_root - 1);

//root.右树=前:[根,左,->右<-]+ 中:[左,根,->右<-]
root.right = Build(pre, in, pre_left + size + 1, pre_right, in_root + 1, in_right);

   //宏观上就已经建好了,剩下的只是子问题了
   return root;
}
//前序遍历
public static void PreOrder(TreeNode T) {
   if (T != null) {
   		System.out.print(T.val + " ");
   		PreOrder(T.left);
   		PreOrder(T.right);
   }
}
//中序遍历
public static void inOrder(TreeNode T) {
   if (T != null) {
       inOrder(T.left);
       System.out.print(T.val + " ");
       inOrder(T.right);
   }
}
//后续遍历
public static void hostOrder(TreeNode T) {
   if (T != null) {
       hostOrder(T.left);
       hostOrder(T.right);
       System.out.print(T.val + " ");
    }
}
//层序遍历
public static void levelOrder(TreeNode T) {
    Queue<TreeNode> q = new LinkedList<>();//队列先进先出
    q.add(T);//头入队
    while (!q.isEmpty()) {
        int k = q.size();
        for (int i = 0; i < k; i++) {
             TreeNode t = q.poll();
             System.out.print(t.val + " ");
             if (t.left != null)
                 q.add(t.left);
             if (t.right != null)
                 q.add(t.right);
            }
        }
    }
public static void main(String[] args) {
  int[] per = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  int[] in = {2, 3, 1, 5, 4, 7, 8, 6, 9};
  TreeNode tree = new TreeNode();
  tree = buildTree(per, in);
  System.out.print("前序遍历:");
  PreOrder(tree);

  System.out.println();
  System.out.print("中序遍历:");
  inOrder(tree);

  System.out.println();
  System.out.print("后序遍历:");
  hostOrder(tree);

  System.out.println();
  System.out.print("层序遍历:");
  levelOrder(tree);
  }
}
public 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;
        }
}

在这里插入图片描述

二叉排序树

a.二叉排序树

1.别名:二叉搜索树,二叉查找树
2.左子树节点值<根节点值<右子树节点值
3.对其进行中序遍历,可得到一个递增序列

**1.查找:就像二分查找一样。例如查找2.
在这里插入图片描述
**2.插入:**找到合适位置的位置。新插入的数据一般都是在叶子节点上。例如插入1
在这里插入图片描述
3.删除
有三种情况
1.要删除的节点,没有孩子,那就直接删除。删1
在这里插入图片描述

2.要删除的节点,只有左孩,或者右孩。删2
在这里插入图片描述

3.要删除的节点,左右孩都有。删除30
在这里插入图片描述
说明:先找到这个节点的右子树中的最小节点35,把他替换到要删除的节点。最后删掉这个最小节点。
4.代码

public class Search {
public static void main(String[] args) {
        TreeNode root=new TreeNode();
        int[] k = {5,3,6,2,4,7};

        for (int i = 0; i < k.length; i++) {
            Insert(root,k[i]);//插入
            if(Find(root,k[i]))//查找
                System.out.println(k[i]+":插入成功");
        }
        root=Delete(root,2);
        if(!Find(root,2))//查找
            System.out.println(2+":删除成功");

    }
public static void Insert(TreeNode root,int key){//插入
        if(root==null){
            root=new TreeNode(key);
            return ;
        }
        TreeNode p=root;
        while(p!=null) {//遍历然后插入
            if(p.val>key)//放到左边
            {
                if(p.left==null){
                    p.left=new TreeNode(key);
                    return ;
                }
                p=p.left;
            }
            else if(p.val<key)//放到右边
            {
                if(p.right==null){
                    p.right=new TreeNode(key);
                    return ;
                }
                p=p.right;
            }
            else if(p.val==key)
                return ;
        }

    }
public static boolean Find(TreeNode root,int key){//查找
       while(root!=null){
           if(root.val==key)
               return true;
           else if(root.val>key)
               root=root.left;
           else
               root=root.right;
       }
        return false;
    }
public static TreeNode Delete(TreeNode root, int key) {
        TreeNode root1 = root;//记录要删除数字的那个节点
        TreeNode root1_farther = null;//记录root1的父节点

        while (root1 != null && root1.val != key) {
            root1_farther = root1;
            if (key > root1.val) root1 = root1.right;
            else root1 = root1.left;
        }
        //要删除的数字找不到
        if (root1 == null)
            return root;

        //如果要删除的左右都有,那就让它变成1,2那种情况。
        if (root1.left != null && root1.right != null) {
            TreeNode min = root1.right;
            TreeNode min_farther = root1;
            while (min.left != null) {//找右子树那个最小的
                min_farther = min;
                min = min.left;
            }
            root1.val = min.val;
            root1 = min;//这个就是要删除的东西
            root1_farther = min_farther;
        }

        //开始确认要删除的数字的孩子情况。
        //这里删除的就是root1这个节点
        TreeNode child = null;//用来记录要删除的root1的下面那些东西。
        if (root1.left != null)
            child = root1.left;

        else if (root1.right != null)
            child = root1.right;

        else if(root1.left==null&&root.right==null)
            child = null;

        //遇到删除根节点的情况
        if (root1_farther == null)
            root = child;

        //要删除的在左边
        else if (root1_farther.left == root1)
            root1_farther.left = child;

        //要删除的在右边
        else root1_farther.right = child;

        return root;
    }
}


在这里插入图片描述

满二叉树

高度为h,有由2^h-1个节点构成的二叉树。
在这里插入图片描述

完全二叉树

除了最后一层都满了,并且最后一层的所有节点都集中在最左边。
在这里插入图片描述

平衡二叉树(AVL树)

平衡二叉搜索树(英语:Balanced Binary Search Tree)是一种结构平衡的二叉搜索树,它是一种每个节点的左右两子树**高度差都不超过一的二叉树。**它能在O({\displaystyle \log n}\log n)内完成插入、查找和删除操作,最早被发明的平衡二叉搜索树为AVL树。

常见的平衡二叉搜索树有:

  • AVL树
  • 红黑树
  • Treap
    – 来自维基百科。

若有错误,还请指正。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值