الخوارزميات وهياكل البيانات في TypeScript: من المبتدئ إلى المحترف
الخوارزميات وهياكل البيانات هي الأساس الذي يقوم عليه تطوير البرمجيات الحديثة. سواء كنت تكتب واجهة أمامية في React، أو خلفية في Node.js، أو تطبيق جوال، فإن الفهم العميق لهذه المفاهيم يسمح لك بإنشاء تطبيقات فعالة وقابلة للتوسع وسريعة. في هذه المقالة، سندرس بالتفصيل الخوارزميات وهياكل البيانات الرئيسية في TypeScript — وهي لغة تجمع بين مرونة JavaScript ودقة الكتابة الثابتة.
تعتبر TypeScript مثالية لتعلم الخوارزميات: فالكتابة الصارمة تساعد في تجنب الأخطاء في مرحلة التجميع، ودعم الأدوية (Generics) يسمح لك بإنشاء هياكل بيانات عالمية وقابلة لإعادة الاستخدام. سنبدأ بمفاهيم بسيطة وننتقل تدريجياً إلى مواضيع أكثر تعقيداً، مع مرافقة كل خطوة بأمثلة واضحة من الكود.
1. هياكل البيانات الأساسية: المكدس والطابور
المكدس (Stack) والطابور (Queue) هما بنيتان خطيتان أساسيتان تستخدمان في كل مكان: من إدارة سجل المتصفح إلى جدولة المهام في أنظمة التشغيل. دعنا نرى تنفيذهما في TypeScript.
المكدس (LIFO — Last In, First Out)
يعمل المكدس على مبدأ "آخر ما يدخل، أول ما يخرج". العمليات الرئيسية هي: push (إضافة عنصر) و pop (إزالة آخر عنصر).
class Stack<T> { private items: T[] = [];
push(element: T): void { this.items.push(element); }
pop(): T | undefined { return this.items.pop(); }
peek(): T | undefined { return this.items[this.items.length - 1]; }
isEmpty(): boolean { return this.items.length === 0; }
size(): number { return this.items.length; }}
// Example usageconst stack = new Stack<number>();stack.push(1);stack.push(2);stack.push(3);console.log(stack.pop()); // 3console.log(stack.peek()); // 2الطابور (FIFO — First In, First Out)
يعمل الطابور على مبدأ "أول ما يدخل، أول ما يخرج". العمليات الرئيسية هي: enqueue (إضافة إلى النهاية) و dequeue (إزالة من البداية).
class Queue<T> { private items: T[] = [];
enqueue(element: T): void { this.items.push(element); }
dequeue(): T | undefined { return this.items.shift(); }
front(): T | undefined { return this.items[0]; }
isEmpty(): boolean { return this.items.length === 0; }
size(): number { return this.items.length; }}
// Example usageconst queue = new Queue<string>();queue.enqueue("First");queue.enqueue("Second");queue.enqueue("Third");console.log(queue.dequeue()); // "First"console.log(queue.front()); // "Second"2. خوارزميات البحث: البحث الخطي والبحث الثنائي
البحث عن البيانات هو أحد أكثر العمليات شيوعاً في البرمجة. سندرس طريقتين رئيسيتين: البحث الخطي (بسيط لكنه بطيء) والبحث الثنائي (سريع لكنه يتطلب بيانات مرتبة).
البحث الخطي
تتحقق الخوارزمية بشكل تسلسلي من كل عنصر في المصفوفة حتى تجد الهدف. درجة التعقيد الزمني: O(n).
function linearSearch<T>(arr: T[], target: T): number { for (let i = 0; i < arr.length; i++) { if (arr[i] === target) { return i; // Returns the index of the found element } } return -1; // Element not found}
// Exampleconst numbers = [10, 20, 30, 40, 50];console.log(linearSearch(numbers, 30)); // 2console.log(linearSearch(numbers, 60)); // -1البحث الثنائي
يعمل البحث الثنائي فقط على المصفوفات المرتبة. يقوم بتقسيم المصفوفة إلى نصفين في كل خطوة، متخلصاً من نصف واحد