الكومة الصغرى تسمح باختيار أصغر عنصر دون ترتيب جميع مواضع القائمة ترتيبًا كاملًا. سنختار كومة أصلية من سبعة أعداد، ونراجع القراءة والإزالة والتعادل، ثم نقارن عمليتين مركبتين تعطيان نتائج مختلفة على المرشح نفسه. الكود والبيانات أمثلة تعليمية محلية، مع شروط واضحة لما تمثله الأولوية.
الخلاصة السريعة
الكومة الصغرى تحفظ شرطًا بين كل أب وأبنائه، فتضع أصغر عنصر عند الجذر. لا يفرض ذلك ترتيب القائمة كاملةً، ولا يحدد معنى الأولوية خارج نموذج البيانات.
- القائمة[3,8,5,14,10,9,6]كومة صغرى صالحة رغم أن 8 يسبق 5 في تمثيلها. استخراج جميع عناصرها بالأصغر يعطي 3,5,6,8,9,10,14.
- مع الفهرسة من 0، ابنا الموضع k هما 2*k+1 و 2*k+2 إذا وجدا. الجذر عند 0 لا يزيد على أي عنصر آخر في كومة عددية صالحة.
- قراءة heap[0]لا تزيل العنصر، بينما heappop يعيد الأصغر ويعدّل الكومة. نتحقق من عدم الفراغ قبل القراءة أو نختار عقدًا واضحًا للإخفاق.
- على الكومة[5,11,9]مع العنصر 2، heappushpop يعيد 2 ويبقي القيم القديمة، و heapreplace يعيد 5 ويدخل 2 مكان الجذر القديم.
- إذا أدخلنا 8 على المثال السابق، تعيد العمليتان 5 وتحتفظان بالقيم 8 و 9 و 11. اتفاق حالة واحدة لا يجعل عقديهما متطابقين.
- للأولويات المتساوية، سجل(الأولوية،عدادالإضافة،المهمة)يحدد ترتيب التعادل ويمنع مقارنة حمولتين غير قابلتين للمقارنة ما دام العداد فريدًا.
- تغيير قيمة داخل الكومة مباشرةً قد يكسر شرطها؛ لا نفترض أن الجذر يتحدث تلقائيًا بعد تعديل عنصر دون عملية تحافظ على البنية.
- الرقم الأصغر يمثل خدمة أسبق في نموذجنا فقط. طابور الأولوية لا يحل اعتمادات المهام، وقياس رتبة العمليات لا يثبت زمنًا فعليًا أو عدالة انتظار.
طابور الأولوية والبنية التي تمثله
يصف مرجع NIST طابور الأولوية بأنه نوع بيانات يدعم إدخال عناصر والعثور على العنصر ذي الأولوية المناسبة وإزالته. يمكن تمثيل ذلك بأكثر من بنية، والكومة إحدى وسائل التنفيذ. وتوضح وثائق Python أن heapq يستعمل قوائم لتمثيل كومة صغرى؛ سنختار أعدادًا وأسماء أصلية وننفذ عملياتها محليًا بدل الاعتماد على صورة مرتبة كاملة.
نستعمل في الأمثلة أولويات صحيحة العدد ومقارنة ثابتة، ونعلن أن رقمًا أصغر يعني اختيارًا أسبق. هذا اتفاق نموذجنا، وليس حكمًا أن كل نظام عمل يستعمل المعنى نفسه لكلمة أولوية. إذا كانت أرقامك تصف درجات يفضّل أكبرها، تحتاج اتجاهًا آخر أو تحويلًا معلنًا للمقارنة. لا تغير معنى الرقم لأن طريقة جاهزة ترجع الأصغر.
كما نميز اسم البنية من وظيفتها. الكومة تحفظ ترتيبًا جزئيًا بين المواضع، والطابور يقدم عملية اختيار بحسب الأولوية. قد تحتاج سجلاتك إلى معلومات إضافية عن التعادل أو هوية المهمة أو صلاحية تنفيذها. سنراجع هذه المعاني إلى جانب العدد الذي يرجع من الدالة، كي لا يتحول نجاح استخراج أصغر رقم إلى قرار لم تتضمنه بيانات المثال.
قائمة صالحة لا تبدو مرتبة تصاعديًا
نختار الكومة 3 و 8 و 5 و 14 و 10 و 9 و 6. عند الجذر 3 يوجد الابنان 8 و 5، وكلاهما لا يقل عنه. تحت 8 نجد 14 و 10، وتحت 5 نجد 9 و 6. كل علاقة أب وابن تحقق الشرط، لذلك التمثيل صالح في نموذج الأعداد. لكن القيمة 8 في الموضع 1 أكبر من 5 في الموضع 2، فلا تكون القائمة مرتبة تصاعديًا عند قراءتها من اليسار إلى اليمين.
هذا ليس عطلًا نصلحه بترتيب الأبناء في الرسم حسب مقدارهم. العلاقة لا تطلب أن يكون الابن الأيسر أصغر من الأيمن، ولا أن تقارن قيمة في فرع بكل قيمة في الفرع الآخر. الكومة تجعل الطريق من الجذر إلى ورقة غير متناقص، بينما يبقى ترتيب المواضع من قائمة أخرى سؤالًا منفصلًا.
الرسم الرئيسي يعرض الفهارس والقيم في شجرة، ثم يكتب القائمة التي تمثلها بالفهرسة من 0. الأرقام الموضوعة عند العقد قيم العناصر، والفهارس تشرح مواضعها. إذا خلطت بينهما، قد تقارن أرقام مواضع بدل مقارنة عناصر الكومة. نراجع كل سهم أبوة في الرسم، لا مظهر القائمة وحده، ثم نفسر ما يضمنه هذا الشرط بالفعل.
فهارس الأبناء وحدود وجودهما
في تمثيل الكومة بقائمة تبدأ فهرستها من 0، ينتقل الموضع k إلى ابنين عند 2*k+1 و 2*k+2 إذا كانا داخل طول القائمة. هذه العلاقة موثقة في heapq. في مثالنا، الموضع 0 له ابنان 1 و 2، والموضع 1 له 3 و 4، والموضع 2 له 5 و 6. المواضع 3 حتى 6 أوراق في القائمة ذات السبعة عناصر، فلا نحاول قراءة أبنائها خارج الحدود.
لفحص الموضع 2، نقارن القيمة 5 مع 9 عند 5 ومع 6 عند 6. لا نقارنها بالفهرسين 5 و 6 بوصفهما قيمتين؛ اتفاق القيمة 6 مع رقم موضعها 6 في هذه القائمة مجرد اختيار عددي. الفصل بين العمودين يجعل المراجعة مفهومة عند تغيير مثال إلى آخر تختلف فيه هذه الأرقام.
يمكن الرجوع إلى الأب للموضع غير الجذري بالفهرس(k-1)//2 في هذا النموذج. للموضع 6 الأب 2، وللموضع 4 الأب 1. أما الجذر 0 فليس له أب داخل الشجرة. لا نستعمل الصيغة عنده ثم نقرأ آخر عنصر بفهرس سالب في Python. علاقة حسابية صالحة للمواضع غير الجذرية تحتاج مجالها المعلن قبل تطبيقها على حد مختلف.
الجذر هو الأصغر لكن بقية المواضع ليست رتبًا
كل عنصر في الشجرة يمكن الوصول إليه من الجذر عبر سلسلة آباء وأبناء. في كومة صغرى عددية صالحة، لا يزيد الأب على الابن في كل خطوة، لذلك لا يزيد الجذر على أي عنصر نصل إليه. هذا يفسر وجود الأصغر في الموضع 0 دون طلب أن تكون جميع مواضع القائمة مرتبة تصاعديًا.
ولا نستنتج أن الموضع 1 يحمل ثاني أصغر عنصر. في مثالنا الموضع 1 يحمل 8، بينما توجد 5 و 6 قبلها في الترتيب العددي للأصغر. إذا أردنا ثاني أصغر، يمكن استخراج الأصغر ثم قراءة الجذر الجديد في نسخة أو اختيار طريقة تلائم المطلوب. لا نحول فهرس القائمة إلى رتبة عددية لكل عنصر لمجرد أن الجذر له الخاصية الخاصة التي أثبتناها.
كذلك قد توجد نسخ متساوية من القيمة الدنيا في أكثر من موضع. استخراج واحدة لا يعني إزالة جميع العناصر ذات الأولوية نفسها. نحدد هل العملية تختار عنصرًا واحدًا أم تجمع كل المتساوين. المثال الأول أرقام مختلفة في الغالب، لكن شرط الكومة يسمح بالتساوي، ولهذا سنخصص لاحقًا جزءًا لمعنى التعادل عند ربط الأرقام بمهمات.
القراءة والإزالة تغيران الحالة بطريقتين
قراءة heap[0]في المثال تعطي 3 ولا تعدل عدد عناصره. أما heappop على نسخة من الكومة فيعيد 3 ويزيل عنصرًا، فتكون أصغر قيمة باقية 5 وعدد العناصر 6. إذا أعدنا الإزالة حتى الفراغ حصلنا على 3 و 5 و 6 و 8 و 9 و 10 و 14. هذا ترتيب استخراج، لا صورة القائمة الأصلية التي ما زلنا نعرضها في الرسم.
نحفظ نسخة من المدخلات إذا أردنا مقارنة القراءة بحالة الإزالة دون إتلاف قائمة المثال التي نراجعها. النسخة هنا قائمة جديدة للأعداد، وليست ادعاءً عن نسخ عميق لكل نوع سجل قد تحمله بنية أخرى. وعند العمل على كومة فارغة، لا نقرأ الموضع 0 ولا ننفذ heappop دون اختيار كيفية معالجة الإخفاق؛ وثائق الواجهة تحدد IndexError لإزالة عنصر من الفراغ.
لا نجعل معرفة عدد العناصر بعد العملية دليلًا على هوية العنصر الذي أزيل. نراجع القيمة المرجعة ومجموعة القيم الباقية وشرط الكومة. قد تتغير مواضع عناصر كثيرة أثناء إعادة البنية، لذلك لا نحفظ فهرسًا قديمًا ثم نستعمله بوصفه معرفًا ثابتًا للمهمة بعد عمليات لاحقة. القيمة والهوية والمكان في التمثيل أدوار مختلفة.
إضافة عنصر وصعوده في المسار
نضيف 4 إلى نسخة من الكومة الأصلية ذات السبعة عناصر. يبدأ موضعه الجديد عند 7، وأبوه عند 3 وقيمته 14. لأن 4 أصغر، يصعد في مقارنة المثال إلى موضع الأب، ثم يقارن بالموضع 1 ذي القيمة 8، فيصعد مرة أخرى. يقف عند مقارنة الجذر 3، لأن 4 لا ينبغي أن يسبقه في الكومة الصغرى.
الناتج يظل فيه 3 عند الجذر، و 4 قريبًا منه بعد تصحيح العلاقات، ويصبح عدد العناصر 8. لا يلزم ترتيب كامل لجميع العناصر أثناء الإضافة. ما نراجعه هو حفظ مجموعة القيم مع العنصر الجديد، وحفظ شرط الأبوة، وكون الجذر ما زال أصغر قيمة. سننفذ heappush على بيانات المثال ونتحقق من هذه الشروط محليًا.
ولا نعرض المسار بوصفه مدة أو عدد دورات معالج مضمونًا لكل نسخة من كل لغة. اختيار كومة أخرى صالحة للقيم نفسها قد يغير المواضع والمسار الداخلي. الرسم يثبت تمثيلًا محددًا قبل العملية، والوصف يتتبع المعنى الذي نراجعه فيه. نحتاج أن نميز النتيجة العامة المطلوبة من تفاصيل حالة تنفيذ شاهدناها في نموذج صغير.
بناء كومة من قائمة عادية
نبدأ قائمة غير مهيأة بهذه القيم: 14 و 3 و 9 و 8 و 6 و 10 و 5. نستعمل heapify لبناء كومة صغرى داخل القائمة، وفق عقد الواجهة. بعد العملية يجب أن يكون الجذر 3 وأن تبقى القيم نفسها مع تكراراتها، وأن يصدق شرط كل أب مع أبنائه. لا نشترط أن تطابق جميع المواضع شكل الرسم الأول حرفيًا؛ قد توجد تمثيلات صالحة متعددة لمجموعة القيم نفسها.
وحتى لو صادف أن أعاد تنفيذ معين الشكل المتوقع، فالمراجعة الأساسية للشروط لا لترتيب غير موثق لكل موضع. إذا أردنا قائمة مرتبة كاملة، فالهدف مختلف عن تهيئة كومة. يمكن استخراج العناصر تباعًا من نسخة مهيأة للتحقق من ترتيبها، أو استخدام عملية ترتيب مناسبة عندما يكون ذلك هو المخرج المطلوب.
يشير توثيق heapify إلى بناء خطي في عدد العناصر. لا نحول هذا الوصف إلى زمن ثابت بوحدة ثانية، ولا نقيس أداء ملف من سبعة أعداد. كذلك لا ننسب صحة البيانات إلى الدالة؛ هي تبني البنية من القيم التي أعطيناها، ولا تتحقق من معنى الأرقام أو من أن وحدة الأولوية متسقة بين سجلات لم نحددها في المثال.
ادفع ثم اسحب: معنى heappushpop
نختار كومة صغيرة 5 و 11 و 9، ونقترح إدخال 2 مع إزالة الأصغر من القيم التي يشملها هذا الاقتراح. heappushpop يعيد 2، فتظل القيم 5 و 11 و 9 في الكومة. العدد الجديد هو الأصغر، لذلك لم يصبح واحدًا من القيم الثلاثة المحتفظ بها. لا نقرأ القيمة المرجعة 5 من اسم العملية وحده؛ نحتاج أن نعرف أنها تجمع إدخال المرشح ثم إزالة الأصغر.
وبالعنصر 8 بدل 2، تعيد العملية 5، وتبقى القيم 8 و 9 و 11. المرشح 8 أكبر من الجذر القديم، فيدخل المجموعة المحتفظ بها، بينما يخرج 5. في الحالتين حجم الكومة لم يتغير، لكن هوية ما خرج وما بقي تختلف بحسب قيمة المرشح. سنراجع أيضًا حالة الفراغ محليًا؛ في هذه العملية يعاد المرشح وتبقى الكومة فارغة.
هذه الأعداد نموذج لا ترتيب أهمية طبيعية لكل موقف. إذا كنا نحتفظ بثلاث قيم أكبر مما وصل، يشرح المثال لماذا لا ينبغي قبول مرشح أصغر منها لمجرد أنه جديد. أما إذا كان القرار يريد إخراج الجذر القديم دائمًا، فهذه ليست النية نفسها، وننتقل إلى عقد الاستبدال الذي سنقارنه في الرسم الداخلي.
اسحب ثم استبدل: معنى heapreplace
على الكومة 5 و 11 و 9 مع العنصر 2، تعيد heapreplace الجذر القديم 5 وتحتفظ بالقيم 2 و 9 و 11. النتيجة مختلفة من heappushpop التي أعادت 2 وأبقت 5. هنا اخترنا إزالة عنصر من المجموعة القائمة ثم إدخال الجديد، لا اختيار الأصغر من المجموعة بعد إضافة المرشح. حجم الكومة ثابت في المثالين، لكنه لا يحدد عقد القرار وحده.
وعندما يكون العنصر الجديد 8، تعيد heapreplace أيضًا 5 وتبقي 8 و 9 و 11، فتتفق نتائج العمليتين في هذه الحالة. لا نستنتج التطابق العام من هذا الاتفاق، لأن الحالة 2 قد أعطت بالفعل نتيجتين مختلفتين. الرسم الثاني يعرض المثال المضاد بتثبيت الكومة والمرشح، ثم يفصل ما يرجع من كل عملية وما يبقى داخلها.
تحتاج heapreplace إلى كومة غير فارغة، وتحدد الواجهة IndexError عند استدعائها على فراغ. لا نجعل حجمًا ثابتًا مرغوبًا سببًا لاختيارها دون فحص شرطها ومعنى الإخراج. إذا كنت تريد أن يعاد المرشح الأصغر نفسه بدل إزالة قديم أكبر منه، فراجع عقد heappushpop. الاسم المختصر للحركة ليس بديلًا عن قراءة القيم الداخلة والمخرجات التي نحتاجها.

تساوي الأولويات لا يحدد ترتيب وصول عادلًا
نفترض مهمتين مستقلتين بأولوية عددية 3. إذا خزنا الزوجين من رقم الأولوية والاسم، فقد تقارن البنية الاسمين عند تعادل الرقمين. هذه مقارنة مسموحة إذا كان الاسمان نصين قابلين للمقارنة، لكنها تمثل ترتيبًا للنصوص، لا بالضرورة أسبقية إضافة أو مدة انتظار. نحتاج سياسة التعادل التي يريدها نموذجنا بدل استنتاجها من الاسم.
وإذا كانت الحمولة قاموسًا، فإن مقارنة قاموسين عند تعادل الأولوية لا تقدم الترتيب المطلوب في Python وقد ترفع TypeError. لا نعالج ذلك بتغيير الأولوية اعتباطيًا حتى نتخلص من التعادل. الخطأ يتعلق بعقد المقارنة للعنصر المخزن، والقرار الدلالي يتعلق بمن يخدم أولًا إذا تساوت الأولوية الأساسية.
في نموذجنا نضيف عدادًا فريدًا متزايدًا بين الأولوية والحمولة. بذلك تقارن السجلات الأولوية أولًا، ثم رقم الإضافة إذا تعادلت، ولا تصل المقارنة إلى قاموس المهمة ما دام العداد فريدًا. توثق الواجهة هذه الفكرة؛ سنستعمل كودًا صغيرًا لبيانات مؤلفة ونراجع أن ترتيب التعادل صار معلنًا. هذا لا يثبت سياسة عادلة لكل نظام، بل ينفذ سياسة اخترناها صراحةً.
كود يعلن مفاتيح المقارنة الثلاثة
الكود التالي يقبل تسلسلًا من أزواج أولوية عددية وحمولة، ثم يعيد الحمولات وفق رقم أصغر أولًا، ومع التعادل حسب الإضافة. ندخل جميع الأزواج قبل استخراجها في هذا النموذج، ولا ننفذ مهام الحمولات نفسها. عدادنا يبدأ 0 ويتقدم مرة لكل إضافة، لذلك لا تتكرر قيمته داخل الكومة التي تنشئها الدالة.
نختار حمولة ألف بأولوية 3، وباء بأولوية 1، وجيم بأولوية 3. المخرج باء ثم ألف ثم جيم. السبق بين ألف وجيم من عداد الإضافة، وليس من ترتيب قاموسي الاسم. إذا غيرنا ترتيب إدخالهما مع ثبات الأولويات، تغير ترتيب تعادلهما وفق السياسة نفسها. لا نحكم بأن ذلك خطأ في الكومة، بل نراجع أن السياسة الجديدة تطابق المطلوب.
نفحص الكود محليًا بقواميس مؤلفة كي تظهر فائدة الفصل بين مفتاح المقارنة والحمولة. كما نراجع الحالة الفارغة والتكرارات في الرقم. لا ندعي أن الدالة تعالج تحديث الأولوية أو حذف مهمة وسط الطابور أو حالات عمل متزامن؛ لم نضع لهذه العمليات عقدًا في المثال. الكود يشرح مفاتيح اختيار معلنة ضمن نطاق صغير قابل للمراجعة.
def priority_order(entries):
import heapq
queue = []
for serial, (priority, payload) in enumerate(entries):
heapq.heappush(queue, (priority, serial, payload))
result = []
while queue:
priority, serial, payload = heapq.heappop(queue)
result.append(payload)
return result
تعديل داخل القائمة قد يكسر البنية
نعود إلى الكومة 3 و 8 و 5 و 14 و 10 و 9 و 6، ونغير القيمة الأخيرة 6 إلى 1 مباشرةً. صار الأب عند الفهرس 2 يحمل 5 بينما ابنه 1 أصغر منه. الشرط لم يعد صحيحًا، والجذر 3 لم يعد أصغر قيمة موجودة. قراءة الجذر بعد هذا التعديل لا تشهد أن 1 اختفت أو أن ترتيبها أصبح مناسبًا تلقائيًا.
إذا أعدنا بناء البنية على هذه القيم بعملية معلنة، يمكن التحقق من عودة 1 إلى الجذر وحفظ بقية القيم. لكننا لا نعرض تعديل مكان قديم بوصفه واجهة تحديث أولوية لكل طابور سجلات. عندما يرتبط المفتاح بحمولة، قد تكون الأولوية المخزنة قيمة مستقلة عن حقل عدلته داخل القاموس؛ لا يفترض الطابور أن أي حقل في الحمولة يغير مفتاحه المحفوظ.
كذلك لا نستنتج من حدوث استثناء أن عملية مقارنة فاشلة أعادت كل قائمة إلى حالتها الأصلية. في تجربة محلية على زوجي أولوية متساويين وحمولتين قاموسيتين، نستخدم نسخة جديدة ثم نراجع الحالة بدل مواصلة افتراض أن البنية ما زالت صالحة. معالجة الإخفاق تحتاج عقدًا يناسب تطبيقك؛ نموذجنا يحتفظ بالحالات الخاطئة منفصلة عن الحالات الصحيحة التي نجري عليها بقية الفحوص.
سجل القيمة المرجعة وما بقي معًا
لفهم العملية، سجل ثلاث معلومات: القيم قبلها، والقيمة المرجعة، والقيم بعد انتهاء العملية مع عددها. في مثال heapreplace مع 2، كانت القيم 5 و 11 و 9، والراجع 5، والباقي 2 و 9 و 11. وفي heappushpop مع 2 كان الراجع 2 والباقي 5 و 9 و 11. لو حفظت الحجم 3 فقط لضيعت الفرق الذي أردنا شرحه.
ولمراجعة مجموعة القيم، نقارن قوائمها بعد ترتيب نسخ منها بدل توقع ترتيب داخلي واحد لكل موضع. شرط الكومة يبقى مطلوبًا مستقلًا عن هذه المقارنة؛ مجموعة صحيحة قد تحفظ الأرقام لكنها تضع أبًا أكبر من ابن. كذلك الجذر الصحيح وحده لا يثبت كل الشروط إذا كانت إحدى علاقات الفروع معطلة بعيدًا عنه.
ونجعل كل اختبار يبدأ ببياناته المعلنة أو نسخة واضحة منها. لا نستعمل كومة استهلكناها بالإزالة ثم نصفها مرة أخرى على أنها الحالة الأصلية. تتابع العمليات يغير الحالة، لذلك تلزم سجلاتها لإعادة التفسير. هذه مراجعة لعمليات على أرقام مؤلفة، وليست تقرير زمن أو صحة لطابور نظام لم نقرأ حالته أو معنى مفاتيحه.
الأولوية لا تعني جاهزية المهمة
يمكن أن تحمل مهمة رقمًا صغيرًا جدًا مع أنها تنتظر متطلبًا لم يكتمل. الكومة التي ترتب الرقم وحده لا تعرف ذلك المتطلب، ولا يجوز استنتاج صلاحية التنفيذ من الجذر إذا كان نموذج العمل يحتاج اعتمادًا إضافيًا. نستطيع في نموذج محدد وضع المهام الجاهزة فقط في طابور الأولوية، ثم اختيار واحد منها وفق الرقم والسياسة المعلنة.
هذا يربط قرارين مختلفين: ما المهام التي يجوز بدءها من جهة الاعتماد، وأيها نختار من جهة الأولوية. نحدد مجموعة المهام التي تسمح متطلباتها بالبدء، ثم نطبق سياسة الأولوية على تلك المجموعة. لا نجعل ترتيب الأرقام جوابًا عن شروط لم تدخل في مفاتيح الكومة، ولا نعطي مهمة محجوبة حق البدء لأنها تحمل الرقم الأصغر فقط.
ولا تعني سياسة رقم أصغر أولًا أن كل عنصر سيحصل على مدة انتظار محدودة في وصول مستمر لعناصر جديدة ذات أرقام أصغر. لم نحلل سياسة انتظار زمنية في نموذجنا المنتهي. نذكر فقط أن استخراج العناصر التي أدخلناها مرة واحدة يحقق ترتيبها المعلن. المعنى العملي للعدل أو الحاجة أو اكتمال الاعتماد يحتاج بيانات وقواعد أخرى غير مصفوفة الأولويات.
فحوص محلية تحترم نطاق الادعاء
نتحقق من شرط كل أب وابن في الكومة المختارة، ثم ننفذ عمليات القراءة والإزالة والإضافة ونقارن مجموعات القيم. نراجع مثالي المرشح 2 والمرشح 8 في العمليتين المركبتين، ثم نختبر الفراغ والتعادل. لهذا تحفظ المراجعة سلوكًا قابلًا لإعادة التنفيذ بدل قول إن جميع العمليات تؤدي النتيجة نفسها لأنها تشبه أسماء حركات متقاربة.
نضيف حالات عددية صغيرة ونقارن مجموعة ما بقي بما تتوقعه عملية صريحة على قائمة عادية. هذا مرجع مستقل لقرار إخراج الأصغر أو استبدال القديم. لا نعلن أن تعداد الحالات المحدود يثبت كل سلوك لكل نوع حمولة أو مقارنات مخصصة. قوائمنا أعداد صحيحة وسجلات بسيطة، ولا نقيس كلفة المقارنة أو ملفًا كبيرًا مجهولًا.
كما نحفظ نسخة Python التي نفذنا بها المثال ونسخة الوثائق التي رجعنا إليها. ما لاحظناه من مواضع داخلية يوصف بوصفه نتيجة تجربة محددة، أما الجذر ومجموعة القيم وشرط الكومة فهي شروط المراجعة العامة هنا. إذا اختلف شكل قائمة صالحة أخرى، نراجع العقد قبل نسب الاختلاف إلى عطل. هذه الخطوات تميز النتيجة الموثقة من ملاحظة عرضية في نموذج صغير.
قائمة مراجعة عند اختيار طابور أولوية
عرّف ما يعنيه الرقم واتجاه الاختيار، ثم ميز الكومة الصغرى من قائمة مرتبة كاملة. راجع الفهرسة وحدود أبناء كل عقدة، ولا تعامل الموضع 1 بوصفه رتبة ثاني أصغر. قبل قراءة الجذر تحقق من وجود عنصر، وقبل عملية مركبة اكتب هل تريد إخراج أصغر مرشح بعد الإضافة أم إخراج عنصر قديم ثم استبداله.
وعند تساوي الأولويات، حدد سياسة التعادل ومفاتيح المقارنة التي تنفذها. احفظ هوية المهمة في الحمولة دون افتراض أن القاموس نفسه قابل للمقارنة، ولا تغير عنصرًا داخل التمثيل ثم تستعمل الجذر كما لو أن البنية أعيدت تلقائيًا. افصل نسخة المراجعة من الحالة التي استهلكت بالعمليات، وسجل القيمة المرجعة والباقي معًا.
وأخيرًا، اربط الادعاء بالبيانات التي حسبتها فعلًا. أمثلتنا قوائم وسجلات أصلية منفذة محليًا، لا قياسات خدمة أو ضمان سرعة أو عدالة. يمكن إعادة مقارنة العمليتين على 5 و 11 و 9 مع المرشح 2، ثم فحص كومة السبعة عناصر في الرسم. حين تظهر المفاتيح والشروط والنتائج معًا، يصبح سبب اختيار العملية مفهومًا قبل نقلها إلى مسألة أخرى.
ولمعنى الموقع مقارنةً بالقيمة في بنية بيانات، اقرأ الفهرس داخل الصف والمحور المحدد.
المصادر ومتابعة القراءة
- Python3.14: heapq والكومة الصغرى والعمليات والتعادل (يفتح في نافذة جديدة)docs.python.org
- NIST: تعريف طابور الأولوية وعمليات الاختيار (يفتح في نافذة جديدة)xlinux.nist.gov
أُعدّ هذا المقال بصياغة عربية أصلية بالاستناد إلى المصادر أعلاه، وهو مدخل تمهيدي إلى الموضوع. اقرأ منهجية المحتوى وحدوده.
