1 | import { NotFindInSetException } from "../exception/NotFindInSetException";
|
2 | import { DisjointSetItem } from "./DisjointSetItem";
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | export 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 |
|
18 |
|
19 | constructor(private key?: keyof T){
|
20 | this.items = {};
|
21 | this.rootItems = {};
|
22 | }
|
23 |
|
24 | |
25 |
|
26 |
|
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 |
|
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 |
|
54 |
|
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 |
|
85 |
|
86 |
|
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 |
|
99 | export default DisjointSet;
|