نسخة الأستاذ التعليمية — للشرح الصفي والمذاكرة المنظمة

ادرس مثلما يشرح الأستاذ: هدف، مثال محلول، تمرين، واجب.

هذا الملف مبني كحصة تعليمية: كل وحدة فيها أهداف التعلم، وشرح الأستاذ المبسط، ومثال محلول خطوة بخطوة، وتمرين صفي، وواجب منزلي — ثم دليل الأستاذ بخطة الدروس، وبنك الأسئلة مع نموذج اختبار نهائي بالإجابات. الأقسام التفاعلية (المحاكيات + متتبع التنفيذ سطر بسطر + الاختبار الذاتي) تبقى للتدريب.

8وحدات تعليمية
6أمثلة محلولة + 12 تمريناً وواجباً
5متتبعات تنفيذ سطر بسطر
20سؤالاً: ذاتي + نهائي
ابدأ من هنا

خريطة المذاكرة الذكية

الترتيب المقترح للحفظ السريع:

  1. Array: افهم الفهرس 0 إلى size-1 ثم احفظ Linear و Binary.
  2. Class: افهم أن الكلاس = بيانات + دوال، ثم احفظ نمط البحث عن max.
  3. Stack: احفظ جملة واحدة: آخر داخل أول خارج + Top يبدأ -1.
  4. Queue: احفظ: دخول من rear وخروج من front.
  5. SLL: ارسمها دائماً: head → [info|next] → ... → null.
  6. Recursion: احفظ: كل ريكرجن = شرط توقف + استدعاء أصغر. واربطه بالـ Stack.
Array
Class
Stack
Queue
SLL
Recursion
قاعدة ذهبية لكل سؤال: اسأل نفسك 3 أسئلة: أين المؤشر الآن؟ ماذا يحدث عند أول عنصر؟ ماذا يحدث عند آخر عنصر / القائمة الفارغة؟ 90% من أخطاء اللابات هنا.
Lab 1–2

01 — المصفوفات Array

وصول O(1) بحث O(n) ثنائي O(log n)

الفكرة بكلمة واحدة

علب مرقمة جنب بعض في الذاكرة. اسم المصفوفة = عنوان أول علبة. الفهرس يبدأ 0 وينتهي size-1.

المنطق: لأن العناصر متجاورة، الوصول لـ a[i] سريع جداً (احسب العنوان مباشرة). لكن الإدخال/الحذف من النص مكلف لأنك تُزيح الباقي.

  • Linear Search: امشِ واحداً واحداً وقارن. يعمل حتى لو غير مرتبة.
  • Binary Search: للنصف كل مرة، لكن شرط: مرتبة تصاعدياً.
  • Bubble / Selection Sort: رتّب أولاً ثم ابحث ثنائياً.
فخ الاختبار: إذا قال “اعرض كل المواقع” لا تعمل return من أول تطابق. اطبع كل index يساوي القيمة واستمر.

النمط الذي تحفظه + شرح سطر بسطر

int binarySearch(int a[], int n, int x) { int l = 0, r = n - 1; // حدود البحث while (l <= r) { // ما دام فيه مجال int mid = (l + r) / 2; // النص if (a[mid] == x) return mid; // وجدناه if (a[mid] < x) l = mid + 1; // اذهب يمين else r = mid - 1; // اذهب يسار } return -1; // غير موجود }
  1. حدد يسار ويمين المصفوفة.
  2. احسب النص وقارنه بالهدف.
  3. ضيّق المجال للنصف المناسب.
  4. كرر حتى تجد أو ينتهي المجال.
مثال حفظ: [2,5,8,11,16] ابحث عن 11 → mid=8 ثم l=mid+1 → mid=11 وجدنا في index 3.

محاكي البحث — جرّب بنفسك

النتيجة تظهر هنا مع الخطوات
Lab 3

02 — Class و Object

الفكرة: صندوق يجمع البيانات + الدوال

تخيل استمارة سيارة: name, model, price هي البيانات، و set, print, search هي الدوال التي تتعامل معها. الـ Object هو نسخة حقيقية من الاستمارة (مثلاً سيارة كامري).
class Car { string name; int model; float price; public: void set(string n, int m, float p); void print(); bool search(string key); };
  1. private (افتراضي): البيانات مخفية للحماية.
  2. public: الدوال بوابة التعامل.
  3. Object: Car c[10]; يعني 10 سيارات حقيقية.
// نمط: إيجاد أحدث سيارة (max) int best = 0; for (int i = 1; i < n; i++) if (c[i].getModel() > c[best].getModel()) best = i;
سؤال متوقع: أحدث سيارة / أرخص سيارة / بحث باسم. كلها نفس النمط: ابدأ بالأول ثم قارن الباقي واحفظ index الفائز وليس القيمة فقط.
Lab 4–5

03 — Stack (المكدس)

LIFO Push/Pop O(1)

الفكرة: كومة صحون

تضع الصحن فوق (Push) وتأخذ من فوق فقط (Pop). آخر داخل = أول خارج LIFO. المؤشر stackTop يبدأ -1 (فارغ).
  • فارغ: stackTop == -1
  • ممتلئ: stackTop == size - 1 (عندك size=10)
  • Push: زد المؤشر ثم خزّن s[++Top]=x
  • Pop: اقرأ ثم أنقص x=s[Top--]
  • Top/Peek: يعرض بدون حذف.
خطأ شائع: Pop من stack فارغ، أو Push في stack ممتلئ. افحص الشرط دائماً قبل العملية!

أشهر تطبيق: فحص الأقواس

ضع كل قوس فتح ( { [ في Stack. عند قوس إغلاق قارنه مع Top ثم Pop. في النهاية يجب أن يكون Stack فارغاً.

bool match(char open, char close){ if (open=='(' && close==')') return true; if (open=='{' && close=='}') return true; if (open=='[' && close==']') return true; return false; } // "({[]})" -> صحيحة | "({[})" -> خاطئة
لماذا Stack؟ لأن آخر قوس فُتح هو أول قوس يجب أن يُغلق — نفس منطق LIFO تماماً.

محاكي Stack المرئي

Stack فارغ — Top = -1
Lab 6–7

04 — Queue (الطابور)

FIFO Enqueue/Dequeue O(1)

الفكرة: طابور مخبز

أول واحد يدخل هو أول واحد يُخدم. الدخول من rear والخروج من front. البداية: front = rear = -1.
  1. Enqueue (إدخال): إذا فارغ اجعل front=0، ثم rear++ وخزّن.
  2. Dequeue (حذف): خذ قيمة front ثم front++. إذا كان آخر عنصر أعد المؤشرين إلى -1.
  3. Peek: اعرض front بدون حذف.
مشكلة الطابور الخطي: بعد حذف من الأمام تبقى خانات فارغة لا تُستخدم. الحل: Circular Queue.

Circular Queue — الالتفاف الذكي

بدل ما تمشي للأمام فقط، التف حول المصفوفة باستخدام باقي القسمة:

rear = (rear + 1) % size; // التفاف front = (front + 1) % size; // ممتلئ: (rear + 1) % size == front // فارغ: front == -1
سؤال PDF مهم: اعكس Queue باستخدام Stack (أخرج الكل إلى Stack ثم أدخلهم مجدداً)، وابحث عن عنصر داخل Circular Queue بالمرور من front حتى rear مع الالتفاف.

محاكي Queue

Queue فارغة — front = rear = -1
Lab 8–9

05 — Singly Linked List

ديناميكية بحث O(n)

الفكرة: قطار بعربات مربوطة

كل عربة (Node) تحمل info + خطاف next يربط بالعربة التالية. head أول القطار و tail آخره وآخر next = null.
head [5|•]
[8|•]
tail [3|null]
  • إضافة للرأس: الجديدة تشير إلى head ثم head = الجديدة. O(1)
  • إضافة للذيل: tail→next = الجديدة ثم tail = الجديدة. O(1)
  • حذف/بحث: امشِ من head حتى تجد. O(n)
انتبه: عند حذف عقدة خزّن p→next قبل الحذف حتى لا تفقد مسار القائمة. وتعامل مع حالتين: القائمة الفارغة، والعقدة الوحيدة (head==tail).

الأسئلة الموجودة في ملفاتك — كيف تحلها؟

  • حذف كل الأصفار: امشِ واحذف كل node قيمتها 0 مع تحديث الروابط.
  • عدّ + أكبر قيمة: عداد و max يبدآن من head ثم traversal.
  • زوجي/فردي: قائمتان جديدتان، وزّع حسب %2.
  • ترتيب 10 عقد: bubble sort بتبديل info وليس العقد.
  • جمع قائمتين: امشِ بالتوازي واجمع عنصراً بعنصر في قائمة ثالثة.
struct Node{ int info; Node* next; }; // إضافة للرأس: Node* p = new Node(x); p->next = head; head = p; if(tail==nullptr) tail = p;

محاكي Linked List

head → (فارغة) → null
⭐ جديد — Lab 10

06 — Recursion (الاستدعاء الذاتي)

مهم للاختبار

الفكرة بكلمة: مرآة أمام مرآة

دالة تنادي نفسها لحل نسخة أصغر من نفس المشكلة. مثل أن تقول: “5! = 5 × 4!” ثم “4! = 4 × 3!” ... حتى تصل لحالة تعرفها.

كل ريكرجن صحيح = عنصران إجباريان:

  1. Base Case (شرط التوقف): أبسط حالة تُحل مباشرة. مثال: if(n<=1) return 1; بدونه → Stack Overflow.
  2. Recursive Case (خطوة التصغير): نادِ نفسك بمدخل أصغر. مثال: return n * fact(n-1);
أخطر خطأ: نسيان Base Case أو عدم التصغير → استدعاءات لا نهائية → stack overflow (البرنامج ينهار).

المنطق: الريكرجن = Stack مخفي!

كل استدعاء يُدفع (Push) في Call Stack مع متغيراته، وعند الوصول للـ Base Case تبدأ العودة (Pop) مع الحلول.

fact(3)
fact(2)
fact(1) توقف
رجوع 1←2←6
int fact(int n){ if(n <= 1) return 1; // Base return n * fact(n - 1); // Recursive } // fact(4) = 4*fact(3) = 4*3*fact(2) // = 4*3*2*fact(1) = 4*3*2*1 = 24
اربطها بما ذاكرته: الـ Call Stack هو Stack حقيقي (LIFO) — آخر دالة دخلت هي أول دالة تخرج. لهذا فهمك للـ Stack يساعدك هنا.

أمثلة تحفظها للاختبار

// مجموع 1..n int sum(int n){ if(n <= 0) return 0; return n + sum(n-1); } // فيبوناتشي int fib(int n){ if(n <= 1) return n; return fib(n-1) + fib(n-2); } // طباعة Linked List بالعكس (ريكرجن!) void printRev(Node* h){ if(h==nullptr) return; // Base printRev(h->next); // انزل للآخر أولا cout << h->info; // اطبع وأنت راجع }
فيبوناتشي بطيء بالريكرجن لأنه يكرر نفس الحسابات. في الاختبار اذكر ذلك: تعقيده O(2^n). الحل: Loop أو Memoization.

Loop مقابل Recursion — متى تستخدم ماذا؟

وجهLoopRecursion
الذاكرةقليلةأكثر (كل استدعاء إطار)
الوضوحأفضل للعد البسيطأجمل للشجر والقوائم والتقسيم
الخطرحلقة لا نهائيةstack overflow
مثالبحث خطيفاكتوريال، عكس قائمة، برج هانوي
قاعدة الاختبار: إذا رأيت “اكتب دالة تستدعي نفسها” أو “بدون حلقات” → ريكرجن. اذكر الـ Base Case أولاً ثم اكتب الاستدعاء.

محاكي الريكرجن — شاهد الـ Call Stack يمتلئ ويفرغ

أدخل n واضغط الزر لعرض شجرة الاستدعاءات
مراجعة أخيرة

07 — جدول المقارنة السريع (احفظه ليلة الاختبار)

الهيكلالفكرةإدخالإخراجالمؤشراتفارغ؟ممتلئ؟
StackLIFOPush فوقPop من فوقTop=-1Top==-1Top==size-1
Queue خطيةFIFOrearfrontfront=rear=-1front==-1rear==size-1
CircularFIFO ملتف(rear+1)%size(front+1)%sizefront,rearfront==-1(rear+1)%size==front
SLLعقد مربوطةرأس/ذيل O(1)بحث O(n)head,tailhead==nullلا تمتلئ (ديناميكية)
Recursionدالة تنادي نفسهامسألة أصغررجوع + حلCall StackBase CaseStack Overflow
كيف تحفظ الجدول؟ جملة واحدة لكل سطر: Stack فوق-فوق، Queue خلف-أمام، Circular باقي القسمة، SLL خطافات، Recursion توقف+تصغير.
🔍 الأهم — تتبع حرف بحرف

08 — متتبع تنفيذ الكود: وين يمشي ووين يوصل؟

الفكرة: لا تقرأ الكود كله مرة واحدة. امشِ مع السهم سطر → حالة الذاكرة → شرح بالحرف. كل متتبع تحت يعرض: 1) السطر المنفذ مضيئاً، 2) قيم المتغيرات في جدول المراقبة، 3) شكل الذاكرة (خلايا/إطارات)، 4) شرحاً عربياً حرفاً بحرف: ماذا قرأ؟ ماذا قارن؟ وين راح بعدها؟
طريقة الاستخدام: اضغط ابدأ التتبع ثم التالي ← خطوة خطوة. زر تشغيل تلقائي يمشي وحده. لاحظ العمود الأيسر (الكود) والعمود الأيمن (الذاكرة) معاً.

تتبع 1 — Binary Search: وين يروح l و r و mid؟

المثال: مصفوفة مرتبة وابحث عن الهدف. لاحظ كيف ينكمش المجال كل خطوة.

الذاكرة (المصفوفة):
lrmida[mid]المقارنة
-----
اضغط «ابدأ التتبع» لترى الكود يمشي سطراً بسطر.
خطوة 0 من 0

تتبع 2 — Stack Push/Pop: وين يتحرك Top؟

السيناريو: Push 10 ثم Push 20 ثم Pop. راقب Top يزيد قبل التخزين وينقص بعد القراءة.

الذاكرة (Stack من الأسفل للأعلى):
Topالحالةآخر عملية
-1فارغ-
اضغط «ابدأ التتبع».
خطوة 0 من 0

تتبع 3 — Queue: الدخول من rear والخروج من front

السيناريو: Enqueue A,B,C ثم Dequeue مرة. لاحظ front لا يرجع للخلف في الطابور الخطي.

الذاكرة (الطابور):
frontrearالقيمة
-1-1-
اضغط «ابدأ التتبع».
خطوة 0 من 0

تتبع 4 — Linked List: المؤشر p يمشي عقدة عقدة (إيجاد الأكبر)

القائمة: head → 5 → 0 → 8 → 3 → null. الهدف: إيجاد أكبر قيمة. راقب p و max.

الذاكرة (العقد):
p تشير إلىmax الآنالمقارنة
---
اضغط «ابدأ التتبع».
خطوة 0 من 0

تتبع 5 — Recursion: شاهد Call Stack يُبنى ثم يُهدم (fact 4)

الدالة تنادي نفسها بقيمة أصغر حتى Base ثم تعود بالضرب. كل سطر مضيء = إطار جديد يُدفع أو يُزال.

Call Stack (آخر داخل أول خارج):
العمقالحالة
0لم يبدأ
اضغط «ابدأ التتبع». أدخل n من 2 إلى 6.
خطوة 0 من 0
👨‍🏫 للأستاذ والطالب المنظم

09 — دليل الأستاذ: الأهداف وخطة الدروس

كيف تستخدم هذا الملف كأستاذ؟ (5 خطوات للحصة)

  1. ابدأ بالهدف: اقرأ أهداف التعلم في الجدول بصوت عالٍ — الطالب يعرف وين رايح قبل ما يمشي.
  2. اشرح الفكرة بمثال من الحياة: صحون (Stack)، طابور مخبز (Queue)، قطار (SLL)، مرآة أمام مرآة (Recursion).
  3. حل المثال المحلول على السبورة: امشِ سطراً بسطر مع جدول المراقبة — ثم افتح المتتبع في القسم 08 وخل الطلاب يضغطون «التالي» بأنفسهم.
  4. نشاط صفي 5 دقائق: تمرين واحد من تمارين كل وحدة — يحله الطالب ثم تقارن إجابته بالنموذج.
  5. واجب + اختبار: واجب منزلي واحد، وفي الحصة القادمة سؤال من بنك الأسئلة.
قاعدة التصحيح: نصف الدرجة على الفكرة (المؤشر/الشرط) ونصفها على التفاصيل (القيم النهائية). من يكتب شرط الفحص قبل العملية (فارغ/ممتلئ/null/Base) يأخذ درجة المنهجية حتى لو أخطأ برقم.

خطة الدروس والأهداف (6 حصص)

الحصةالوحدةهدف التعلم (بعد الحصة الطالب قادر على...)المفرداتالتقييم
1Arrayكتابة Linear و Binary Search من الذاكرة وشرط كل منهماindex, size-1, مرتبةتمرين أ-1 + واجب أ
2Classتعريف class مع private/public وإيجاد max بنمط الفائزobject, set/get, maxتمرين ج-1 + واجب ج
3Stackتنفيذ Push/Pop/Top مع شرطي الفارغ والممتلئ + فحص الأقواسLIFO, Top=-1, size-1تمرين س-1 + واجب س
4Queueالتمييز بين الخطية والدائرية وكتابة شرط الامتلاء الملتفFIFO, front/rear, %sizeتمرين ق-1 + واجب ق
5SLL + Recursionرسم العقد وتتبع p/next + كتابة دالة recursive بعنصريهاhead/tail/null, Baseتمرين ل-1 + ر-1
6مراجعةحل نموذج الاختبار النهائي في زمن محدد وتصحيح ذاتيكل المفرداتنموذج القسم 10

الأمثلة المحلولة (نموذج إجابة الأستاذ)

مثال أ (Array): مصفوفة [2,5,8,11,16] ابحث عن 11 ثنائياً.

الحل النموذجي: l=0,r=4 → mid=2 (8<11) → l=3 → mid=(3+4)/2=3 → a[3]=11 == الهدف → return 3. عدد المقارنات 2 فقط مقابل 4 في الخطي. المنهجية: اكتب l,r,mid في جدول قبل كل مقارنة.

مثال س (Stack): نفذ Push 10 ثم Push 20 ثم Pop.

الحل: Top=-1 → Push 10: Top=0,s[0]=10 → Push 20: Top=1,s[1]=20 → Pop: x=20,Top=0. المتبقي [10] والقمة 10. من ينسى Top++ قبل التخزين يخسر المنهجية.

مثال ر (Recursion): احسب fact(4).

الحل: fact(4)=4×fact(3)=4×3×fact(2)=4×3×2×fact(1)=4×3×2×1=24. Base: fact(1)=1. العمق 4 إطارات ثم عودة عكسية.

التمارين الصفية + الواجبات (حلولها في المتتبع)

  • تمرين أ-1 (صفي): رتب [16,2,11,5] تصاعدياً بـ Bubble ثم ابحث عن 5 ثنائياً. الحل: [2,5,11,16] ثم index 1
  • واجب أ: اكتب Linear Search يعرض كل مواقع القيمة 0 في مصفوفة. تلميح: لا return مبكر
  • تمرين س-1 (صفي): هل "([)]" صحيحة؟ ولماذا؟ الحل: خاطئة — Top عند ] هو [ وليس (
  • واجب س: اعكس Queue باستخدام Stack (3 خطوات). تلميح: Dequeue→Push ثم Pop→Enqueue
  • تمرين ق-1 (صفي): طابور دائري size=5 فيه front=3,rear=1 — هل هو ممتلئ؟ الحل: (1+1)%5=2 ≠ 3 → لا
  • واجب ق: ابحث عن عنصر في Circular مع الالتفاف من front حتى rear.
  • تمرين ل-1 (صفي): قائمة 5→0→8→3 أوجد الأكبر بتتبع p. الحل: max=8
  • واجب ل: احذف كل الأصفار مع حفظ next قبل الحذف.
  • تمرين ر-1 (صفي): اكتب sum(n) recursive بعنصريها. الحل: base n<=0→0، وإلا n+sum(n-1)
  • واجب ر: اكتب printRev للـ SLL (انزل ثم اطبع وأنت راجع).
أخطاء شائعة يرصدها الأستاذ: فهرس يبدأ من 1 بدل 0 / نسيان front=0 عند أول إدخال / حذف عقدة دون حفظ next / ريكرجن بلا Base / مقارنة a[mid] بالفهرس بدل القيمة.
📝 بنك الأسئلة + نموذج نهائي

10 — الاختبار النهائي (نموذج الأستاذ بالإجابات)

الزمن المقترح: 45 دقيقة

بنك الأسئلة المتوقعة من ملفات الـ PDF (/recap سريع)

#السؤالالفكرة المختبرةنموذج الجواب المختصر
1اعرض كل مواقع القيمة xLinear بلا return مبكرحلقة تطبع كل i حيث a[i]==x
2ابحث ثنائياً في مرتبةl/r/midضيّق النصف كل مرة، -1 إن غاب
3أحدث/أرخص سيارةنمط maxbest=0 ثم قارن واحفظ index
4نفذ Push/Pop ثم اعرض TopTop±1Push: ++ثم خزّن / Pop: اقرأ ثم --
5افحص "( { [ ] } )"Stack والأقواسادفع الفتح، طابق واسحب، فارغ=صحيحة
6اعكس Queue بـ StackFIFO→LIFO→FIFODequeue→Push الكل ثم Pop→Enqueue
7هل Circular ممتلئ؟(rear+1)%size==frontعوّض واحكم
8احذف أصفار SLL / جد الأكبر / وزع زوجي-فرديtraversal + روابطامشِ بـ p، احفظ next قبل الحذف
9اكتب fact/sum/fib recursiveBase + تصغيرشرط التوقف أولاً ثم الاستدعاء الأصغر
10اطبع SLL بالعكس دون حلقةريكرجن + روابطprintRev(next) ثم اطبع info

نموذج اختبار نهائي — أجب ثم اضغط لإظهار الحل

س1 (Array — 3 درجات): مصفوفة [4,7,10,13] مرتبة. تتبع Binary Search عن 13 واذكر كل mid.

س2 (Stack — 3 درجات): Stack فارغ size=5. نفذ: Push 3, Push 9, Pop, Push 7. ما المحتوى وTop؟

س3 (Queue — 2 درجة): Enqueue X,Y ثم Dequeue مرة. من يخرج؟ وما front؟

س4 (SLL + Recursion — 2 درجات): قائمة 2→9→4. أوجد الأكبر بحلقة، ثم اكتب دالة recursive تطبعها بالعكس.

قبل الاختبار

اختبر نفسك — 8 أسئلة

1) ما ترتيب Stack؟

2) Binary Search يحتاج إلى:

3) أين تتم الإضافة في Queue؟

4) ماذا تحتوي Node في SLL؟

5) ما عنصرا أي دالة Recursive صحيحة؟

6) ماذا يحدث لو نسيت Base Case؟

7) كيف تعرف أن Circular Queue ممتلئة؟

8) طباعة Linked List بالعكس أنسب بـ: