Skip to content

مدخل إلى التفكير الخوارزمي

مقدمة

كيف تحل المشكلات بكفاءة؟ ربما واجهت هذا الحيرة: نفس المشكلة، كود شخص ما ينفذ في ثوانٍ، بينما كود شخص آخر يستمر في الدوران لدقائق. الفرق غالباً يكمن في الخوارزمية. يأخذك هذا الفصل لفهم المفاهيم الأساسية للتفكير الخوارزمي.

ماذا ستتعلم في هذه المقالة؟

بعد إكمال هذا الفصل، ستكتسب:

  • قدرة على تفكيك المشكلات: أمام المشكلات المعقدة، يمكنك التفكير في استراتيجيات مثل فرّق تسد، والتكرار العودي، بدلاً من كتابة الكود مباشرة
  • قدرة على تقييم الكفاءة: استخدام تدوين O الكبيرة لتحديد أي الحلين أكثر كفاءة، بدلاً من التخمين بالحدس
  • تفكير التعقيد: تقدير حجم البيانات ومتطلبات الوقت قبل كتابة الكود، واختيار المستوى المناسب من الخوارزمية
  • أساس للتعلم المستقبلي: وضع الأساس لهياكل البيانات المتقدمة، والأنظمة الموزعة، والتعلم الآلي
الفصلالمحتوىالمفهوم الأساسي
الفصل 1البحث الثنائيفرّق تسد، O(log n)
الفصل 2خوارزميات الترتيبالفقاعات، الترتيب السريع، ترتيب الدمج
الفصل 3تحليل التعقيدالتعقيد الزمني، التعقيد المكاني

0. نظرة عامة: ما هي الخوارزمية؟

تخيل أنك تبحث عن كلمة في القاموس:

  • الطريقة الأولى: البدء من الصفحة الأولى وتقليب الصفحات واحدة تلو الأخرى (البحث الخطي)
  • الطريقة الثانية: التحديد بواسطة الحرف الأول، ثم البحث الثنائي (البحث الثنائي)

كلتا الطريقتين تجدان الكلمة، لكن الكفاءة مختلفة تماماً. الخوارزمية هي طريقة لحل المشكلات.

Algorithmic Thinking: Ways to Solve ProblemsDifferent strategies fit different kinds of problems
Binary searchEliminate half each time, O(log n)
Time Complexity Quick Reference
O(1)ConstantBest, such as array access
O(log n)LogarithmicVery good, such as binary search
O(n)LinearCommon, such as traversal
O(n log n)LinearithmicAcceptable, such as quicksort
O(n²)QuadraticSlow, such as bubble sort
O(2ⁿ)ExponentialVery slow, such as brute-force recursion
Core idea:Algorithms are methods for solving problems. A good algorithm can improve efficiency by orders of magnitude. Understanding algorithmic thinking matters more than memorizing individual algorithms.

المؤشرات الأساسية للخوارزميات:

المؤشرالمعنىلماذا هو مهم
التعقيد الزمنياتجاه وقت التشغيل مع زيادة البياناتالتنبؤ بالأداء مع البيانات واسعة النطاق
التعقيد المكانياتجاه استهلاك الذاكرة مع زيادة البياناتتقييم استهلاك الذاكرة
الصحةهل تعطي دائماً نتائج صحيحةالمتطلب الأساسي لأي خوارزمية

قراءة الجدول سطراً بسطر

التعقيد الزمني: يُوصف بتدوين O الكبيرة. O(n) يعني أن البيانات تتضاعف، والوقت يتضاعف؛ O(n^2) يعني أن البيانات تتضاعف، والوقت يصبح 4 أضعاف.

التعقيد المكاني: يستخدم أيضاً تدوين O الكبيرة. بعض الخوارزميات تبدل المساحة بالوقت (مثل جداول التجزئة)، وبعضها يبدل الوقت بالمساحة (مثل خوارزميات الضغط).

الصحة: يجب أن تعطي الخوارزمية نتائج صحيحة لجميع المدخلات الممكنة. الشروط الحدية (مدخل فارغ، مدخل ضخم) هي الأكثر عرضة للأخطاء.


1. البحث الثنائي: استبعاد النصف في كل مرة

1.1 مبدأ البحث الثنائي

كيف يعمل البحث الثنائي؟

المتطلب الأساسي: يجب أن تكون البيانات مرتبة

العملية:

  1. العثور على العنصر الأوسط
  2. إذا كان العنصر الأوسط يساوي الهدف، تم العثور عليه!
  3. إذا كان الهدف أصغر من العنصر الأوسط، استمر في النصف الأيسر
  4. إذا كان الهدف أكبر من العنصر الأوسط، استمر في النصف الأيمن
  5. استبعاد النصف في كل مرة، حتى يتم العثور عليه أو التأكد من عدم وجوده

التعقيد الزمني: O(log n)

تشبيه من الحياة: لعبة تخمين الأرقام. فكر برقم من 1 إلى 100، في كل مرة تخمن الرقم الأوسط، أقول لك أكبر أم أصغر. بحد أقصى 7 محاولات يمكنك التخمين correctly (لأن 2^7 = 128 > 100).

جرّب بنفسك أدناه: يوضح هذا العرض كيف يعمل البحث الثنائي، يمكنك اختيار البحث المتسلسل أو الثنائي للمقارنة:

Search AlgorithmsHow to find a target in data
Linear search: check items one by one
3
7
2
9
5
1
8
4
6
10
Target number:
Time complexity: O(n)
Use case: unordered arrays
Performance Comparison
Data sizeLinear searchBinary search
10At most 10 stepsAt most 4 steps
100At most 100 stepsAt most 7 steps
1000At most 1000 stepsAt most 10 steps
10000At most 10000 stepsAt most 14 steps

1.2 لماذا البحث الثنائي سريع جداً؟

كمية البياناتالبحث الخطيالبحث الثنائي
100100 مرة7 مرات
1,0001,000 مرة10 مرات
1,000,0001,000,000 مرة20 مرة
1,000,000,0001,000,000,000 مرة30 مرة

قراءة الجدول سطراً بسطر

العمود الأول (كمية البيانات): كم عدد البيانات التي يتم البحث عنها. يمكن ملاحظة أن كمية البيانات تزداد من 100 إلى مليار (زيادة بمقدار 10 مليون مرة!)

العمود الثاني (البحث الخطي): الطريقة "الأغبى"، البدء من الأولى والبحث واحدة تلو الأخرى. عدد عمليات البحث يساوي كمية البيانات؛ كلما زادت البيانات، زادت عمليات البحث.

العمود الثالث (البحث الثنائي): الطريقة الذكية، استبعاد النصف في كل مرة. عدد عمليات البحث مرتبط فقط بلوغاريتم كمية البيانات؛ حتى مع مليار بيانات يحتاج فقط إلى 30 مرة!

خلاصة المقارنة: عندما تصل كمية البيانات إلى مليون، يحتاج البحث الخطي إلى مليون مرة، بينما يحتاج البحث الثنائي إلى 20 مرة فقط -- فرق يبلغ 50,000 مرة!

قوة النمو اللوغاريتمي

التعقيد الزمني للبحث الثنائي هو O(log n)، مما يعني:

  • مليار بيانات، بحد أقصى 30 عملية بحث
  • تريليون بيانات، بحد أقصى 40 عملية بحث

هذه هي قوة النمو اللوغاريتمي -- البيانات تزداد 1000 مرة، وعمليات البحث تزداد فقط 10.


2. الترتيب: تحويل العشوائي إلى منظم

2.1 خوارزميات الترتيب الشائعة

الخوارزميةالتعقيد الزمنيالخصائصسيناريو الاستخدام
ترتيب الفقاعاتO(n^2)بسيط ولكنه بطيءالتعليم، البيانات الصغيرة
ترتيب الاختيارO(n^2)بسيط ولكنه بطيءالبيانات الصغيرة
ترتيب الإدراجO(n^2)سريع مع البيانات شبه المرتبةالبيانات الصغيرة، شبه المرتبة
الترتيب السريعO(n log n)الأسرع عملياًالترتيب العام
ترتيب الدمجO(n log n)ترتيب مستقرالسيناريوهات التي تتطلب الاستقرار
ترتيب الكومةO(n log n)ترتيب في الموقعالسيناريوهات ذات الذاكرة المحدودة

قراءة الجدول سطراً بسطر

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

ترتيب الاختيار: في كل مرة يتم اختيار الأصغر ووضعه في المقدمة. بسيط أيضاً، ولكن بغض النظر عن ترتيب البيانات، يقوم دائماً بنفس عدد المقارنات.

ترتيب الإدراج: مثل تنظيم الأوراق في يدك عند لعب الورق. يتم إدراج كل عنصر في الجزء المرتب بالفعل. فعال جداً مع البيانات شبه المرتبة.

الترتيب السريع: الأكثر استخداماً في التطوير العملي. الأسرع في المتوسط، ولكن في أسوأ الحالات (البيانات مرتبة بالفعل) يتدهور إلى O(n^2).

ترتيب الدمج: يتبنى فكرة "فرّق تسد"، دائماً O(n log n)، ولكنه يتطلب مساحة إضافية. مناسب للسيناريوهات التي تحتاج ترتيباً مستقراً.

ترتيب الكومة: يستخدم بنية بيانات الكومة للترتيب في الموقع (بدون مساحة إضافية)، ولكنه عملياً يكون عادةً أبطأ من الترتيب السريع.

2.2 لماذا الترتيب السريع "سريع"؟

مبدأ الترتيب السريع

الفكرة الأساسية: فرّق تسد

  1. اختيار عنصر "محوري"
  2. وضع الأصغر من المحوري على اليسار، والأكبر على اليمين
  3. ترتيب كلا الجانبين بشكل عودي
  4. دمج النتائج

لماذا هو سريع؟

  • بعد كل تقسيم، يكون العنصر المحوري في موقعه النهائي
  • في المتوسط، كل تقسيم يستبعد حوالي نصف العناصر
  • التعقيد الزمني O(n log n)

تشبيه من الحياة: ترتيب رف الكتب. تسحب كتاباً واحداً، تضع الأرفع على اليمين والأخف على اليسار. ثم تكرر هذه العملية مع كل مجموعة.

جرّب بنفسك أدناه: يوضح هذا العرض تصور خوارزميات الترتيب، يمكنك إنشاء مصفوفة ومشاهدة المقارنة بين ترتيب الفقاعات والترتيب السريع:

Sorting AlgorithmsPut data into order
50
30
70
40
90
20
60
80
10
55
Choose a sorting algorithm
Select a sorting algorithm to start the demo
Time complexity:
Algorithm Comparison
AlgorithmAverage timeWorst timeSpaceStable
Bubble sortO(n²)O(n²)O(1)
Quick sortO(n log n)O(n²)O(log n)
Merge sortO(n log n)O(n log n)O(n)
Insertion sortO(n²)O(n²)O(1)

3. التكرار العودي: استدعاء الذات

3.1 جوهر التكرار العودي

ما هو التكرار العودي؟

التكرار العودي هو تقنية برمجة حيث تستدعي الدالة نفسها.

عنصران أساسيان:

  1. الحالة الأساسية: متى يتوقف التكرار العودي؟
  2. الخطوة العودية: كيف يتم تفكيك المشكلة إلى مشكلات فرعية أصغر؟

مثال كلاسيكي: المضروب

js
function factorial(n) {
  if (n <= 1) return 1        // الحالة الأساسية
  return n * factorial(n - 1) // الخطوة العودية
}

تشبيه من الحياة: دمى ماتريوشكا الروسية. تفتح دمية فتجد دمية أصغر بداخلها، حتى أصغر دمية لا يمكن فتحها.

3.2 التكرار العودي مقابل التكرار

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

قراءة الجدول سطراً بسطر

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

استهلاك الذاكرة: التكرار العودي يستخدم "مكدس الاستدعاءات" لحفظ معلومات كل مستوى، مثل تكديس الصحون؛ كل مستوى عودي يضيف صحنًا. الحلقات لا تحتاج هذه التكلفة.

الأداء: كل استدعاء دالة له تكلفة (تمرير المعلمات، عمليات المكدس، إلخ)، لذلك التكرار العودي عادةً أبطأ من الحلقات.

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

فخ التكرار العودي

تجاوز المكدس: التكرار العودي عميق جداً، مما يستنزف مساحة مكدس الاستدعاءات.

الحلول:

  • التحول إلى التكرار
  • استخدام تحسين التكرار الذيل (بعض اللغات تدعم ذلك)
  • تقييد عمق التكرار العودي

جرّب بنفسك أدناه: يوضح هذا العرض عملية الاستدعاءات العودية، شاهد كيف تستدعي الدالة نفسها:

Recursive Thinking: A Function Calls ItselfBreak a large problem into smaller problems of the same kind
🪆
Nested dolls
Open a large doll and there is a smaller doll inside
Open that one and there is an even smaller one, until the smallest case
That is recursion.
Recursive examples
Factorial: n! = n × (n-1)!
5! = 5 × 4!
4! = 4 × 3!
3! = 3 × 2!
2! = 2 × 1!
1! = 1 (base case)
↑ return 1
↑ return 2 × 1 = 2
↑ return 3 × 2 = 6
↑ return 4 × 6 = 24
↑ return 5 × 24 = 120
Three Elements of Recursion
1
Base case
When should recursion stop? There must be a termination condition.
Example: 1! = 1
2
Recursive call
How does the problem get smaller? Call the same function on a smaller case.
Example: turn n! into (n-1)!
3
Return result
How does the current problem use the result of the subproblem?
Example: the result of n × (n-1)!
✓ Pros
  • Concise code
  • Naturally expresses recursive structures
  • Good for tree and graph traversal
✗ Cons
  • May repeat work
  • Uses stack space
  • Can be harder to debug

4. الخوارزمية الجشعة: اختيار الأمثل في كل خطوة

4.1 فكرة الخوارزمية الجشعة

ما هي الخوارزمية الجشعة؟

الخوارزمية الجشعة تختار في كل خطوة الخيار الذي يبدو أفضل في تلك اللحظة، على أمل الوصول إلى الحل الأمثل الشامل.

شروط التطبيق:

  1. خاصية الاختيار الجشع: الأمثل محلياً يمكن أن يؤدي إلى الأمثل شاملاً
  2. البنية التحتية المثلى: الحل الأمثل للمشكلة يحتوي على الحلول المثلى للمشكلات الفرعية

مثال كلاسيكي: الباقي من العملات

  • الهدف: استخدام أقل عدد من العملات لتشكيل المبلغ المحدد
  • الاستراتيجية الجشعة: في كل مرة اختيار العملة ذات القيمة الأكبر
  • النتيجة: 67 = 50 + 10 + 5 + 1 + 1 (5 عملات)

تشبيه من الحياة: عند تسلق جبل، في كل مرة تختار المسار الأكثر انحداراً للصعود. على الرغم من أنك قد لا تصل إلى القمة الأعلى، عادةً تصل إلى موقع جيد.

4.2 قيود الخوارزمية الجشعة

الخوارزمية الجشعة لا تحصل دائماً على الحل الأمثل

مثال مضاد: باقي العملات

إذا كانت الفئات [1, 3, 4] وتريد تشكيل 6:

  • الجشع: 4 + 1 + 1 = 3 عملات
  • الأمثل: 3 + 3 = 2 عملة

الخوارزمية الجشعة فشلت هنا!

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

جرّب بنفسك أدناه: يوضح هذا العرض التأثير الفعلي للخوارزمية الجشعة، يمكنك تجربة مجموعات مختلفة من العملات ومراقبة أداء الاستراتيجية الجشعة:

Greedy Algorithms: Choose the Best Current MoveLocal optimum → global optimum?
A greedy algorithm chooses the best option available at each step
It hopes a series of local choices reaches a global optimum
Classic problems
Coin Change Problem
Change needed: 37
20
× 1 = 20
10
× 1 = 10
5
× 1 = 5
1
× 2 = 2
Needs 5 coins total
✓ Greedy strategy: choose the largest coin each time
✓ Works for currencies such as RMB and USD
Greedy vs Dynamic Programming
FeatureGreedy algorithmDynamic programming
Decision styleChoose the current best each stepConsider all possibilities and choose the best
OptimalityMay not be globally optimalGuarantees a global optimum
Time complexityO(n) or O(n log n)O(n²) or higher
Best fitLocal optimum → global optimumOverlapping subproblems
✓ Pros
  • Simple to implement
  • Efficient
  • Low space complexity
✗ Cons
  • Does not always guarantee a global optimum
  • Limited applicability
  • Requires an optimality proof

5. نماذج تصميم الخوارزميات

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

قراءة الجدول سطراً بسطر

فرّق تسد: تقسيم المشكلة الكبيرة إلى مشكلات صغيرة، وحل كل منها بشكل منفصل ثم الدمج. مثل ترتيب المنزل: تقسم أولاً إلى غرفة المعيشة، غرفة النوم، المطبخ، تنظف كل منها وفي النهاية كل شيء مرتب.

الجشع: في كل مرة تختار الأفضل حالياً، دون النظر في العواقب طويلة المدى. مثل الأكل باختيار طبقك المفضل أولاً؛ قد لا يكون الطريقة المثلى للأكل، لكنه سريع.

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

التراجع: إذا لم تنجح، عد وأعد المحاولة. مثل السير في متاهة: إذا هذا الطريق لا يعمل، عد إلى التقاطع السابق وجرب طريقاً آخر.

جرّب بنفسك أدناه: يوضح هذا العرض خصائص وسيناريوهات تطبيق نماذج تصميم الخوارزميات المختلفة:

Algorithm Design ParadigmsCommon patterns for solving problems
Algorithm design paradigms are general strategies for solving problems. Learning them helps you find solution ideas quickly.
✂️
Divide and conquer
Divide, solve, combine
📊
Dynamic programming
Store results to avoid repetition
🎯
Greedy
Local optimum
🔙
Backtracking
Try and retreat
✂️Divide and conquer
Core idea
Split a large problem into smaller independent problems, solve them recursively, then combine the results.
Use cases
Array sortingMatrix multiplicationLarge integer arithmetic
Classic problems
📝
Merge sort
📝
Quick sort
📝
Binary search
📝
Strassen matrix multiplication
Time complexity
O(n log n)
Often much faster than brute force
Paradigm Comparison
ParadigmCore strategyOptimalityUse case
✂️ Divide and conquerSplit → recurse → combineGuarantees optimumProblems that split independently
📊 Dynamic programmingStore subproblem answersGuarantees optimumOverlapping subproblems
🎯 GreedyChoose the best each timeNot always optimalLocal optimum → global optimum
🔙 BacktrackingDepth-first searchGuarantees optimumSmall search spaces that need enumeration
How to choose the right paradigm?
1
Analyze problem features
Are there overlapping subproblems? Is there optimal substructure?
2
Decide whether an optimum is required
Greedy is not always optimal; dynamic programming guarantees an optimum.
3
Consider input size
Backtracking fits small inputs, while divide and conquer fits larger inputs.

6. الملخص: الخوارزميات هي فن حل المشكلات

لنستخدم تشبيهاً لتلخيص الأفكار الخوارزمية المختلفة:

الفكرةالتشبيهالنقطة الأساسية
البحث الثنائيتخمين الأرقاماستبعاد النصف في كل مرة
الترتيبترتيب رف الكتبإرساء النظام
التكرار العوديدمى ماتريوشكاتصغير الكبير
الجشعاختيار طريق التسلقالأمثل المحلي

الرؤية الأساسية

جوهر الخوارزميات هو التوازن بين "الكفاءة" و"الصحة".

  • الخوارزمية الجيدة يمكن أن تحسن كفاءة البرنامج بعدة درجات من الحجم
  • لكن التحسين المفرط قد يضيف تعقيداً
  • تأكد من الصحة أولاً، ثم اسعَ للكفاءة

فهم التفكير الخوارزمي أهم من حفظ الخوارزميات المحددة:

  • فرّق تسد: تفكيك المشكلات الكبيرة إلى صغيرة
  • الجشع: اختيار الأمثل في كل خطوة
  • البرمجة الديناميكية: تسجيل حلول المشكلات الفرعية
  • التراجع: المحاولة والعودة إذا لم تنجح

قراءة إضافية

  • مقدمة في الخوارزميات: الكتاب المدرسي الكلاسيكي لتعلم الخوارزميات بشكل منهجي
  • LeetCode: تحسين المهارات الخوارزمية من خلال حل التمارين
  • تصور الخوارزميات: فهم عملية تنفيذ الخوارزميات بشكل حدسي
  • خوارزميات المسابقات: تعلم تقنيات الخوارزميات الأكثر تقدماً