Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

القائمة المترابطة

آخر تحديث

تخزّن القائمة المترابطة تسلسلاً على شكل سلسلة من العقد، حيث تحمل كل عقدة قيمةً ومؤشراً إلى العقدة التالية. على عكس المصفوفة، العقد ليست متجاورة في الذاكرة - فتتّبع مؤشرات next للتنقل عبر القائمة. اضغط تشغيل في الأعلى لمشاهدة العقد وهي تُربط في البداية والنهاية، وقيمة يجري البحث عنها بالتنقل عبر السلسلة، وعقدة تُزال بإعادة توصيل مؤشر.

الإدراج أو الحذف في البداية هو O(1) لأنك تعيد توجيه الرأس فقط. الوصول إلى موضع في المنتصف أو إلى النهاية هو O(n) لأنه يجب عليك المشي إلى هناك أولاً. هذه المقايضة -أطراف رخيصة، لا وصول عشوائي- هي ما يميّز القائمة المترابطة عن المصفوفة.

التعقيد الزمني

العمليةالتعقيدملاحظات
الإدراج في البدايةO(1)إعادة توجيه الرأس
الإدراج في النهايةO(n)المشي إلى النهاية أولاً (O(1) مع مؤشر ذيل)
البحثO(n)اتّباع مؤشرات next
حذف الرأسO(1)إعادة توجيه الرأس إلى ما بعدها
الوصول بالفهرسO(n)لا وصول عشوائي

القائمة المترابطة مقابل المصفوفة

الجانبالقائمة المترابطةالمصفوفة
الذاكرةعقد متناثرة + مؤشراتكتلة متجاورة
الوصول العشوائيO(n)O(1)
الإدراج/الحذف في المقدمةO(1)O(n) (إزاحة)
ملاءمة الذاكرة المؤقتةضعيفةجيدة

مثال محلول

بناء القائمة [10, 20]، ثم إضافة 5 في المقدمة، ثم حذف 20:

الخطوةالبنيةالإجراء
البدايةhead -> nullقائمة فارغة
إدراج 10 في البدايةhead -> 10 -> nullإعادة توجيه الرأس إلى عقدة جديدة يكون next الخاص بها هو الرأس القديم (null)
إدراج 20 في النهايةhead -> 10 -> 20 -> nullالمشي إلى العقدة 10 وضبط next الخاص بها على عقدة جديدة 20
إدراج 5 في البدايةhead -> 5 -> 10 -> 20 -> nullالعقدة الجديدة 5 تشير إلى الرأس القديم 10؛ والرأس يشير الآن إلى 5
حذف 20head -> 5 -> 10 -> nullالمشي إلى 10 وضبط next الخاص بها من 20 إلى null؛ العقدة 20 تُفصل

متى تستخدم القائمة المترابطة

استخدمها عندماتجنّبها عندما
تُدرج أو تحذف عند الأطراف (أو عند عقدة تحتفظ بها) أكثر بكثير مما تفهرستحتاج إلى وصول عشوائي سريع حسب الموضع (فهرسة O(1))
يتغيّر الحجم كثيراً ولا تريد تكلفة إعادة التحجيم/النسختمرّ بحلقات محكمة حيث تهيمن محلية الذاكرة المؤقتة على الأداء
تبني طابوراً أو مكدساً أو قائمة تجاورالذاكرة محدودة - فكل عقدة تدفع مؤشراً إضافياً لكل عنصر
تحتاج إلى مراجع مستقرة إلى عقد تبقى بعد عمليات إدراج في أماكن أخرىتقرأ في الغالب ونادراً ما تعدّل، فالمصفوفة أبسط وأسرع

كود Linked List

تنفيذ نظيف وقابل للتشغيل لخوارزمية Linked List بلغات Python, JavaScript, Java, C++, C. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.

كود Linked List بلغة Python

Python
1class Node:2    def __init__(self, value):3        self.value = value4        self.next = None5
6
7class LinkedList:8    def __init__(self):9        self.head = None10
11    def append(self, value):12        node = Node(value)13        if self.head is None:14            self.head = node15            return16        current = self.head17        while current.next:18            current = current.next19        current.next = node20
21    def find(self, value):22        current = self.head23        while current:24            if current.value == value:25                return True26            current = current.next27        return False28
29    def delete(self, value):30        # Re-link the previous node around the match31        current, prev = self.head, None32        while current:33            if current.value == value:34                if prev is None:35                    self.head = current.next36                else:37                    prev.next = current.next38                return True39            prev, current = current, current.next40        return False41
42    def __str__(self):43        values, current = [], self.head44        while current:45            values.append(str(current.value))46            current = current.next47        return " -> ".join(values) + " -> None"48
49
50lst = LinkedList()51for value in [3, 7, 1, 9]:52    lst.append(value)53
54print("List:    ", lst)55print("find(7): ", lst.find(7))56lst.delete(1)57print("After delete(1):", lst)
شغّل هذا الكود في ساحة تجربة Python

الأسئلة الشائعة حول القوائم المترابطة

ما الفرق بين القائمة المترابطة والمصفوفة؟
تخزّن المصفوفة العناصر في كتلة متجاورة واحدة، مما يمنح وصولاً عشوائياً بـ O(1) لكن عمليات إدراج/حذف بـ O(n) تزيح العناصر. أما القائمة المترابطة فتخزّن العقد في أي مكان في الذاكرة موصولةً بمؤشرات، مما يمنح عمليات إدراج/حذف بـ O(1) عند موضع معروف لكن وصولاً بـ O(n) لأنه يجب عليك التنقل عبر السلسلة.
متى يجب أن أستخدم القائمة المترابطة؟
تتألق القوائم المترابطة عندما تُدرج أو تُزيل بشكل متكرر عند الأطراف (أو عند عقدة تحتفظ بمرجع لها بالفعل) ونادراً ما تحتاج إلى وصول عشوائي - مثل الطوابير والمكدسات وقوائم التجاور وذاكرات التخزين المؤقت من نوع LRU. إذا كنت تحتاج إلى وصول مفهرس سريع، فالمصفوفة أو المصفوفة الديناميكية عادةً أفضل.
ما هو التعقيد الزمني للقائمة المترابطة؟
الإدراج أو الحذف عند الرأس هو O(1). البحث، أو الوصول إلى النهاية دون مؤشر ذيل، هو O(n) لأنك تتّبع مؤشرات next واحداً تلو الآخر. لا يوجد وصول عشوائي بـ O(1) - فالفهرسة داخل القائمة المترابطة هي O(n).
ما الفرق بين القائمة المترابطة الأحادية والمزدوجة؟
تخزّن القائمة المترابطة الأحادية مؤشر next فقط لكل عقدة، لذا يمكنك التنقل في اتجاه واحد ويتطلب حذف عقدة مرجعاً إلى سابقتها. أما القائمة المترابطة المزدوجة فتضيف مؤشر prev، مما يتيح التنقل للخلف والحذف بـ O(1) لعقدة محتفظ بها، مقابل مؤشر إضافي لكل عقدة والمزيد من التدبير عند كل إدراج وحذف.
لماذا يكون الإدراج في النهاية O(n) إذا كان الإدراج في البداية O(1)؟
الإدراج في البداية يعيد توصيل مؤشر head فقط، وهو عمل ثابت. أما الوصول إلى النهاية فيعني اتّباع مؤشرات next من الرأس حتى النهاية، وهو O(n). الاحتفاظ بمؤشر tail منفصل يجعل الإدراج في النهاية O(1) أيضاً، ولهذا كثيراً ما تتتبّع القوائم الواقعية كلا الطرفين.
هل تتمتع القوائم المترابطة بإدراج O(1) في كل مكان؟
لا - هذا مفهوم خاطئ شائع. الإدراج نفسه يكون O(1) فقط بمجرد أن تحتفظ بمؤشر إلى العقدة التي تُدرج بعدها. أما العثور على ذلك الموضع بالقيمة أو بالفهرس فما زال يكلّف O(n) لأنه يجب عليك التنقل عبر السلسلة للوصول إلى هناك.
Coddy programming languages illustration

أتقن الخوارزميات مع Coddy

ابدأ الآن