📊 فهم الـ Graphs في Python: عالم البيانات المرتبطة 🧩
مرحباً بك في عالم الـ Graphs أو الرسوم البيانية في البرمجة! 🎯 تخيل أنك تريد رسم خريطة تربط بين أصدقائك على مواقع التواصل، أو تخطط لمسار رحلة بين عدة مدن، أو حتى تحلل شبكة من الروابط بين صفحات الويب. في كل هذه الحالات، البيانات ليست مجرد قائمة منفصلة، بل هي مجموعة من العناصر المرتبطة ببعضها. هذا هو بالضبط ما يمثله الـ Graph – وهو أحد أهم هياكل البيانات لتمثيل هذه العلاقات المعقدة.
في هذا الدرس، سنتعلم معاً ماهية الـ Graph، ومصطلحاته الأساسية، وكيف نبنيه ببساطة في لغة Python باستخدام أدوات تعرفها بالفعل. هيا بنا! 🚀
🔍 ما هو الـ Graph (الرسم البياني)؟
ببساطة شديدة، الـ Graph هو مجموعة من النقاط المتصلة ببعضها بواسطة خطوط.
- العقدة (Node أو Vertex): تمثل كل نقطة في الرسم البياني. يمكن أن تكون مدينة، شخصاً، صفحة ويب، أو أي كيان تريد تمثيله. نرمز لها عادة بحرف مثل
A,B,C. - الحافة (Edge): هي الخط الذي يربط بين عقدتين. تمثل العلاقة أو الاتصال بينهما، مثل طريق بين مدينتين، أو صداقة بين شخصين.
مثال من الحياة الواقعية: شبكة مترو الأنفاق! 🚇 كل محطة هي عقدة (Node)، والخط الحديدي الذي يصل بين محطتين هو حافة (Edge).
📝 مصطلحات أساسية في الـ Graphs
قبل أن نبدأ في البرمجة، دعنا نتعرف على بعض المصطلحات المهمة:
- مُوجَّه (Directed) vs غير موجه (Undirected):
- في الـ Graph غير الموجه، الحافة لا تملك اتجاه. إذا كان هناك طريق بين المدينة A والمدينة B، يمكنك السفر في كلا الاتجاهين. العلاقة متبادلة. ↔️
- في الـ Graph الموجه، الحافة لها اتجاه، مثل سهم. قد يعني وجود طريق من A إلى B، ولكن ليس بالضرورة العكس. ➡️
- مرجح (Weighted) vs غير مرجح (Unweighted):
- في الـ Graph غير المرجح، كل الحواف متساوية. العلاقة موجودة أو غير موجودة.
- في الـ Graph المرجح، لكل حافة قيمة أو "وزن" مرتبط بها، مثل مسافة الطريق بين مدينتين، أو تكلفة الرحلة. ⚖️
- قائمة الجوار (Adjacency List): طريقة شائعة لتمثيل الـ Graph في الذاكرة، حيث نحتفظ لكل عقدة بقائمة بالعقد المجاورة لها مباشرة (المتصلة بها بحافة).
💻 كيف ننشئ Graph في Python؟
أسهل طريقة لبناء Graph بسيط في بايثون هي استخدام القاموس (Dictionary)! سنمثل قائمة الجوار (Adjacency List).
الفكرة: المفتاح في القاموس سيكون اسم العقدة، والقيمة ستكون قائمة (List) تحتوي على أسماء جميع العقد المتصلة بها مباشرة.
مثال 1: بناء Graph غير موجه
لنبني رسمًا بيانيًا بسيطًا يمثل شبكة صغيرة من الأصدقاء، حيث العلاقة صداقة متبادلة (غير موجهة).
# إنشاء Graph غير موجه باستخدام قاموس
# المفتاح: اسم الشخص (العقدة)
# القيمة: قائمة بأسماء أصدقائه (العقد المتصلة)
friends_graph = {
"أحمد": ["سارة", "خالد"], # أحمد صديق لسارة وخالد
"سارة": ["أحمد", "خالد"], # سارة صديقة لأحمد وخالد
"خالد": ["أحمد", "سارة", "ليلى"],
"ليلى": ["خالد"]
}
# طباعة Graph الأصدقاء
print("شبكة الأصدقاء:")
for person, friends_list in friends_graph.items():
print(f"{person} -> {friends_list}")
# للوصول إلى أصدقاء شخص معين
print("\nأصدقاء خالد هم:", friends_graph["خالد"])
شرح الكود:
- قمنا بإنشاء قاموس
friends_graph. - العقد هي أسماء الأشخاص:
"أحمد","سارة","خالد","ليلى". - الحواف ممثلة بالقوائم داخل القاموس. وجود
"سارة"في قائمة"أحمد"والعكس يعني أن هناك حافة غير موجهة بينهما (صداقة متبادلة).
مثال 2: بناء Graph موجه
لنفترض أننا نريد تمثيل مسار أحادي الاتجاه، مثل متابعة حساب على تويتر (أنا أتابعك، ولكنك قد لا تتابعني).
# إنشاء Graph موجه لعلاقات المتابعة
follow_graph = {
"أحمد": ["سارة"], # أحمد يتابع سارة
"سارة": ["خالد"], # سارة تتابع خالد
"خالد": ["أحمد", "سارة"], # خالد يتابع أحمد وسارة
"ليلى": [] # ليلى لا تتابع أحدًا (حساب جديد)
}
print("\nشبكة المتابعة:")
for follower, following_list in follow_graph.items():
if following_list: # إذا كانت القائمة غير فارغة
print(f"{follower} يتابع -> {following_list}")
else:
print(f"{follower} لا يتابع أحداً")
🧩 طريقة أخرى: مصفوفة الجوار (Adjacency Matrix)
هناك طريقة أخرى لتمثيل الـ Graph وهي باستخدام مصفوفة ثنائية الأبعاد (قائمة داخل قائمة).
- الصفوف والأعمدة تمثل العقد.
- إذا كانت الخلية
[i][j]تحتوي على1، فهذا يعني وجود حافة من العقدةiإلى العقدةj. إذا كانت0، فلا يوجد اتصال.
# تمثيل Graph بسيط (العقد: A, B, C) بمصفوفة جوار
# الفهرس 0 -> A, الفهرس 1 -> B, الفهرس 2 -> C
adjacency_matrix = [
[0, 1, 1], # A متصل بـ B و C
[1, 0, 0], # B متصل بـ A فقط
[1, 0, 0] # C متصل بـ A فقط
]
# تفسير: هذا Graph غير موجه لأن المصفوفة متناظرة
print("\nمصفوفة الجوار:")
for row in adjacency_matrix:
print(row)
ملاحظة: طريقة القاموس (قائمة الجوار) غالباً ما تكون أكثر كفاءة في الذاكرة عندما يكون الـ Graph "متناثراً" (ليس كل العقد متصلة ببعضها).
🎯 خلاصة الدرس
تعلمنا اليوم الأساسيات القوية للـ Graphs في Python:
- الـ Graph هو هيكل بيانات يمثل عقداً (Nodes) متصلة بواسطة حواف (Edges).
- يمكن أن يكون موجهاً أو غير موجه، مرجحاً أو غير مرجح.
- أسهل طريقة لبنائه في بايثون هي استخدام قاموس تكون قيمه قوائم، وهذا ما يسمى تمثيل قائمة الجوار (Adjacency List).
- تعرفنا أيضاً على فكرة مصفوفة الجوار (Adjacency Matrix) كتمثيل بديل.
الـ Graph هو البوابة لفهم خوارزميات رائعة مثل إيجاد أقصر مسار، أو تحليل الشبكات الاجتماعية! 💡
🎓 اختبر نفسك
التعليقات
شاركنا رأيك أو أسئلتك حول هذا المقال