并查集数据结构java源码

在网上看到一个题目:

给定一个字符串的集合,格式如:。要求将其中交集不为空的集合合并,要求合并完成的集合之间无交集,例如上例应输出

(1) 请描述你解决这个问题的思路;

(2) 给出主要的处理流程,算法,以及算法的复杂度;

(3) 请描述可能的改进。

其中一个解决方案是使用并查集,(数据结构中有,但已经忘了囧) 所以,百度了一下,主要参考了一个博主的

文章http://blog.csdn.net/dm_vincent/article/details/7655764  ,思路讲得很清楚,但是在代码实现上并不具一般应用性,为了再复习一下,用java泛型实现了一个并查集结构,可用于整数,字符串等等集合以及自定义数据类型。

Union_Find类:

package com.algorithms;

import java.util.HashMap;

/**
 * 并查集,数据结构
 * 采用泛型编程
 * 采用指向父节点方式实现,即map.get(key)的值是父节点的key,根节点的key和value相等,也是一个并查集的入口
 * @author "zhshl"
 * @date	2014-10-20
 *
 */
public class Union_Find<T> {
	private HashMap<T,T> unionMap=new HashMap<T, T>(); //记录节点之间的关系
	private  HashMap<T,Integer> unionSize=new HashMap<T, Integer>();///某个树的大小,某一个并查集的大小
	private int count=0;///并查集数目

	/**
	 * 获取并查集总数
	 * @return
	 */
	public int getCount(){
		return count;
	}

	/**
	 * 返回key属于的并查集的根的value,如果不存在key则返回NULL
	 * @param key
	 * @return
	 */
	public T find(T key){

		if(!unionMap.containsKey(key)){
			return null;
		}

		T value=unionMap.get(key);
		while(!value.equals(key)){
			///如果key和value不相等,则不是根节点

			///路劲压缩,将该节点的父节点指向其爷爷节点
			unionMap.put(key, unionMap.get(unionMap.get(key)));

			key=value;
			if(!unionMap.containsKey(key)){
				return null;
			}
			value=unionMap.get(key);
		}
		return value;
	}

	/**
	 * 将key1,key2加入并查集
	 * @param key1
	 * @param key2
	 */
	public void union(T key1,T key2){
		///首次加入则存入map中
		if(!unionMap.containsKey(key1)){
			unionMap.put(key1, key1);
			unionSize.put(key1, 1);
			count++;
		}
		if(!unionMap.containsKey(key2)){
			unionMap.put(key2, key2);
			unionSize.put(key2, 1);
			count++;
		}

		T root1=find(key1);
		T root2=find(key2);

		if(root1.equals(root2)){
			///如果已经属于同一个并查集,直接返回
			return ;
		}

		if(unionSize.get(root1)>unionSize.get(root2)){
			////第一个并查集包含节点多时, 让第二颗树根节点指向第一颗树根节点,并修改对应的并查集大小
			unionMap.put(root2, root1);

			int size=unionSize.get(root1)+unionSize.get(root2);
			unionSize.put(root1, size);

		}else{
			unionMap.put(root1, root2);
			int size=unionSize.get(root1)+unionSize.get(root2);
			unionSize.put(root2, size);
		}

		count--;////总并查集数目减少一

	}

}

测试代码类:

package com.algorithm.test;

import com.algorithms.Union_Find;

public class Union_Find_Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

			Union_Find<String> uf=new Union_Find<String>();
			uf.union("s1", "s2");
			uf.union("s3", "s4");
			uf.union("s1", "s3");

			uf.union("s5", "s6");
			uf.union("s6", "s7");

			String str1=uf.find("s5");
			String str2=uf.find("s2");

		/*
			Union_Find<Integer> uf2=new Union_Find<Integer>();
			uf2.union(1, 2);
			uf2.union(3, 2);
			uf2.union(4, 2);
			uf2.union(5, 2);
			uf2.union(3, 5);
			uf2.union(2, 4);*/

			System.out.println(str1+":::::"+str2);
	}

}
时间: 2024-10-12 21:07:07

并查集数据结构java源码的相关文章

tomcat集群实现源码级别剖析

随着互联网快速发展,各种各样供外部访问的系统越来越多且访问量越来越大,以前Web容器可以包揽接收-逻辑处理-响应整个请求生命周期的工作,现在为了构建让更多用户访问更强大的系统,人们通过不断地业务解耦.架构解耦将web容器的逻辑处理抽离交由其他中间件处理,例如缓存中间件.消息队列中间件.数据存储中间件等等.Web容器负责的工作可能越来越少,但是它确实必不可少的部分,它负责接收用户请求并分别调用各个服务最后响应.可以说目前最受欢迎的web容器是用Java写的tomcat小猫,由于生产上的tomcat

如何阅读Java源码 阅读java的真实体会

刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码很漂亮,但我绝不建议你一开始就读它.我文中会专门谈到这个,暂时不展开. 强烈

Java源码阅读的真实体会

原文:http://zwchen.iteye.com/blog/1154193 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的

JAVA源码解读---HashMap目录扩展的奥秘

摘要:为了探索JAVA1.7源码中HashMap类数据的组织方法与目录扩展方法,本文通过对JAVA1.7源码中HashMap类源码的阅读与分析,得出结论:hashmap中存储数据的数据结构采用的是链表数组,目录是个数组,数组的成员是链表.冲突解决方法:典型的链地址法,冲突后,在链表头部插入数据.目录扩展方法:已二倍的方式扩展,一直到目录的最大上限.目录扩展的触发条件:装载因子的方式触发.从java中hashmap的实现可以看出,桶数据的组织方式并不是一种非常高效的方式.对检索效率不利.同时,数据

《Java源码分析》:线程池 ThreadPoolExecutor

<Java源码分析>:线程池 ThreadPoolExecutor ThreadPoolExecutor是ExecutorService的一张实现,但是是间接实现. ThreadPoolExecutor是继承AbstractExecutorService.而AbstractExecutorService实现了ExecutorService接口. 在介绍细节的之前,先介绍下ThreadPoolExecutor的结构 1.线程池需要支持多个线程并发执行,因此有一个线程集合Collection来执行

Java源码之LinkedList

Java源码之LinkedList 转载请注意出处:http://blog.csdn.net/itismelzp/article/details/51620311 一.LinkedList概述 本文采用jdk1.8进行分析. LinkedList实现了List,Deque接口的双向链表,实现了链表的所有可选操作,并且可有null值.查找某个值的时候必须从头到尾的遍历链表.它是非线程安全的,当多个线程结构化修改同一链表时需要加上同步处理.(程结构化修改包括:添加.删除,不包括:修改值)可使用Col

《Java源码分析》:Java NIO 之 Buffer

<Java源码分析>:Java NIO 之 Buffer 在上篇博文中,我们介绍了Java NIO 中Channel 和Buffer的基本使用方法,这篇博文将从源码的角度来看下Buffer的内部实现. 在Java API文档中,对Buffer的说明摘入如下: Buffer:是一个用于特定基本数据类型的容器.这里的特定基本数据类型指的是:除boolean类型的其他基本上数据类型. 缓冲区是特定基本数据类型元素的线性有限序列.除内容外,缓冲区饿基本属性还包括三个重要的属性,如下: 1.capaci

[收藏] Java源码阅读的真实体会

收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧,如果你从来没有学过Java,或是任何一门编程语言如C++,一开始去啃<Core Java>,你是很难从中吸收到营养的,特别是<深入Java虚拟机>这类书,别人觉得好,未必适合现在的你. 虽然Tomcat的源码

如何阅读Java源码?

阅读本文大概需要 3.6 分钟. 阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃<Core Java>,那样是很难有收获的,尤其是<深入Java虚拟机>这类书,或许别人觉得好,但是未必适合现在的你. 比如设计模式,许多Java源码当中都会涉及到.再比如阅读Spring源码的时候,势必要先对IOC,AOP,Java动态代理等知识点有所了解. 2.强烈的求知欲 强烈的求知欲