ما معنى First-In, First-Out (FIFO) في الخوارزميات وهياكل البيانات؟
First-In, First-Out — واختصارها FIFO — تعني ببساطة: أول عنصر يدخل هو أول عنصر يخرج. تخيّل طابور الخبز أو صندوق المحاسبة في السوبرماركت؛ من وقف أولاً يُخدَم أولاً، ولا أحد يتجاوز الدور. هذا هو جوهر المبدأ في علوم الحاسوب، ويُطبَّق عبر هيكل بيانات اسمه الطابور (Queue). إذا كنت تتعلّم الخوارزميات أو تستعد لمقابلة عمل، فهم FIFO في دقائق قليلة ممكن تماماً، وهذا ما سنفعله هنا بأمثلة عملية بدل التعريفات الجافة.
كيف يعمل الطابور (Queue) عملياً؟
الطابور هو التطبيق المباشر لمبدأ FIFO، وله طرفان محدّدان لا يختلطان:
- الخلف (Rear/Back): من هنا فقط نُضيف عنصراً جديداً، والعملية تُسمى Enqueue (إدخال).
- الأمام (Front): من هنا فقط نُخرج العنصر، والعملية تُسمى Dequeue (إخراج).
ولأن الإدخال من جهة والإخراج من جهة أخرى، يستحيل أن يتجاوز عنصرٌ جديد عنصراً أقدم منه. لو أدخلت الأرقام 5 ثم 8 ثم 3 بهذا الترتيب، فسيخرج أول ما يخرج الرقم 5، ثم 8، ثم 3 — تماماً بترتيب الوصول.
عادةً يوفّر الطابور عمليتين مساعدتين أيضاً: Peek (أو Front) لقراءة العنصر الأمامي دون حذفه، وisEmpty للتأكد أن الطابور غير فارغ قبل محاولة الإخراج — وتجاهل هذه الخطوة سبب شائع جداً للأخطاء البرمجية.
FIFO مقابل LIFO: لا تخلط بينهما
أكبر التباس يقع فيه المبتدئون هو الخلط بين الطابور (FIFO) والمكدّس Stack الذي يعمل بمبدأ LIFO (آخر ما يدخل أول ما يخرج، مثل رصّ الأطباق فوق بعضها). الفرق جوهري:
| الوجه | FIFO — الطابور Queue | LIFO — المكدّس Stack |
|---|---|---|
| القاعدة | الوارد أولاً يخرج أولاً | الوارد أخيراً يخرج أولاً |
| التشبيه | طابور انتظار | كومة أطباق |
| نقطة الإدخال | الخلف | القمة (Top) |
| نقطة الإخراج | الأمام | القمة (Top) |
| استخدام نموذجي | جدولة المهام، معالجة الطلبات بالترتيب | التراجع Undo، تتبّع استدعاءات الدوال |
القاعدة الذهنية: إن كان العدل والترتيب الزمني مهمّين اختر FIFO، وإن كنت تحتاج الرجوع للخلف اختر LIFO.
الطابور الدائري (Circular Queue) ولماذا نحتاجه
عند تنفيذ الطابور بمصفوفة ذات حجم ثابت، ومع كثرة الإدخال والإخراج، يتحرّك مؤشّرا الأمام والخلف نحو نهاية المصفوفة فتبدو ممتلئة رغم وجود أماكن فارغة في بدايتها. الحل هو الطابور الدائري، الذي يعامل المصفوفة وكأنها حلقة مغلقة: عندما يصل المؤشّر إلى النهاية يعود إلى البداية ليعيد استخدام الخلايا المُفرَّغة. هذا يرفع كفاءة استخدام الذاكرة ويلغي الحاجة إلى إزاحة العناصر يدوياً.
أين تُستخدم FIFO في الواقع؟
المبدأ ليس نظرياً؛ أنت تستفيد منه يومياً دون أن تدري:
- طابور الطباعة: المستندات تُطبع بترتيب إرسالها.
- جدولة العمليات في أنظمة التشغيل: خوارزمية FCFS (First-Come, First-Served) تخدم أول عملية وصلت أولاً.
- الشبكات والراوترات: حزم البيانات تُعالَج بترتيب وصولها في طوابير الانتظار.
- أنظمة الرسائل والمهام (Message Queues): مثل RabbitMQ وKafka التي تنظّم ملايين الطلبات في التطبيقات الحديثة.
- خوارزمية BFS (البحث بالعرض أولاً): تعتمد على طابور لاستكشاف الرسوم البيانية والشبكات مستوى بمستوى.
وفي المحاسبة والمخازن، لـ FIFO معنى مماثل: البضاعة التي دخلت المخزن أولاً تُباع أو تُصرف أولاً — وهو مفهوم مهم في تقييم المخزون.
خطأ شائع يجب تجنّبه
كثيرون يستخدمون قائمة عادية (Array/List) ويحذفون العنصر الأول بدالة مثل حذف الفهرس صفر، ثم يتفاجؤون بأن البرنامج يبطؤ مع الكبر. السبب أن حذف العنصر الأول من مصفوفة يفرض إزاحة كل العناصر الباقية، فتصبح كلفته كبيرة. الحل: استخدم بنية طابور حقيقية بزمن ثابت لكل عملية — مثل deque في بايثون، أو ArrayDeque/LinkedList في جافا، أو Queue<T> في #C. عندها تصبح عمليتا الإدخال والإخراج سريعتين ومستقرتين مهما كبر الطابور.
الأسئلة الشائعة
هل FIFO خوارزمية أم هيكل بيانات؟ هو مبدأ أو سياسة ترتيب. الطابور (Queue) هو هيكل البيانات الذي يطبّق هذا المبدأ، وقد تُبنى عليه خوارزميات مثل BFS وجدولة FCFS.
ما الفرق بين FIFO وFCFS؟ لا فرق جوهري في المعنى؛ FCFS (First-Come, First-Served) هو الاسم المستخدم غالباً في جدولة العمليات، وهو تطبيق مباشر لمبدأ FIFO.
ما سرعة عمليات الطابور؟ عند تنفيذه بشكل صحيح (قائمة مترابطة أو مصفوفة دائرية)، تكون كلفة الإدخال والإخراج ثابتة، أي O(1) لكل عملية، وهذا ما يجعله فعّالاً جداً.
متى أختار الطابور بدل المكدّس؟ اختر الطابور حين يهمّك الحفاظ على الترتيب الزمني والعدالة (من وصل أولاً يُخدَم أولاً)، واختر المكدّس حين تحتاج معالجة أحدث عنصر أولاً أو التراجع خطوة للخلف.