الخوارزميات وهياكل البيانات باستخدام TypeScript: دليل عملي

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الخوارزميات وهياكل البيانات باستخدام TypeScript: من النظرية إلى التطبيق

\n

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

\n\n

1. هياكل البيانات الأساسية: المكدس والطابور

\n

المكدس والطابور هيكلان بسيطان ولكنهما مفيدان للغاية. يعمل المكدس وفق مبدأ LIFO (Last In, First Out)، بينما يعمل الطابور وفق مبدأ FIFO (First In, First Out). في TypeScript، من السهل تنفيذهما باستخدام مصفوفة مع استخدام الأدوية (Generics) لضمان أمان الأنواع.

\n\n

تنفيذ المكدس (Stack)

\n
class Stack<T> {\n    private items: T[] = [];\n\n    push(item: T): void {\n        this.items.push(item);\n    }\n\n    pop(): T | undefined {\n        return this.items.pop();\n    }\n\n    peek(): T | undefined {\n        return this.items[this.items.length - 1];\n    }\n\n    isEmpty(): boolean {\n        return this.items.length === 0;\n    }\n\n    size(): number {\n        return this.items.length;\n    }\n}\n\n// مثال على الاستخدام\nconst stack = new Stack<number>();\nstack.push(10);\nstack.push(20);\nconsole.log(stack.pop()); // 20\nconsole.log(stack.peek()); // 10
\n\n

تنفيذ الطابور (Queue)

\n
class Queue<T> {\n    private items: T[] = [];\n\n    enqueue(item: T): void {\n        this.items.push(item);\n    }\n\n    dequeue(): T | undefined {\n        return this.items.shift();\n    }\n\n    front(): T | undefined {\n        return this.items[0];\n    }\n\n    isEmpty(): boolean {\n        return this.items.length === 0;\n    }\n\n    size(): number {\n        return this.items.length;\n    }\n}\n\n// مثال على الاستخدام\nconst queue = new Queue<string>();\nqueue.enqueue('A');\nqueue.enqueue('B');\nconsole.log(queue.dequeue()); // A\nconsole.log(queue.front()); // B
\n

لاحظ: الطريقة المضمنة shift() لها تعقيد O(n)، لذلك بالنسبة للبيانات الكبيرة، من الأفضل تنفيذ الطابور باستخدام قائمة مرتبطة.

\n\n

2. خوارزميات البحث: البحث الخطي والثنائي

\n

البحث عن العناصر هو أحد أكثر العمليات شيوعًا. البحث الخطي بسيط ولكنه بطيء مع البيانات الكبيرة. البحث الثنائي يعمل بتعقيد O(log n)، ولكنه يتطلب مصفوفة مرتبة.

\n\n

البحث الخطي

\n
function linearSearch<T>(arr: T[], target: T): number {\n    for (let i = 0; i < arr.length; i++) {\n        if (arr[i] === target) {\n            return i;\n        }\n    }\n    return -1;\n}\n\nconst numbers = [3, 7, 1, 9, 4];\nconsole.log(linearSearch(numbers, 9)); // 3
\n\n

البحث الثنائي (النسخة العودية)

\n
function binarySearch<T>(arr: T[], target: T, left: number = 0, right: number = arr.length - 1): number {\n    if (left > right) {\n        return -1;\n    }\n\n    const mid = Math.floor((left + right) / 2);\n\n    if (arr[mid] === target) {\n        return mid;\n    }\n\n    if (arr[mid] > target) {\n        return binarySearch(arr, target, left, mid - 1);\n    } else {\n        return binarySearch(arr, target, mid + 1, right);\n    }\n}\n\nconst sortedArray = [1, 3, 5, 7, 9, 11];\nconsole.log(binarySearch(sortedArray, 7)); // 3\nconsole.log(binarySearch(sortedArray, 6)); // -1
\n

للنسخة التكرارية، استخدم حلقة while. يساعد TypeScript في تجنب الأخطاء المتعلقة بالأنواع: الدالة العامة <T> تضمن أن المصفوفة والعنصر المستهدف من نفس النوع.

\n\n

3. الترتيب: الترتيب السريع (Quick Sort)

\n

الترتيب السريع هو أحد أكثر الخوارزميات فعالية بمتوسط تعقيد O(n log n). ر

المدونات

توصيات الكتب