并查集(代码及详细注释)

并查集及其Java实现

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。一般在集合的关系查找中使用较多(两个元素是否属于同一集合)百度百科

  • Java代码以及测试类
import java.util.Arrays;
import java.util.Scanner;

public class UnionSearch {
    private int[] id;  //记录每个子集的“上司”(父节点)
    private int count;  //记录子集个数

    public UnionSearch(int N) {   //初始化并查集,开始每个节点父节点默认为自身
        id = new int[N];
        count = N;
        for(int i = 0; i < N; i++)
            id[i] = i;
    }

    public int getCount() {   //获取并集后的个数
        return count;
    }

    public int[] getId() {    //获得每个个体的“上司”数组(并不一定是”顶头上司“)
        return id;
    }

    public boolean connected(int p, int q) {  //判断两个个体是否在同一子集之中
        return find(p) == find(q);
    }

    public int find(int p) {   //寻找个体p的”顶头上司“(根节点),只有根节点的父节点是自身
        while(p != id[p])
            p = id[p];
        return p;
    }

    public void union(int p, int q){    //将个体p合并进个体q所在子集之中
        int pRoot = find(p);
        int qRoot = find(q);
        if(pRoot == qRoot)    //两个个体原本位于同一子集之中,无需操作
            return;
        id[pRoot] = qRoot;    //两个个体位于不同子集之中,需将p个体父节点修改为q节点的根节点即可
        count--;
    }

    public int[] rootArr(int N){   //返回每个个体的根节点(所在子集)数组
        int[] rootArr=new int[N];
        for (int i = 0; i < N; i++) {
            rootArr[i]=find(i);
        }
        return rootArr;
    }
}

class testUnion{   //测试类
    public static void main(String[] args) {
        Scanner r = new Scanner(System.in);
        int N = r.nextInt();   //初始化N个个体,0~N-1
        int M = r.nextInt();   //M组两两合并关系
        UnionSearch quickunion = new UnionSearch(N);  //初始化并查集
        for (int i = 0; i < M; i++) {    //输入M组合并关系数组
            int temp1=r.nextInt();
            int temp2=r.nextInt();
            quickunion.union(temp1,temp2);
        }
        System.out.println(quickunion.connected(1,2)); //判断两个节点是否在同一子集之中
        System.out.println(Arrays.toString(quickunion.getId()));   //得到合并后的每个节点的”上司“节点
        System.out.println(quickunion.getCount());  //得到合并后的子集个数
        System.out.println(Arrays.toString(quickunion.rootArr(N)));  //得到每个节点所在子集数组
    }
}
  • 输入输出测试样例
    运行结果
    博客中相关问题欢迎询问探讨,相互学习。QQ:1476154032,以上。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当我们需要查询大量数据时,通常需要使用分页查询,将结果分成多个页面返回给用户,以提高查询效率和用户体验。以下是使用Java代码实现分页查询的示例,带有注释说明每个重要步骤的作用。 ``` public List<User> findUsersByPage(int pageNum, int pageSize) { // 计算起始记录的索引 int startIndex = (pageNum - 1) * pageSize; // 构造SQL语句,使用LIMIT关键字来实现分页 String sql = "SELECT * FROM user LIMIT ?, ?"; try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { // 设置查询参数 ps.setInt(1, startIndex); ps.setInt(2, pageSize); // 执行查询,获取结果集 ResultSet rs = ps.executeQuery(); // 构造User对象列表,用于存放查询结果 List<User> users = new ArrayList<>(); // 遍历结果集,将每个记录转换为User对象并添加到列表中 while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setAge(rs.getInt("age")); // ...其他属性赋值 users.add(user); } // 返回查询结果 return users; } catch (SQLException e) { // 处理异常 e.printStackTrace(); return null; } } ``` 在这个示例中,我们使用了Java的JDBC API来连接数据库,并使用MySQL的LIMIT语句来实现分页查询。具体步骤如下: 1. 首先计算起始记录的索引,这个索引可以通过pageNum和pageSize计算得出。例如,如果pageNum=3,pageSize=10,则起始索引为20。 2. 构造SQL语句,使用占位符(?)来表示参数。这里我们使用了LIMIT语句来限制返回的记录数,第一个参数表示起始索引,第二个参数表示返回的记录数。注意,MySQL中LIMIT的起始索引是从0开始的。 3. 使用JDBC API获取数据库连接,创建PreparedStatement对象,并设置查询参数。在这个示例中,我们设置了两个参数,分别是起始索引和返回记录数。 4. 执行查询,获取结果集。在JDBC中,查询结果通常以ResultSet对象的形式返回。 5. 遍历结果集,将每个记录转换为User对象,并添加到User列表中。 6. 返回查询结果。 需要注意的是,在实际应用中,我们通常还需要对pageNum和pageSize进行合法性检查,防止出现非法参数导致的异常或安全问题。同时,还需要对查询语句中的关键字进行转义,防止SQL注入攻击。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值