Java算法-1.连通性问题

来源:互联网 发布:中文安卓编程王者荣耀 编辑:程序博客网 时间:2024/06/06 07:12
/**
 * 问题描述:
 * 假设现在有一个整数对序列,每个整数代表某种类型的对象,我们用p-q对表示"p连接到q",并且这种连接具有传递性:
 * 即如果p连接到q,而q又连接到r则p连接到r。我们的目标是写一个程序,把多余的对从集合中过滤掉:
 * 当程序输入p-q对时,程序判断以前的数对是否包含了p-q连接,如果没有则添加否则忽略。
 * 
 * 
 *分析:
 * 我们的问题是设计一个可以记住曾处理过的所有对的足够信息的程序,以能够判断新输入的对象是否已经连接。我们把设计这种方法的任务称为"连通性问题"。
 * 例1:整数可能代表大型网络中的计算机,数对表示网络中计算机之间的连接。这时就可以用我们的程序来决定是否要在p-q之间建立一个新的连接,或使用已有的连接来建立通信路径。
 * 例2:整数可以代表电路中的接触点,数对表示连接两点的导线。那么我们可以用程序找到连接所有点的方法,条件是没有多余的连接。
 * 例3:在某些编程环境下,声明的两个变量可能是等价的,问题就是:在声明一系列的变量之后,如何判断两个给定的变量名是否等价。
 * 连通性问题的说明只要求我们的程序能判断出所给的任意p-q对是否是连接的,并不要求程序显示连接p-q对的任何或所有方法。
 * 这里其实我们可以换一个问法:M条连接足以把所有的N个对象连接起来吗?对于这个问题图论中的一个基本理论说明:所有N对象是连接的,当且仅当连通性算法输出的数对数目是N-1.
 * 也就是说连通性算法的输出对数目绝不会超过N-1,一旦超过了N-1,则以后所遇到的任何对都是已连接的。所以可以对一个计数器增1,如果计数器累加到N-1时就回答"是"否则就"否"。
 * 输入的对集合称为图,输出的对集合称为该图的生成树。生成树连接了图的所有对象,而且分量中的任意两个对象都是连接的。。明确的说,(1)每次得到一个新对时,它必须判断是否代表着新连接,(2)然后把此信息与以前的连接信息融合在一起
 * 作为它对对象连通性的理解。把这两个任务封装在一起作为抽象操作,用输入的整数值代表抽象集合中的元素,然后设计算法和数据结构,他们能够:
 * 1)找到包含给定项的集合--查找 2)把包含两个给定项的集合用这些集合的并来代替--合并
 * 用查找和合并很容易解决连通性问题,我们的重点是找到一种数据结构,它能有效的支持合并和查找两种操作。
 *
 */
public class ConnectionDemo {
/*快速查找算法原理说明:
* 这个算法是解决连通性问题的快速查找算法。算法的基础是一个整数数组,数组具有的特性是p与q是连接的当且仅当第p个元素与第q个元素时相等的。
* 数组的索引值代表了需要连接的对象,而它们的值代表了它们的连通性,如果相等则表示连通。初始化时第i个数组元素初始化为i。要完成p,q的合并操作,
* 需要遍历整个数组,把所有与第p个数组元素相等的元素改为第q个元素的值。要完成查找工作我们只需要判断第q个元素的值是否与第p个元素的值相等就行。
* 算法性质:
* 1)快速查找算法要解决N个对象的连通性问题,需要进行M次合并,至少要执行M*N条指令。
* 解释:每执行一次合并操作,就必须重复执行N次for循环。

*/
public static void quickSearch(int N){
int[] id = new int[N];
for(int i = 0;i<id.length;i++){
id[i] = i;
}
Scanner sc = new Scanner(System.in);
String in = null;
while(sc.hasNext()){
in = sc.next();
String[]input = in.split(",");
int p = Integer.parseInt(input[0]);
int q = Integer.parseInt(input[1]);
int t = id[p];
if(t == id[q]){//如果输入的"对象"所对应的值相等,说明已经添加了
System.out.println(p+","+q+"已经连接上了,序列如下:");
for(int i = 0;i<id.length;i++){
if(id[i] == t)//查找已经连接的路径
System.out.print(i+"->");
}
continue;
}
//合并两个集合
for(int i =0;i<id.length;i++){
if(id[i] == t){
id[i] = id[q];
}
}
System.out.println("向集合中添加分量:"+p+"-->"+q);
}
}
/*快速合并算法原理说明:
* 这个算法是解决连通性问题的快速合并算法。算法的特点:
* 1)利用图的连通性来解决p,q对象的连通性,如果p,q在一个图的生成树中,那么p,q就是连接的。
* 2)将数组的索引看作是对象,而索引值是此对象所在生成树的根,只有根节点才有到自身的连接,所以刚开始时假设对象都是单个的根
* 算法性质:
* 1)快速合并算法要执行M*N/2条以上的指令来解决有N个对象和M个输入对的连通性问题(M>N)。
* 解释:每执行一次合并操作,就必须重复执行N次for循环。

*/
public static void quickMerge(int N){
int[] id = new int[N];
for(int i = 0;i<id.length;i++){
id[i] = i;
}
Scanner sc = new Scanner(System.in);
String in = null;
while(sc.hasNext()){
in = sc.next();
String[]input = in.split(",");
int p = Integer.parseInt(input[0]);
int q = Integer.parseInt(input[1]);
int i,j;
for(i = p;i != id[i];i = id[i]);//找p对象的根
for(j = q;j != id[j];j = id[j]);//找q对象的根
if(i == j){//两对象有相同的根则表示已经连接
System.out.println(p+","+q+"已经连接上了,序列如下:");
continue;
}
//将第p个对象的根连接至第q个对象的根
id[i] = j;
System.out.println("向集合中添加分量:"+p+"-->"+q);
}
}
public static void main(String[] args) {

//ConnectionDemo.quickSearch(10);
ConnectionDemo.quickMerge(10);
}
}
0 0
原创粉丝点击