-
Notifications
You must be signed in to change notification settings - Fork 296
Expand file tree
/
Copy pathDisJointSet.cs
More file actions
140 lines (118 loc) · 3.63 KB
/
DisJointSet.cs
File metadata and controls
140 lines (118 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Advanced.Algorithms.DataStructures
{
/// <summary>
/// A disjoint set implementation.
/// </summary>
public class DisJointSet<T> : IEnumerable<T>
{
/// <summary>
/// A Map for faster access for members.
/// </summary>
private Dictionary<T, DisJointSetNode<T>> set
= new Dictionary<T, DisJointSetNode<T>>();
public int Count { get; private set; }
/// <summary>
/// Creates a new set with given member.
/// Time complexity: log(n).
/// </summary>
public void MakeSet(T member)
{
if (set.ContainsKey(member))
{
throw new Exception("A set with given member already exists.");
}
var newSet = new DisJointSetNode<T>()
{
Data = member,
Rank = 0
};
//Root's Parent is Root itself
newSet.Parent = newSet;
set.Add(member, newSet);
Count++;
}
/// <summary>
/// Returns the reference member of the set where this member is part of.
/// Time complexity: log(n).
/// </summary>
public T FindSet(T member)
{
if(!set.ContainsKey(member))
{
throw new Exception("No such set with given member.");
}
return findSet(set[member]).Data;
}
/// <summary>
/// Recursively move up in the set tree till root
/// and return the Root.
/// Does path Compression on all visited members on way to root
/// by pointing their parent to Root.
/// </summary>
private DisJointSetNode<T> findSet(DisJointSetNode<T> node)
{
var parent = node.Parent;
if(node !=parent)
{
//compress path by setting parent to Root
node.Parent = findSet(node.Parent);
return node.Parent;
}
//reached root so return the Root (reference Member)
return parent;
}
/// <summary>
/// Union's given member's sets if given members are in differant sets.
/// Otherwise does nothing.
/// Time complexity: log(n).
/// </summary>
public void Union(T memberA, T memberB)
{
var rootA = FindSet(memberA);
var rootB = FindSet(memberB);
if(rootA.Equals(rootB))
{
return;
}
var nodeA = set[rootA];
var nodeB = set[rootB];
//equal rank so just pick any of two as Root
//and increment rank
if(nodeA.Rank == nodeB.Rank)
{
nodeB.Parent = nodeA;
nodeA.Rank++;
}
else
{
//pick max Rank node as root
if(nodeA.Rank < nodeB.Rank)
{
nodeA.Parent = nodeB;
}
else
{
nodeB.Parent = nodeA;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return set.Values.Select(x => x.Data).GetEnumerator();
}
}
internal class DisJointSetNode<T>
{
internal T Data { get; set; }
internal int Rank { get; set; }
internal DisJointSetNode<T> Parent { get; set; }
}
}