Skip to content

Commit a25c6c8

Browse files
committed
update union find python version
1 parent 29657e4 commit a25c6c8

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : 3zz
3+
# @Time : 2019-09-02 17:23
4+
# @File : __init__.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : 3zz
3+
# @Time : 2019-09-02 17:23
4+
# @File : union_find.py
5+
6+
7+
class UnionFind:
8+
"""
9+
普通并查集 时间复杂度O(n)
10+
"""
11+
12+
def __init__(self, n):
13+
self._count = n
14+
self._id = [i for i in range(n)]
15+
16+
def _find(self, p):
17+
assert 0 <= p <= self._count
18+
return self._id[p]
19+
20+
def is_connected(self, p, q):
21+
return self._find(p) == self._find(q)
22+
23+
def union(self, p, q):
24+
assert 0 <= p < self._count and 0 <= q < self._count
25+
p_id = self._find(p)
26+
q_id = self._find(q)
27+
if p_id == q_id:
28+
return
29+
for i in range(self._count):
30+
if self._id[i] == q_id:
31+
self._id[i] = p_id
32+
33+
34+
class UnionFind2:
35+
"""
36+
利用parent数组存储结果
37+
"""
38+
39+
def __init__(self, n):
40+
self._count = n
41+
self._parent = [i for i in range(n)]
42+
43+
def _find(self, p):
44+
assert 0 <= p < self._count
45+
while p != self._parent[p]:
46+
p = self._parent[p]
47+
return p
48+
49+
def is_connected(self, p, q):
50+
return self._find(p) == self._find(q)
51+
52+
def union(self, q, p):
53+
assert 0 <= q < self._count and 0 <= p < self._count
54+
q_root = self._find(q)
55+
p_root = self._find(p)
56+
if p_root == q_root:
57+
return
58+
self._parent[p_root] = q_root
59+
60+
61+
class UnionFind3:
62+
"""
63+
新加一个size数组用来存储以i为根的集合中的元素个数
64+
"""
65+
66+
def __init__(self, n):
67+
self._count = n
68+
self._sz = [1] * n
69+
self._parent = [i for i in range(n)]
70+
71+
def _find(self, p):
72+
assert 0 <= p < self._count
73+
while p != self._parent[p]:
74+
p = self._parent[p]
75+
return p
76+
77+
def is_connected(self, q, p):
78+
return self._find(q) == self._find(p)
79+
80+
def union(self, q, p):
81+
p_root = self._find(p)
82+
q_root = self._find(q)
83+
if q_root == p_root:
84+
return
85+
if self._sz[q_root] < self._sz[p_root]:
86+
self._parent[q_root] = p_root
87+
self._sz[p_root] += self._sz[q_root]
88+
else:
89+
self._parent[p_root] = q_root
90+
self._sz[q_root] += self._sz[p_root]
91+
92+
93+
class UnionFind4:
94+
"""
95+
利用rank数组用来存储以i为根的集合所表示的层数
96+
利用层数可以用来加速集合间的合并 从而不要让并查集长度过长
97+
"""
98+
99+
def __index__(self, n):
100+
self._count = n
101+
self._rank = [i for i in range(n)]
102+
self._parent = [i for i in range(n)]
103+
104+
def find(self, q):
105+
assert 0 <= q < self._count
106+
while q != self._parent[q]:
107+
q = self._parent[q]
108+
return q
109+
110+
def is_connected(self, p, q):
111+
return self.find(q) == self.find(p)
112+
113+
def union(self, p, q):
114+
p_root = self.find(p)
115+
q_root = self.find(q)
116+
if p_root == q_root:
117+
return
118+
if self._rank[p_root] < self._rank[q_root]:
119+
self._parent[p_root] = q_root
120+
elif self._rank[p_root] > self._rank[q_root]:
121+
self._parent[q_root] = p_root
122+
else:
123+
# rank[p_root] = rank[q_root]
124+
self._parent[q_root] = p_root
125+
self._rank[q_root] += 1
126+
127+
128+
class UnionFind5:
129+
"""
130+
使用压缩路径能够更进一步加快union操作
131+
"""
132+
133+
def __init__(self, n):
134+
self._count = n
135+
self._rank = [1] * n
136+
self._parent = [i for i in range(n)]
137+
138+
def find(self, p):
139+
"""
140+
在这里 使用递归的方式进行路径压缩
141+
"""
142+
assert 0 <= p < self._count
143+
if p != self._parent[p]:
144+
self._parent[p] = self.find(self._parent[p])
145+
return self._parent[p]
146+
147+
def find2(self, p):
148+
"""
149+
递归有可能导致栈溢出 所以find2使用非递归方式进行路径压缩
150+
"""
151+
assert 0 <= p < self._count
152+
r = p
153+
while r != self._parent[r]:
154+
r = self._parent[r]
155+
k = p
156+
while k != r:
157+
j = self._parent[k]
158+
self._parent[k] = r
159+
k = j
160+
return r
161+
162+
def is_connect(self, q, p):
163+
return self.find(q) == self.find(p)
164+
165+
def union(self, p, q):
166+
assert 0 <= q < self._count and 0 <= p < self._count
167+
q_root = self.find(q)
168+
p_root = self.find(p)
169+
if p_root == q_root:
170+
return
171+
if self._rank[p_root] < self._rank[q_root]:
172+
self._parent[p_root] = q_root

0 commit comments

Comments
 (0)