Union-Find (DSU)
Union-Find (Disjoint Set Union) Union-Find (DSU)
Union-Find هيكل بيانات يتتبّع مجموعات منفصلة لا تتقاطع، بعمليتين أساسيتين: دمج مجموعتين (union) وفحص هل عنصران بنفس المجموعة (find) — بزمن شبه ثابت مع تحسينين بسيطين.
كل عنصر يشير لأب، والجذر (العنصر الذي يشير لنفسه) هو ممثّل المجموعة. مع 'تسطيح المسار' (كل عنصر يُزار يشير مباشرة للجذر) و'الاتحاد بالرتبة' (إلحاق الشجرة الأقصر بالأطول)، يصبح تعقيد كل عملية O(α(n)) تقريبًا — α هي دالة أكرمان العكسية، تنمو ببطء شديد وتبقى عمليًا ≤ 4.
الصياغة
parent = list(range(n))
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) # تسطيح المسار
return parent[x]
def union(a, b):
ra, rb = find(a), find(b)
if ra != rb:
parent[rb] = ra📄 مثال
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, a, b):
ra, rb = self.find(a), self.find(b)
if ra == rb:
return False
if self.rank[ra] < self.rank[rb]:
ra, rb = rb, ra
self.parent[rb] = ra
if self.rank[ra] == self.rank[rb]:
self.rank[ra] += 1
return True
uf = UnionFind(5)
uf.union(0, 1)
uf.union(1, 2)
print(uf.find(0) == uf.find(2)) # True — بنفس المجموعة
print(uf.find(0) == uf.find(3)) # Falseأهم النقاط
| النقطة | الوظيفة |
|---|---|
| التعقيد الزمني | O(α(n)) تقريبًا لكل عملية (شبه ثابت) مع تسطيح المسار والاتحاد بالرتبة معًا |
| بلا أي تحسين | O(n) بأسوأ حالة (شجرة منحرفة تشبه قائمة مترابطة) |
| الدعم | دمج مجموعتين وفحص العضوية بسرعة — لا يدعم فصل عنصر عن مجموعته بكفاءة |
💡 نصائح عملية
- لا تنسَ تسطيح المسار — بدونه تفقد الخوارزمية أهم ميزة أدائها وتقترب من O(n) بأسوأ حالة
⚠️ أخطاء شائعة
- الظن أن Union-Find تخزّن تفاصيل العلاقات الفردية بين العناصر — هي تجيب فقط 'هل بنفس المجموعة؟'، لا 'كيف ترتبط بالتحديد؟'
خصائص ذات صلة
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار DSA الكامل بالعربي.