طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 101 · تركيب البيانات والخوارزميات
الدرس 14 · الوحدة 7: اختيار تركيب بيانات لحل مشكلة

المكدس والطابور

تركيبان بسيطان جدًّا، وفي كل نظام تقريبًا. ⏱ نحو 30 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تنفّذ المكدس بعملياته push و pop و peek.
  • تحل مسألة توازن الأقواس بالمكدس.
  • تنفّذ الطابور بـ deque وتعرف لماذا لا نستخدم pop(0).
  • تختار المكدس أو الطابور حسب طبيعة المسألة.

١المكدس Stack: آخر من يدخل أول من يخرج

المكدس تركيب بعمليتين أساسيتين: push يضع عنصرًا في القمة، و pop يأخذ العنصر من القمة. وبجانبهما peek لرؤية القمة دون أخذها. كلها O(1).

main.py
class Stack:    def __init__(self):        self.items = []    def push(self, x):        self.items.append(x)       # O(1)    def pop(self):        return self.items.pop()    # O(1)    def peek(self):        return self.items[-1]    def is_empty(self):        return len(self.items) == 0 s = Stack()for x in ["كتاب 1", "كتاب 2", "كتاب 3"]:    s.push(x)print("القمة:", s.peek())while not s.is_empty():    print("أخذنا:", s.pop())
Shell×
>>> %Run main.py
القمة: كتاب 3
أخذنا: كتاب 3
أخذنا: كتاب 2
أخذنا: كتاب 1
>>>

نضع القمة في آخر القائمة لا في أولها؛ لأن append و pop() في الآخر O(1)، أما في الأول فـ O(n).

٢تطبيق: هل الأقواس متوازنة؟

المترجم يتحقق أن كل قوس مفتوح له قوس يغلقه بالترتيب الصحيح. الحل بالمكدس: نضع كل قوس مفتوح في المكدس، وعند القوس المغلق نتأكد أن القمة هي القوس المقابل له:

🔎 تتبّع: هل "([)]" متوازنة؟
main.py
pairs = {")": "(", "]": "["}stack = []ok = Truefor ch in "([)]":    if ch in "([":        stack.append(ch)    elif not stack or stack.pop() != pairs[ch]:        ok = False        breakprint(ok and not stack)
Variables · المتغيّرات في الذاكرة
Shell×

٣الطابور Queue: أول من يدخل أول من يخرج

الطابور يضيف من الخلف enqueue ويُخرج من الأمام dequeue. لو استخدمنا list لكان الإخراج pop(0) بـ O(n). لذلك نستخدم collections.deque، وهو قائمة مترابطة مزدوجة من الداخل: الطرفان كلاهما O(1):

main.py
from collections import deque printer = deque()printer.append("تقرير.pdf")      # enqueueprinter.append("شهادة.docx")printer.append("جدول.xlsx") while printer:    doc = printer.popleft()       # dequeue    print("طباعة:", doc, "| الباقي:", len(printer))
Shell×
>>> %Run main.py
طباعة: تقرير.pdf | الباقي: 2
طباعة: شهادة.docx | الباقي: 1
طباعة: جدول.xlsx | الباقي: 0
>>>

٤محاكاة طابور: كم ينتظر العملاء؟

الطوابير تُستخدم لمحاكاة الأنظمة الحقيقية: عملاء يصلون إلى كاشير يخدم عميلًا كل 3 دقائق. كم ينتظر كل عميل؟

main.py
from collections import deque arrivals = [("أحمد", 0), ("سارة", 1), ("خالد", 2), ("منى", 8), ("فهد", 9)]SERVICE = 3                       # دقائق لكل عميل queue = deque(arrivals)clock = 0for _ in range(len(arrivals)):    name, arrived = queue.popleft()    start = max(clock, arrived)   # ينتظر حتى يفرغ الكاشير    print(f"{name}: وصل {arrived}، بدأ {start}، انتظر {start - arrived} د")    clock = start + SERVICE
Shell×
>>> %Run main.py
أحمد: وصل 0، بدأ 0، انتظر 0 د
سارة: وصل 1، بدأ 3، انتظر 2 د
خالد: وصل 2، بدأ 6، انتظر 4 د
منى: وصل 8، بدأ 9، انتظر 1 د
فهد: وصل 9، بدأ 12، انتظر 3 د
>>>

٥متى أستخدم أيهما؟

المكدس (LIFO)الطابور (FIFO)
التراجع Undo وزر الرجوعطابور الطباعة والطلبات
مكدس الاستدعاءات في العوديةالبحث بالعرض BFS (الدرس 19)
التحقق من الأقواس وتقييم العمليات الحسابيةمحاكاة الانتظار والجدولة
البحث بالعمق DFSتحميل الرسائل بترتيب وصولها

توقّع وتحقّق

زر التراجع Ctrl+Z:

آخر تعديل أولًا.

إخراج أول عنصر من deque:

O(1).

هل "(()" متوازنة؟

يبقى قوس في المكدس.

تعقيد push و pop في المكدس المبني على list:

في الآخر.

الخلاصة

تحدٍّ برمجي: فاحص الأقواس

متوسط

اكتب دالة balanced(text) تتحقق من توازن الأقواس الثلاثة () و [] و {} في النص، وتتجاهل أي حرف آخر.

المطلوب:
  • استخدم مكدسًا وقاموسًا للأزواج.
  • اطبع النتيجة لكل نص من النصوص الخمسة في سطر.

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
tests = ["(a + b) * [c]", "{[()]}", "([)]", "((", "print(x[0])"] def balanced(text):    pass
المطلوب×
(a + b) * [c] True
{[()]} True
([)] False
(( False
print(x[0]) True
💡 تلميح 1
الأحرف الأخرى: لا تفعل بها شيئًا.
💡 تلميح 2
في الآخر: return not stack (المكدس فارغ = متوازن).

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
tests = ["(a + b) * [c]", "{[()]}", "([)]", "((", "print(x[0])"] def balanced(text):    pairs = {")": "(", "]": "[", "}": "{"}    stack = []    for ch in text:        if ch in "([{":            stack.append(ch)        elif ch in ")]}":            if not stack or stack.pop() != pairs[ch]:                return False    return not stack for t in tests:    print(t, balanced(t))
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس