树与二叉树与二叉平衡排序树(上)

二叉树与二叉平衡树

在这里插入图片描述

简单介绍一下树

树的度:找到分支最多的节点,这个节点有多少分支,这棵树的度就为几。
分支最多的节点为D,它有三个分支
这棵树的度为3

深度

树的深度就是树的层数
深度为4

根节点与叶子节点

叶子节点:没有子节点的节点
这棵树的根节点是A
叶子节点为E,F,G,H

二叉树

树的度最高不超过2的树,称为二叉树

满二叉树

如果一个节点有子节点,那么他一定有两个节点并且叶子节点都在树的最后一层

完全二叉树

除了最后一层节点是满的,最后一层的节点都集中在左侧
满二叉树是完全二叉树

二叉树的遍历

在这里插入图片描述

前序遍历:先根次序遍历
根左右
先打根节点,再打左子树,再打右子树
1,2,4,5,3,6
中序遍历:中跟次序遍历
左根右
先打印左子树,在打印根节点在打印右子树
4,2,5,1,3,6
后序遍历:后根次序遍历
左右根
先打印左子树,在打印右子树,在打印根节点
4,5,2,6,3,1
以下是代码实现

 public static void firstRoot(TreeNode root){
        if (root == null)return;
        System.out.println(root.val);
        firstRoot(root.left);
        firstRoot(root.right);
    }
    
  public static void midRoot(TreeNode root){
        if (root == null)return;
        midRoot(root.left);
        System.out.println(root.val);
        midRoot(root.right);
    }

    public static void lastRoot(TreeNode root){
        if (root == null)return;
        lastRoot(root.left);
        lastRoot(root.right);
        System.out.println(root.val);
  	  }

建立一个二叉树

通过前序和中序建立一个二叉树。
给我们一个前序遍历和中序遍历我们来建立二叉树,首先我们要先找根节点,通过根节点再找到它的左子树和右子树,最后建立二叉树。
以下是代码实现

 	private static int getIndex(int[] arr , int target){
        for (int i = 0 ; i <arr.length ; i++){
            if (arr[i] == target)return i;
        }
        return 0;
    }

    public static TreeNode buildTree(int[] first,int[] mid){
        if (first == null || mid == null || first.length == 0 || mid.length == 0 || first.length != mid.length) return null;
        //从前序遍历中找到根节点
        TreeNode root = new TreeNode(first[0]);
        //在中序遍历中找到根节点位置的索引
        int rootIndex = getIndex(mid,root.val);
        //找到左子树的前序和中序
        int[] leftMid = Arrays.copyOfRange(mid,0,rootIndex);
        int[] leftFirst = Arrays.copyOfRange(first,1,rootIndex + 1);
        //找到右子树的前序和中序
        int[] rightMid = Arrays.copyOfRange(mid,rootIndex-1,mid.length);
        int[] rightFirst = Arrays.copyOfRange(first,rootIndex + 1,first.length);
        //递归构建左右子树
        TreeNode left = buildTree(leftFirst,leftMid);
        TreeNode right = buildTree(rightFirst,rightMid);
        //将左右子数添加到当前的根节点
        root.left = left;
        root.right = right;
        return root;
    }

通过后序和中序建立二叉树的做法与前序和中序建立差不多,后序的根结点是在最后一个。

二叉树的广度和深度优先搜索

深度优先搜索

 public static boolean dfs(TreeNode root,int target){
        if (root == null)return false;
        if (root.val == target)return true;
        return dfs(root.left,target) || dfs(root.right,target);
    }

广度优先搜索

public static boolean bfs(ArrayList<TreeNode> roots,int target){
        if (roots == null || roots.size() == 0)return false;
        ArrayList<TreeNode> childRoots = new ArrayList<>();
        for (TreeNode temp : roots){
            if (temp.val == target)return true;
            if (temp.left != null)childRoots.add(temp.left);
            if (temp.right != null)childRoots.add(temp.right);
        }
        return bfs(childRoots,target);
    }

    public static boolean bfs(TreeNode root,int target){
        ArrayList<TreeNode> roots = new ArrayList<>();
        roots.add(root);
        return bfs(roots,target);
    }

二叉树的比较

比较两个二叉树是否相等

    public static boolean compareTree(TreeNode root1,TreeNode root2){
        if (root1 == null && root2 != null || root1 != null && root2 == null)return false;
        if (root1 == null && root2 == null)return true;
        if (root1.val != root2.val)return false;
        return compareTree(root1.left,root2.left) && compareTree(root1.right,root2.right);
    }

如果左右子树互换

public static boolean compareTree2(TreeNode root1,TreeNode root2){
        if (root1 == null && root2 != null || root1 != null && root2 == null)return false;
        if (root1 == null && root2 == null)return true;
        if (root1.val != root2.val)return false;
        return compareTree(root1.left,root2.left) && compareTree(root1.right,root2.right)
                || compareTree(root1.left,root2.right) && compareTree(root1.right,root2.left);
    }

普利姆算法

在这里插入图片描述
我们要将所有点连通,并且让他们之间的距离最小
我们首先
1.任选一个点作为起点
在这里插入图片描述
2.找到与已连接部分路径最短的的点。
3.不能形成回路
在这里插入图片描述
如何用程序表示一个图
1.点集合
set集合 Set
2.边集合
二维数组· int[][] distance
在这里插入图片描述
准备工作

public class MapNode {
    public int val;
    public int index;
    public List<MapNode> neighbor;
    public MapNode(int val,int index){
        this.val = val;
        this.index = index;
        neighbor = new ArrayList<>();
    }
}

普利姆算法具体实现

public static MapNode getMapNodeByIndex(Set<MapNode> pointSet,int index){
        for (MapNode node : pointSet){
            if (node.index == index )return node;
        }
        return null;
    }
    public static void getMinDis(Set<MapNode> pointSet,int[][] distance,Set<MapNode> linkedPoint){
        MapNode start = null;
        MapNode end = null;
        int minDis = Integer.MAX_VALUE;
        //找到距离已有的点最近的点
        for (MapNode myPoint : pointSet){
            for (int i = 0 ; i < distance[myPoint.index].length ; i++){
                if (distance[myPoint.index][i] < minDis//找到比最小距离要小的点
                        && myPoint.index != i//除去自己到自己的距离
                        && !linkedPoint.contains(getMapNodeByIndex(pointSet,i))){
                        //已连接的点不能有序号为i的点
                    start = myPoint;
                    end = getMapNodeByIndex(pointSet,i);
                    minDis = distance[myPoint.index][i];
                }
            }
        }
        //将距离最近的点连接在一起
        start.neighbor.add(end);
        end.neighbor.add(start);
        linkedPoint.add(end);
    }
    public static void prim(Set<MapNode> pointSet,int[][] distance,MapNode begin){
        Set<MapNode> linkedPoint = new HashSet<>();
        linkedPoint.add(begin);
        while(linkedPoint.size() < pointSet.size()){
            getMinDis(pointSet,distance,linkedPoint);
        }
    }

克鲁斯卡尔算法

克鲁斯卡尔算法也叫加边法
1.找到最短的边
2.边不能重复
3.边的两个点不能出自同一连通区域(不能形成环)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是代码实现

 	public static List<MapNode> getMapNodeList( List<List<MapNode>> linkedMapNode, MapNode 	node){
        for (List<MapNode> mapNodes : linkedMapNode){
            if (mapNodes.contains(node))return mapNodes;
        }
        return null;
    }


    public static void getMinDis(Set<MapNode> pointSet,int[][] distance, List<List<MapNode>> linkedMapNode){
        //找到最短的边

        int minDis = Integer.MAX_VALUE;
        MapNode begin = null;
        MapNode end = null;
        List<MapNode> beginList = null;
        List<MapNode> endList = null;
        for (int i = 0 ; i < distance.length ; i++){
            for (int j = 0 ; j < distance[i].length ; j++){
                if (distance[i][j] < minDis && i != j){
                    MapNode a = getMapNodeByIndex(pointSet,i);
                    MapNode b = getMapNodeByIndex(pointSet,j);
                    List<MapNode> alist = getMapNodeList(linkedMapNode,a);
                    List<MapNode> blist = getMapNodeList(linkedMapNode,b);
                    if (alist != null && blist != null && alist == blist){
                        //判断是否出自同一部落
                        minDis = distance[i][j];
                        begin = a;
                        end = a;
                        beginList = alist;
                        endList = blist;
                    }
                }
            }
        }

        begin.neighbor.add(end);
        end.neighbor.add(begin);
        //看看这两个部落是否需要合并
        if (beginList == null && endList == null){
            //两个都是新的点
            List<MapNode> mapNodes = new ArrayList<>();
            mapNodes.add(begin);
            mapNodes.add(end);
            linkedMapNode.add(mapNodes);
        }else if (beginList != null && endList == null){
            //两个点其中一个是新的
            beginList.add(end);
        }else if (endList != null && beginList == null){
            endList.add(begin);
        }else if (beginList != null && endList != null){
            beginList.addAll(endList);
            linkedMapNode.remove(endList);
        }

        //判断这个边能不能连接
        //1.两个点都是新的
        //2.两个点其中一个是新的(其中一个点没有部落)
        //3.两个点出自不同的连通区域(两个点来自不同的部落)
        //同以上三点等效 ==== 两个点不能出自同一个部落

    }
    public static void kruskar(Set<MapNode> pointSet,int[][] distance){

        List<List<MapNode>> linkedMapNode = new ArrayList<>();//部落的集合
        while (linkedMapNode.size() == 1 && linkedMapNode.get(0).size() == pointSet.size()){
            //只能有一个部落,并且唯一的一个部落大小是和所有的点的集合大小一样
            getMinDis(pointSet,distance,linkedMapNode);

        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值