我正在学习数据结构和算法,并试图在Java中实现不相交的数据结构。这是我的代码 -
import java.util.*;
public class DisjointSet<T> {
Set<LinkedHashSet<T>> allSets;
DisjointSet() {
allSets = new HashSet<LinkedHashSet<T>>();
}
public void makeSet(T t) {
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
LinkedHashSet set = (LinkedHashSet) itr.next();
if (set.contains(t)) {
return;
}
}
LinkedHashSet<T> set = new LinkedHashSet<T>();
set.add(t);
allSets.add(set);
}
public T findSet(T t) {
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
LinkedHashSet set = (LinkedHashSet) itr.next();
if (set.contains(t)) {
Iterator itr1 = set.iterator();
T t1 = (T) itr1.next();
return t1;
}
}
return null;
}
public void union(T t1, T t2) {
LinkedHashSet<T> set1 = null, set2 = null;
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
LinkedHashSet set = (LinkedHashSet) itr.next();
if (set.contains(t1)) {
set1 = (LinkedHashSet<T>) set;
System.out.println("Got set1:: " + set1);
} else if (set.contains(t2)) {
set2 = (LinkedHashSet<T>) set;
System.out.println("Got set2:: " + set2);
}
}
if (null != set1) {
System.out.println("Adding set2 to set1");
set1.addAll(set2);
if (null != set2) {
System.out.println("Removing set2");
System.out.println(allSets.remove(set2));
}
}
}
public void viewAllSets() {
System.out.println(this.allSets);
}
}
这是我正在运行的代码来测试我的实现 -
public class DisjointTest {
public static void main(String [] args) {
DisjointSet<Integer> dsets = new DisjointSet<Integer>();
dsets.makeSet(30);
dsets.makeSet(600);
dsets.makeSet(20);
dsets.makeSet(25);
dsets.makeSet(90);
dsets.makeSet(100);
dsets.makeSet(1);
dsets.viewAllSets();
System.out.println();
System.out.println(dsets.findSet(25));
dsets.union(20, 25);
dsets.viewAllSets();
System.out.println();
System.out.println(dsets.findSet(25));
dsets.union(1, 100);
dsets.viewAllSets();
System.out.println();
dsets.union(20, 100);
dsets.viewAllSets();
System.out.println(dsets.findSet(100));
System.out.println();
dsets.union(30, 90);
dsets.viewAllSets();
System.out.println();
dsets.union(1, 90);
dsets.viewAllSets();
}
}
当我尝试将一个集合与另一个集合合并,比如说set2,它有2个或更多元素时,集合会正确合并,但即使在调用allsets.remove(set2)
之后,set2也不会从集合集合中删除
但是,如果要合并的集合,即; set2只有1个元素,allSets.remove(set2)
成功地从集合集合中删除了set2。
以下是我的代码的输出,它确认了我的问题 -
[[1], [100], [20], [25], [600], [90], [30]]
25
Got set1:: [20]
Got set2:: [25]
Adding set2 to set1
Removing set2
true
[[1], [100], [20, 25], [600], [90], [30]]
20
Got set1:: [1]
Got set2:: [100]
Adding set2 to set1
Removing set2
true
[[1, 100], [20, 25], [600], [90], [30]]
Got set2:: [1, 100]
Got set1:: [20, 25]
Adding set2 to set1
Removing set2
false
[[1, 100], [20, 25, 1, 100], [600], [90], [30]]
1
Got set1:: [20, 25, 1, 100]
Got set2:: [90]
Adding set2 to set1
Removing set2
true
[[1, 100], [20, 25, 1, 100, 90], [600], [30]]
我无法理解为什么HashSet.remove(LinkedHashSet)
无法删除包含多个元素的LinkedHashSet
,但成功删除了包含1个元素的LinkedHashSet
。
任何帮助都将受到高度赞赏。 非常感谢你。
答案 0 :(得分:4)
您错过了使用集合的关键点:您不能修改存储在集合中的值(至少不能改变其相等性)。
如果修改已存储在HashSet中的值,并且该修改更改了值的hashCode,则无法再在该集合中找到该值,因为它不再位于与其hashCode对应的存储桶中。
将一个集合与另一个集合时,您更改其hashCode,从而完全破坏整个数据结构的正确性。
示例:
请注意,TreeSet也是如此。 TreeSet通过构造值树来工作:如果A小于root,则它转到左分支。如果修改A并且它变得比root大,TreeSet将尝试在树的错误分支中找到它。
答案 1 :(得分:0)
至于其他人的理论基础已经回答。
就解决方案使用好的ol矢量并避免花哨的smanchy hashsets而言 - 如果你去了hashsets,你在数学上理解它的集合的想法会被破坏
import java.util.*;
public class DisjointSet<T> {
Vector allSets;
DisjointSet() {
allSets = new Vector();
}
public void makeSet(T t) {
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
Vector set = (Vector) itr.next();
if (set.contains(t)) {
return;
}
}
Vector set = new Vector();
set.add(t);
allSets.add(set);
}
public T findSet(T t) {
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
Vector set = (Vector) itr.next();
if (set.contains(t)) {
Iterator itr1 = set.iterator();
T t1 = (T) itr1.next();
return t1;
}
}
return null;
}
public void union(T t1, T t2) {
Vector set1 = null, set2 = null;
Iterator itr = allSets.iterator();
while (itr.hasNext()) {
try {
Vector set = (Vector) itr.next();
if (set.contains(t1)) {
set1 = (Vector) set;
System.out.println("Got set1:: " + set1);
} else if (set.contains(t2)) {
set2 = (Vector) set;
System.out.println("Got set2:: " + set2);
}
}
catch(Exception e) { e.printStackTrace(); }
}
if (null != set1) {
System.out.println("Adding set2 to set1");
set1.addAll(set2);
if (null != set2) {
System.out.println("Removing set2");
viewAllSets();
System.out.println(allSets.contains(set2)+" "+allSets.remove(set2));
}
}
}
public void viewAllSets() {
System.out.println(this.allSets);
}
public static void main(String [] args) {
DisjointSet<Integer> dsets = new DisjointSet<Integer>();
dsets.makeSet(30);
dsets.makeSet(600);
dsets.makeSet(20);
dsets.makeSet(25);
dsets.makeSet(90);
dsets.makeSet(100);
dsets.makeSet(1);
dsets.viewAllSets();
System.out.println();
System.out.println(dsets.findSet(25));
dsets.union(20, 25);
dsets.viewAllSets();
System.out.println();
System.out.println(dsets.findSet(25));
dsets.union(1, 100);
dsets.viewAllSets();
System.out.println();
dsets.union(20, 100);
dsets.viewAllSets();
System.out.println(dsets.findSet(100));
System.out.println();
}
}