مكدس عام
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 59 من 61.
التحدي
سهلتُعد المكدس (stack) بنية بيانات أساسية تتبع مبدأ "آخر من يدخل هو أول من يخرج" (LIFO)—أي أن آخر عنصر تمت إضافته هو أول عنصر يتم إزالته. فكر في كومة من الأطباق: أنت تضيف الأطباق إلى الأعلى وتزيلها من الأعلى.
لنقم ببناء بنية بيانات Stack عامة (generic) يمكنها الاحتفاظ بأي نوع من العناصر! يتبع المكدس مبدأ "آخر من يدخل هو أول من يخرج"—مثل كومة من الكتب حيث يمكنك الإضافة أو الإزالة من الأعلى فقط.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
stack.rs: قم بتعريف هيكلStack<T>العام الذي يستخدمVec<T>داخلياً لتخزين العناصر. قم بتنفيذ ثلاث دوال:newلإنشاء مكدس فارغ، وpushلإضافة عنصر إلى الأعلى، وpopلإزالة وإرجاع العنصر العلوي (بإرجاعOption<T>لأن المكدس قد يكون فارغاً).main.rs: قم باستيراد وحدة المكدس الخاصة بك واستعرض عمل المكدس مع الأعداد الصحيحة. أنشئ مكدساً، وادفع الأرقام المقدمة إليه، ثم اسحب العناصر منه واطبع كل واحد منها. استخدمunwrap_orللتعامل معOptionالذي ترجعه دالة pop—إذا كان المكدس فارغاً، استخدم-1كقيمة افتراضية.
يحتاج المكدس إلى عمليتين أساسيتين:
- push — تضيف عنصراً إلى أعلى المكدس
- pop — تزيل وترجع العنصر العلوي
يجب أن ترجع دالة pop القيمة Option<T> لأن المكدس قد يكون فارغاً. يحتوي النوع Vec بالفعل على دالة pop ترجع Option<T>، والتي يمكنك الاستفادة منها في تنفيذك.
يجب أن يعمل المكدس الخاص بك على النحو التالي: عند دفع القيم 10 و 20 و 30 (بهذا الترتيب)، فإن السحب ثلاث مرات يجب أن يعطيك 30 و 20 و 10 (بالترتيب العكسي). أما السحب الرابع من مكدس فارغ فيجب أن يرجع القيمة الافتراضية.
اطبع كل قيمة مسحوبة في سطر مستقل:
30
20
10
-1على سبيل المثال، مع المدخلات 5 و 15 و 25:
25
15
5
-1ستتلقى ثلاثة مدخلات: ثلاثة أعداد صحيحة لدفعها إلى المكدس (قم بتحليل كل منها كـ i32). بعد دفع الثلاثة جميعاً، قم بالسحب أربع مرات لاستعراض كل من عمليات السحب الناجحة وحالة المكدس الفارغ.
جرّب بنفسك
mod stack;
use stack::Stack;
fn main() {
// قراءة ثلاثة أعداد صحيحة من المدخلات
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let num1: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let num2: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let num3: i32 = input3.trim().parse().expect("Invalid number");
// TODO: إنشاء Stack جديد
// TODO: دفع الأرقام الثلاثة إلى الـ stack (num1، num2، num3 بهذا الترتيب)
// TODO: السحب (Pop) أربع مرات وطباعة كل نتيجة
// استخدم unwrap_or(-1) للتعامل مع حالة الـ stack الفارغ
}
جميع دروس Object Oriented Programming
1الأساليب والسلوك
مقدمة في كتل التنفيذمعامل Selfالأساليب القابلة للتعديلالدوال المرتبطةكتل تنفيذ متعددةتسلسل الأساليبمراجعة - إجراءات المستطيل4مشروع: حيوان أليف افتراضي
تعريف الحيوان الأليفإطعام الحيوان الأليف2التغليف والوحدات البرمجية
أساسيات الوحدات البرمجيةالكلمة المفتاحية Publicالحقول الخاصةدوال Gettersدوال Settersمراجعة - الخزانة الآمنة5الأنواع العامة (Generics)
الـ Structs العامةالـ Methods العامةأنواع عامة متعددةالـ Functions العامةمراجعة - Coordinate Point3التعدادات المتقدمة (Advanced Enums)
التعدادات مع البياناتالأساليب (Methods) في التعداداتمطابقة حالات البياناتمراجعة التعداد Optionملخص - التعداد Shape6تعريف الـ Traits
ما هي الـ Trait؟تنفيذ الـ Traitsالتنفيذات الافتراضيةتجاوز التنفيذات الافتراضيةالـ Traits مع المعاملاتملخص - مشغل الوسائط