数据结构第四章 并查集

本文详细介绍了数据结构中的并查集,包括测试程序、寻根及路径压缩、查询集合节点数、集合合并以及判断节点是否在同一集合。通过递归查询根节点实现集合判断,通过调整根节点的父节点实现集合合并。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 并查集顾名思义有两个功能,,

一是查询两个节点在不在一个集合,这可以通过递归对父节点的应用实现查询根节点,只要两节点根节点相同则在一个集合

二是把两个集合并在一起,这可以通过把一个集合的根节点的父节点指针指向另一个集合的根节点。

目录

1.测试程序

2.寻根,并压缩路径的方法 

 3.告诉根节点集合有多少节点的方法

4.集合的并运算 

 5.确认两节点是否在一集合

全部代码 


1.测试程序

public static void main(String[] args) {
		int[] data = {-1, 0, -1, 0, 2, -1, 0, 4, 5, 8};
        //测试基本操作
		for (int i = 0; i < 10; i++) {
			data[i] = findRoot(data, i);
			tellRoot(data, i);	
		}
		System.out.println(Arrays.toString(data));
		System.out.println("0,2在一个集合:"+areAGroup(data, 0, 2));
		Union(data, 0, 2);
        //测试两集合结合后的效果
		System.out.println(Arrays.toString(data));
		System.out.println("0,2在一个集合:"+areAGroup(data, 0, 2));
		
	}

2.寻根,并压缩路径的方法 

//寻找根节点,并同时压缩路径的方法:输入数组和节点位置,将节点内容从父节点改为根节点
	public static int findRoot(int[] deposit, int node) {
		if (deposit[node] >= 0) {
			return findRootDetail(deposit, deposit[node]);
		} else {
			return deposit[node];//本身是根节点,直接返回节点存储值即可
		}	
	}
	public static int findRootDetail(int[] deposit, int node) {
		if(deposit[node] < 0) {//如果该节点内容小于0则该节点为根节点
			return node; 
		} else {
			return findRootDetail(deposit, deposit[node]);//路径压缩
		}
	}

 3.告诉根节点集合有多少节点的方法

//告诉根节点,有新节点以此点为根节点的方法
	public static void tellRoot(int[] deposit, int node) {
		if(deposit[node] >= 0) { //如果本身是根节点不用减减,因为本来就有-1
			tellRootDetail(deposit, deposit[node]);
		}
	}
	public static void tellRootDetail(int[] deposit, int node) {
		if(deposit[node] < 0) {
			deposit[node]--;//告诉根节点,有新节点以此点为根节点
		} else {
			tellRootDetail(deposit, deposit[node]);
		}
	}

4.集合的并运算 

//集合的并运算
	public static void Union(int[] deposit, int root1, int root2) {
		//小集合并入大集合树高增长慢
		if (deposit[root1] > deposit[root2]) {
			deposit[root2] += deposit[root1];//root2节点数增加
			deposit[root1] = root2;//小树根节点父节点改为大树根节点
		} else {
			deposit[root1] += deposit[root2];//root2节点数增加
			deposit[root2] = root1;
		}
	}

 5.确认两节点是否在一集合

//确认两节点是否在一集合
	public static boolean areAGroup(int[] deposit, int node1, int node2) {
		int node1Root = findRoot(deposit, node1);
		int node2Root = findRoot(deposit, node2); 
		//由于根节点是-1,有三种情况两节点在一集合,1.两节点指向的根节点的量都为正数且相同,2.节点1的根节点指针指向节点2,节点2根节点指针为负数 3.第2种情况反过来
		if (node1Root == node2Root || node1Root == node2 || node2Root == node1) {
			return true;
		} else {
			return false;
		}
	}

全部代码 

import java.util.*;
public class test {
	public static void main(String[] args) {
		int[] data = {-1, 0, -1, 0, 2, -1, 0, 4, 5, 8};
		for (int i = 0; i < 10; i++) {
			data[i] = findRoot(data, i);
			tellRoot(data, i);	
		}
		System.out.println(Arrays.toString(data));
		System.out.println("0,2在一个集合:"+areAGroup(data, 0, 2));
		Union(data, 0, 2);
		System.out.println(Arrays.toString(data));
		System.out.println("0,2在一个集合:"+areAGroup(data, 0, 2));
		
	}
	//寻找根节点,并同时压缩路径的方法:输入数组和节点位置,将节点内容从父节点改为根节点
	public static int findRoot(int[] deposit, int node) {
		if (deposit[node] >= 0) {
			return findRootDetail(deposit, deposit[node]);
		} else {
			return deposit[node];//本身是根节点,直接返回节点存储值即可
		}	
	}
	public static int findRootDetail(int[] deposit, int node) {
		if(deposit[node] < 0) {//如果该节点内容小于0则该节点为根节点
			return node; 
		} else {
			return findRootDetail(deposit, deposit[node]);//路径压缩
		}
	}
	
	//告诉根节点,有新节点以此点为根节点的方法
	public static void tellRoot(int[] deposit, int node) {
		if(deposit[node] >= 0) { //如果本身是根节点不用减减,因为本来就有-1
			tellRootDetail(deposit, deposit[node]);
		}
	}
	public static void tellRootDetail(int[] deposit, int node) {
		if(deposit[node] < 0) {
			deposit[node]--;//告诉根节点,有新节点以此点为根节点
		} else {
			tellRootDetail(deposit, deposit[node]);
		}
	}
	
	//集合并运算
	public static void Union(int[] deposit, int root1, int root2) {
		//小集合并入大集合树高增长慢
		if (deposit[root1] > deposit[root2]) {
			deposit[root2] += deposit[root1];//root2节点数增加
			deposit[root1] = root2;//小树根节点父节点改为大树根节点
		} else {
			deposit[root1] += deposit[root2];//root2节点数增加
			deposit[root2] = root1;
		}
	}
	
	//确认两节点是否在一集合
	public static boolean areAGroup(int[] deposit, int node1, int node2) {
		int node1Root = findRoot(deposit, node1);
		int node2Root = findRoot(deposit, node2); 
		//由于根节点是-1,有三种情况两节点在一集合,1.两节点指向的根节点的量都为正数且相同,2.节点1的根节点指针指向节点2,节点2根节点指针为负数 3.第2种情况反过来
		if (node1Root == node2Root || node1Root == node2 || node2Root == node1) {
			return true;
		} else {
			return false;
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值