كيف تحل واجبات CPCS 204 بدون ما تضيع في الكود واللابات

فريق زدني فريق زدني 11 مايو 2026
9 دقائق للقراءة
كيف تحل واجبات CPCS 204 بدون ما تضيع في الكود واللابات

تفتح واجب CPCS 204 وتقول: الموضوع واضح، Linked List وكم method. بعد ساعة تكتشف أن الكود يكمبايل، بس الناتج غلط. بعد ساعتين يصير عندك 6 نسخ من نفس الملف، كل نسخة تصلح مشكلة وتكسر مشكلة ثانية. وفي النهاية تشك في كل شيء: هل المشكلة في head؟ في size؟ في remove؟ ولا في بيانات الاختبار اللي جربتها؟

وهنا مربط المشكلة في واجبات CPCS 204. المادة مو اختبار حفظ Java. في خطة جامعة الملك عبدالعزيز، CPCS 204 هي Data Structures I بعد CPCS 203، وفكرتها أنك تختار البنية المناسبة وتفهم تكلفة الخوارزمية. الدكتور ما يبغى كودا طويلا فقط. يبغى يشوف هل أنت فاهم كيف تتحرك البيانات منطقيا.

خلنا نتعامل مع الواجب كعملية واضحة: تقرأ، ترسم، تقسم، تكتب، تختبر، ثم تسلم. بدون رمي كود عشوائي في IntelliJ وانتظار المعجزة.

📋 ملخص سريع

  • الفكرة الأساسية: واجبات CPCS 204 تختبر طريقة تفكيرك في data structures، لا حفظك للـ syntax
  • قبل الكود: استخرج المتطلبات والقيود من PDF، خصوصا التعقيد المسموح وطرق التسليم
  • أصعب نقطتين: Linked List references، وRecursion داخل Trees أو BST
  • طريقة العمل: ابدأ بالـ Node، ثم البنية، ثم method واحدة، ثم مثال اختبار صغير
  • قبل التسليم: اختبر الحالات الطرفية، راجع اسم الملف، وارفع قبل الموعد بوقت كافي

اقرأ ملف الواجب كأنه rubric، مو قصة

أكبر خطأ يبدأ من أول 10 دقائق. الطالب يفتح PDF، يقرأ العنوان، يشوف مثال، ويبدأ يكتب. بعدين يكتشف أن المطلوب كان removeById وليس removeByName، أو أن insert لازم تكون O(1)، أو أن استخدام array إضافية ممنوع.

قبل ما تكتب سطر واحد، افتح ورقة واكتب 4 قوائم:

القائمةماذا تكتب فيها؟مثال من CPCS 204
المطلوبكل كلاس وكل ميثود مطلوبةaddFirst, deleteLast, search
القيودممنوعات أو شروط تعقيدلا تستخدم Java Collections
المخرجاتشكل الطباعة أو الملف النهائيقائمة مرتبة، جدول، report
التسليماسم الملف والصيغة والموعدzip على Blackboard

لو ما قدرت تعبئ الجدول، أنت لسا ما فهمت الواجب. لا تستعجل. نصف مشاكل CPCS 204 ما تجي من صعوبة الكود، تجي من أنك حليت سؤالا مختلفا عن السؤال المطلوب.

🔴 قاعدة قبل الكود

كل method في ملف الواجب لازم تتحول لسطر واضح عندك: اسمها، مدخلاتها، مخرجاتها، وحالة فشلها. لو method ما تعرف ترسم مثال عليها، لا تكتبها الآن.

افصل بين فكرة الحل وشكل Java

في CPCS 202 و203 كنت تفكر غالبا بهذه الطريقة: أكتب class، أضيف fields، أكتب loop، أشغل. في CPCS 204 هذا لا يكفي. لازم تفصل بين سؤالين:

  1. ما هي البنية التي أحاول تمثيلها؟
  2. كيف أكتبها في Java؟

خذ Linked List مثلا. قبل Java، عندك فكرة بسيطة: كل node تحمل data وتشير للـ node التالية. أول node اسمها head. آخر node تشير إلى null. أي عملية إضافة أو حذف معناها تغيير سهم واحد أو أكثر.

لما تفهم هذا على ورقة، Java تصير ترجمة. أما لو بدأت من Java مباشرة، بتتعامل مع current.next.next كأنه تعويذة، وليس كعلاقة بين عقد.

لو أساس OOP عندك مهتز من 203، راجع دليل حل واجبات CPCS 203 قبل ما تدخل بعمق في 204. المادة كلها مبنية على classes وobjects وconstructors.

واجب المصفوفات: لا تخسر السهل

أول واجب في CPCS 204 يكون في كثير من الشعب مراجعة قوية على Arrays وOOP وFile I/O، أو تطبيق بسيط يستخدم مصفوفة كمرحلة قبل linked list. هذا الواجب يبدو سهل، لكنه يكشف عادة ثلاث مشاكل:

  • الطالب يخلط بين index وعدد العناصر الفعلي
  • ينسى معالجة array ممتلئة أو فاضية
  • يكتب كل شيء في main بدل تقسيمه إلى methods

افترض أن عندك نظام منتجات. لا تبدأ بواجهة ولا menu. خل البداية من أبسط unit ممكن:

public class Product {
    private int id;
    private String name;
    private double price;

    public Product(int id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public int getId() { return id; }
    public String getName() { return name; }
    public double getPrice() { return price; }
}

بعدها اكتب class ثاني يدير array. أهم شيء: لا تعتبر طول array هو عدد المنتجات. عندك products.length للسعة، وعندك count لعدد العناصر المستخدمة.

public class ProductStore {
    private Product[] products = new Product[50];
    private int count = 0;

    public boolean add(Product p) {
        if (count == products.length) return false;
        products[count] = p;
        count++;
        return true;
    }
}

الفرق بين products.length و count يطلع في الاختبار والواجب. لو بحثت في كل السعة بدل العناصر المستخدمة، راح تمر على null وتطلع لك NullPointerException.

⚠️ فخ array الفاضية

أي method تبحث أو تحذف من array لازم تسأل: ماذا لو count == 0؟ لا تتركها للصدفة. الحالة الفاضية test case أساسي، وليس رفاهية.

واجب Linked List: ارسم قبل ما تلمس head

من هذه النقطة يبدأ CPCS 204 فعلا. Linked List تعلمك معنى dynamic structure. ما عندك index مباشر. عندك بداية، وأسهم، وتنقل خطوة خطوة.

قاعدة لا تكسرها: لا تغير head إلا وأنت قاصد. كثير من الطلاب يكتبون loop يتحرك بـ head نفسه، فيخربون القائمة كلها. استخدم متغير اسمه current للتنقل، واترك head ثابتة إلا في عمليات محددة مثل الإضافة في البداية أو حذف أول عنصر.

اكتب أصغر شكل أولا:

class Node {
    int value;
    Node next;

    Node(int value) {
        this.value = value;
        this.next = null;
    }
}

ثم اكتب addFirst لأنها أسهل عملية وتعلمك كيف يتغير head:

public void addFirst(int value) {
    Node node = new Node(value);
    node.next = head;
    head = node;
    size++;
}

لاحظ الترتيب. لو كتبت head = node قبل node.next = head، فقدت القائمة القديمة. السطران بسيطان، لكن ترتيبهم هو الفرق بين حل صحيح وحل يكسر كل شيء.

بعدها اكتب addLast. في هذه العملية لا تلمس head إلا لو القائمة فاضية:

public void addLast(int value) {
    Node node = new Node(value);
    if (head == null) {
        head = node;
    } else {
        Node current = head;
        while (current.next != null) {
            current = current.next;
        }
        current.next = node;
    }
    size++;
}

قبل ما تكمل remove وsearch، شغل addFirst وaddLast على 3 أرقام فقط. لا تنتظر حتى تكتب 200 سطر. CPCS 204 يعاقب التأجيل في debugging.

كثير من الطلاب يضيعون في Linked List لأنهم فاهمين الفكرة كلاميا، لكن ما يقدرون يرسمونها. لو وصلت هنا وحاس إن head وcurrent وnext كلها متداخلة، لا تكمل عشوائيا.

Linked List موقف معك؟

لو واجب CPCS 204 صار كله NullPointerException وتغييرات في head، أرسل لنا المطلوب ونمشي معك على الرسم والمنطق خطوة خطوة قبل كتابة الحل.

أرسل واجب Linked List

واجب Stack وQueue: لا تحفظ، افهم جهة الحركة

Stack وQueue يبدون أسهل من Linked List، لكن الغلط هنا يكون في اختيار الجهة. Stack يعني آخر عنصر يدخل هو أول عنصر يطلع. Queue يعني أول عنصر يدخل هو أول عنصر يطلع.

لو نفذت Stack باستخدام linked list، خلي push وpop على head. السبب بسيط: كل عملية O(1). أما لو خليت pop من النهاية في singly linked list، بتحتاج تمشي على القائمة حتى قبل الأخير، وتصير O(n).

القرار ليس ذوقا. القرار مرتبط بالتعقيد.

البنيةالعمليةأفضل مكان في linked listالسبب
Stackpushheadإضافة مباشرة
Stackpopheadحذف مباشر
Queueenqueuetailدخول من النهاية
Queuedequeueheadخروج من البداية

لو الواجب طلب Queue، فكر هل عندك tail pointer؟ لو عندك tail، الإضافة في النهاية O(1). لو ما عندك، كل enqueue يحتاج traversal. هذا النوع من القرارات هو بالضبط ما يقيسه CPCS 204.

💡 اسأل عن التعقيد بعد كل method

بعد ما تكتب أي method، اكتب تعليق صغير في ورقتك: O(1)، O(n)، أو O(log n). لو ما تعرف التعقيد، غالبا ما فهمت العملية بالكامل.

Recursion وBST: ابدأ من حالة التوقف

Recursion في CPCS 204 ليست فقرة جانبية. تظهر في trees، traversals، وربما sorting. أكثر خطأ شائع: الطالب يكتب recursive call قبل ما يكتب base case.

قبل أي recursive method، اسأل: متى تتوقف؟

مثال height في شجرة:

public int height(Node root) {
    if (root == null) return -1; // شجرة فاضية

    int leftHeight = height(root.left);
    int rightHeight = height(root.right);

    return 1 + Math.max(leftHeight, rightHeight);
}

شرط root == null ليس تفصيلة. هو الفرامل. بدونه، الكود يستدعي نفسه حتى ينهار.

في BST، لا تبدأ بـ delete. الترتيب الأفضل: search ثم insert ثم traversals. delete آخر شيء، لأنه يجمع كل الحالات:

  • node غير موجودة
  • node ورقة
  • node لها ابن واحد
  • node لها ابنان

لو واجبك فيه BST delete، ارسم شجرة صغيرة واكتب الحالات الأربع تحتها. لا تكتب delete من الذاكرة. هذا الجزء بالذات يفضح الحل المنسوخ، لأن الطالب الذي لم يرسم الشجرة لا يعرف يشرح لماذا اختار in-order successor.

🔴 لا تبدأ بأصعب method

في واجب BST، اكتب search أولا. بعدها insert. بعدها traversal. لما الثلاثة يشتغلون، ابدأ delete. لو بدأت بـ delete من أول يوم، راح تخلط بين أخطاء الإدخال وأخطاء الحذف.

حذف node لها ابنان في BST من أكثر اللحظات التي تعطل الطلاب. تكون فاهم الشجرة، لكن أول ما تنقل قيمة successor وتعيد ربط الفروع، يطلع الناتج غريب.

BST delete مربكك؟

نقدر نراجع معك حالات حذف BST على ورقة قبل الكود، ونوضح لك متى تستخدم in-order successor وكيف تختبر الناتج بدون ما نعطيك حل جاهز للتسليم.

أرسل سؤال BST

اكتب test cases قبل ما تثق في الحل

تشغيل المثال الموجود في ملف الواجب لا يكفي. المثال غالبا يغطي المسار الطبيعي فقط. درجاتك تضيع في الحالات الطرفية.

المقصود بـ test cases هنا ليس بالضرورة اختبارات رسمية يعطيها الدكتور. أحيانا ملف الواجب يعطيك sample input/output فقط، وأحيانا يعطي مثال واحد. أنت تحتاج تبني أمثلة اختبارك بنفسك، لأن المصحح أو الـ TA ممكن يجرب حالات إضافية غير المثال الموجود في PDF.

لأي بنية بيانات، جهز جدول اختبار صغير:

الحالةماذا تختبر؟مثال
فارغةoperation على بنية بلا عناصرremove() من list فاضية
عنصر واحدتغيير head أو rootحذف العنصر الوحيد
أكثر من عنصرtraversal عاديطباعة 5 nodes
قيمة غير موجودةsearch أو deleteحذف id غير موجود
duplicateهل مسموح؟إدخال نفس id مرتين

اكتب main صغير للاختبار، حتى لو الواجب لا يطلبه. لا تخلط test code مع الحل النهائي لو الدكتور طلب ملفات محددة، لكن استخدمه أثناء التطوير.

public static void main(String[] args) {
    MyList list = new MyList();
    list.addLast(10);
    list.addLast(20);
    list.addFirst(5);

    list.print();       // 5 10 20
    list.remove(10);
    list.print();       // 5 20
}

اقرأ الناتج بعين ناقدة. لا تكتفي أنه “طلع شيء”. هل الترتيب صحيح؟ هل size تغير؟ هل head مازال صحيح؟ هل العملية الثانية ما كسرت الأولى؟

لما الناتج يختلف عن sample output

هذا الموقف يتكرر كثير: تشغل البرنامج، الناتج قريب من المطلوب، لكن مو مطابق. لا تبدأ تعدل عشوائيا في هذه اللحظة. اختلاف sample output له 4 أسباب شائعة:

نوع الاختلافغالبا سببهكيف تفحصه؟
عنصر ناقصinsert أو remove تجاهل حالةاطبع size بعد كل عملية
ترتيب غلطaddFirst بدل addLast أو العكسارسم القائمة قبل الطباعة
تكرار عنصرduplicate handling ناقصجرب نفس id مرتين
crash في النهايةtraversal تجاوز nullراقب current في debugger

ارجع لأول عملية يظهر بعدها الاختلاف. لا تقرأ آخر 50 سطرا وتقول “الكود كله غلط”. في data structures، الخطأ الصغير ينتشر. لو size صار غلط في العملية الثالثة، كل ما بعدها يبان غلط حتى لو methods الثانية صحيحة.

طريقة عملية: بعد كل operation في main، اطبع اسم العملية والناتج:

System.out.println("After add 10:");
list.print();

System.out.println("After remove 10:");
list.print();

هذه الطباعة مؤقتة. قبل التسليم احذفها أو علقها حسب المطلوب. الهدف أنها تكشف لك متى بدأ الخلل. كثير من الطلاب يقضون ساعة في remove، ثم يكتشفون أن المشكلة أصلا في addLast.

💡 لا تثق في آخر نتيجة فقط

في واجبات CPCS 204، آخر print لا يكفي. اختبر بعد كل عملية أساسية. البنية قد تكون صحيحة بعد أول إدخال، وتنكسر بعد حذف أول عنصر، ثم تظهر المشكلة بعد خمس عمليات.

استخدم debugger بدل التخمين

قراءة الكود بعينك مفيدة، لكنها لا تكفي لما المشكلة في references. في Linked List، السطر يبدو صحيحا، لكن current.next يكون null في وقت لم تتوقعه. وقتها debugger يوفر عليك وقتا كبيرا.

تعلم أربع أدوات فقط في البداية:

  • Breakpoint: ضع نقطة توقف قبل loop أو قبل تغيير pointer
  • Step over: نفذ السطر الحالي بدون دخول method أخرى
  • Step into: ادخل method تريد فحصها من الداخل
  • Watch: راقب قيمة head, current, current.next, size

لا تحتاج تكون خبير IDE. فقط شغل الواجب على test صغير، مثل 3 nodes، وامش سطرا سطرا. لو القائمة فيها 100 عنصر، أنت تعذب نفسك. صغر المثال حتى تقدر تشوف كل pointer بعينك.

مثال: لو remove(20) لا يعمل، لا تختبر على 10 عناصر. جرب:

list.addLast(10);
list.addLast(20);
list.addLast(30);
list.remove(20);
list.print();

لو هذا المثال الصغير اشتغل، انتقل لحذف head. بعدها حذف tail. بعدها قيمة غير موجودة. بهذه الطريقة تعرف بالضبط أي حالة ناقصة.

كيف تتعامل مع اللاب بدون توتر

اللاب الأسبوعي في CPCS 204 ليس مكانا تكتشف فيه الموضوع لأول مرة. المفروض تدخل اللاب وعندك فكرة أولية، حتى لو بسيطة. اقرأ عنوان اللاب قبل الحضور: Arrays؟ Linked Lists؟ Recursion؟ Trees؟ بعدها حل مثال واحد صغير في البيت.

في اللاب نفسه، اشتغل بهذا الترتيب:

  1. اقرأ المطلوب كامل قبل ما تفتح ملف Java
  2. اكتب أسماء classes وmethods فقط
  3. شغل compile مبكر
  4. طبق أول method
  5. اختبرها على input صغير
  6. بعدها كمل

لا تنتظر نهاية اللاب عشان تضغط Run لأول مرة. هذا خطأ قاتل. الكود الذي لم يشتغل خلال أول 20 دقيقة غالبا يتحول إلى كرة ثلج من الأخطاء.

لو عندك TA في اللاب، لا تسأله “الكود ما يشتغل”. هذا سؤال واسع. اسأله سؤالا محددا: “في removeLast، هل لازم أوقف عند current.next.next ولا current.next؟” أو “في queue، هل الأفضل أحفظ tail عشان enqueue تصير O(1)؟” السؤال المحدد يعطيك جوابا مفيدا ويحسن صورتك كطالب فاهم وين المشكلة.

خطة 3 أيام قبل التسليم

لو التسليم باقي عليه 3 أيام، لا تقسم وقتك عشوائيا. استخدم خطة بسيطة:

خطة إنهاء واجب CPCS 204

  1. اليوم الأول: اقرأ PDF، استخرج المتطلبات، ارسم البنية، واكتب skeleton لكل class بدون منطق داخلي.

  2. اليوم الثاني: طبق methods الأساسية واحدة واحدة. بعد كل method، اكتب test صغير وشغله. لا تنتقل للجزء التالي إذا الجزء الحالي يعطي ناتج غلط.

  3. اليوم الثالث: نظف الكود، اختبر الحالات الطرفية، راجع اسم الملفات، احذف test prints الزائدة، وارفع نسخة مبكرة على Blackboard.

لو بدأت قبل التسليم بيوم واحد، لا تحاول تكون مثاليا. ركز على المطلوب الأساسي في rubric. حل ناقص لكنه نظيف ومفهوم أفضل من كود طويل لا يشتغل.

⚠️ لا تؤجل الرفع

ارفع نسخة أولية قبل الموعد بساعات، حتى لو كنت ناوي تعدل بعدها. مشاكل Blackboard في آخر ساعة ليست عذرا مضمونا، ورفع نسخة مبكرة يحميك من أسوأ سيناريو.

كيف تطلب مساعدة بدون ما تقع في الغش

في CPCS 204، الحدود مهمة. فهم المفهوم مسموح. مناقشة الفكرة مسموحة. لكن أخذ كود جاهز وتسليمه باسمك مشكلة أكاديمية حقيقية.

المساعدة الصحيحة شكلها كذا:

  • تشرح لك معنى head وtail على رسم
  • تراجع معك لماذا remove يكسر القائمة
  • تساعدك تبني test cases
  • توضح لك لماذا التعقيد صار O(n)

المساعدة الغلط شكلها كذا:

  • شخص يكتب لك الكود كامل
  • تأخذ ملف زميل وتغير أسماء المتغيرات
  • تبحث عن solution جاهز وتنسخه
  • ترفع كودا لا تقدر تشرحه للدكتور أو الـ TA

لو الدكتور سألك: “ليش هذا السطر هنا؟” لازم تجاوب بثقة. هذا هو الاختبار الحقيقي، حتى لو الواجب اشتغل عندك.

كيف تربط CPCS 204 بما بعدها

لا تتعامل مع الواجب كأنه مهمة وتنتهي. كل شيء هنا يرجع لك لاحقا. Linked List تساعدك تفهم queues وgraphs. BST يجهزك للخوارزميات. Big-O يظهر مرة ثانية في CPCS 223 تحليل وتصميم الخوارزميات.

ولو تبغى صورة أوسع عن المادة نفسها، اقرأ شرح CPCS 204 تراكيب البيانات. هذا المقال هنا مركز على الواجبات واللابات، أما شرح المادة يعطيك خريطة المفاهيم كاملة.

آخر شيء مهم: لا تبدأ واجب CPCS 204 من الكود. ابدأ بالرسم. لا تثق في method بدون test. ولا تؤجل السؤال لين ليلة التسليم. المادة صعبة، لكنها عادلة: الطالب الذي يرسم ويفحص ويتدرج غالبا يوصل.

تحتاج خطة واضحة لواجب CPCS 204؟

لو عندك PDF واجب CPCS 204 ومش عارف تبدأ من وين، أرسله لنا ونرتب لك جلسة تفهم فيها المتطلبات، الرسم، test cases، وخطة الحل بدون تسليم كود جاهز باسمك.

أرسل واجبك على واتساب

أسئلة شائعة

كيف أبدأ واجب CPCS 204؟ +

ابدأ بقراءة ملف الواجب مرتين: مرة لفهم القصة العامة، ومرة لاستخراج كل method وكل شرط على التعقيد. بعدها ارسم البنية على ورقة قبل كتابة الكود.

ما أصعب جزء في واجبات CPCS 204؟ +

أصعب جزء غالبا هو الانتقال من استخدام ArrayList الجاهزة إلى بناء Linked List أو Tree بنفسك. الخطأ لا يكون في syntax فقط، بل في فهم تحرك references.

هل أستخدم Java Collections في الواجب؟ +

لا تستخدم Java Collections إلا إذا سمح ملف الواجب صراحة. كثير من واجبات CPCS 204 هدفها أن تبني البنية بنفسك، لا أن تستدعي LinkedList جاهزة.

كيف أتأكد أن حلي جاهز للتسليم؟ +

شغل test cases للحالات العادية والحالات الطرفية: list فاضية، عنصر واحد، حذف أول عنصر، duplicate values، وقيم غير موجودة. لا تعتمد على المثال الموجود في ملف الواجب فقط.

هل تحتاج خصوصي؟