UNPKG

2.63 kBPlain TextView Raw
1import { NotFindInSetException } from "../exception/NotFindInSetException";
2import { DisjointSetItem } from "./DisjointSetItem";
3
4/**
5 * 并查集
6 */
7export class DisjointSet<T = string>{
8 private items: {[index: string]: DisjointSetItem<T>};
9 private rootItems: {[index: string]: DisjointSetItem<T>};
10
11 public get RootItems(){
12 return this.rootItems;
13 }
14
15 /**
16 * 并查集
17 * @param key 已指定键创建集合
18 */
19 constructor(private key?: keyof T){
20 this.items = {};
21 this.rootItems = {};
22 }
23
24 /**
25 * 创建集合
26 * @param value
27 */
28 public makeSet(value: T){
29 const disjointSetItem = new DisjointSetItem(value);
30 if (!this.items[disjointSetItem.getKey(this.key)]){
31 this.items[disjointSetItem.getKey(this.key)] = disjointSetItem;
32 this.rootItems[disjointSetItem.getKey(this.key)] = disjointSetItem;
33 }
34 return this;
35 }
36
37 /**
38 * 查找节点对应的集合
39 * @param value
40 */
41 public find(value: T): string{
42 const disjointSetItem = new DisjointSetItem(value);
43 const foundDisjointSetItem = this.items[disjointSetItem.getKey(this.key)];
44 if (!foundDisjointSetItem){
45 return null;
46 }
47 return foundDisjointSetItem.getRoot().getKey(this.key);
48 }
49
50 /**
51 * 合并集合
52 * 将两个集合合并到子集较多的集合中
53 * @param value1
54 * @param value2
55 */
56 public union(value1: T, value2: T){
57 const rootKeyA = this.find(value1);
58 const rootKeyB = this.find(value2);
59
60 if (rootKeyA === null || rootKeyB === null){
61 throw new NotFindInSetException();
62 }
63
64 if (rootKeyA === rootKeyB){
65 return this;
66 }
67
68 const rootA = this.items[rootKeyA];
69 const rootB = this.items[rootKeyB];
70
71 if (rootA.getRank() < rootB.getRank()){
72 rootB.addChild(rootA);
73 delete this.rootItems[rootKeyA];
74 return this;
75 }
76
77 rootA.addChild(rootB);
78 delete this.rootItems[rootKeyB];
79 return this;
80 }
81
82 /**
83 * 判断两个节点是否在同一集合中
84 * 未能查找到集合抛出NotFindInSetException异常
85 * @param value1
86 * @param value2
87 */
88 public inSameSet(value1: T, value2: T){
89 const rootKeyA = this.find(value1);
90 const rootKeyB = this.find(value2);
91 if (rootKeyA === null || rootKeyB === null){
92 throw new NotFindInSetException();
93 }
94
95 return rootKeyA === rootKeyB;
96 }
97}
98
99export default DisjointSet;