الخوارزميات وهياكل البيانات في TypeScript: تطبيق عملي
TypeScript ليست مجرد إضافة فوق JavaScript. بفضل الكتابة الصارمة والإمكانيات الحديثة، تعتبر TypeScript مثالية لتنفيذ الخوارزميات وهياكل البيانات المعقدة. في هذه المقالة، سنستعرض هياكل البيانات والخوارزميات الرئيسية مع أمثلة عملية باستخدام TypeScript. ستتعلم كيفية تنفيذ المكدس، قائمة الانتظار، القائمة المرتبطة، جدول التجزئة، بالإضافة إلى إتقان خوارزميات البحث الثنائي والفرز.
1. المكدس وقائمة الانتظار: هياكل بيانات أساسية
المكدس وقائمة الانتظار هما هيكلان أساسيان يُستخدمان في كل مكان: من معالجة استدعاءات الدوال إلى إدارة المهام في المتصفح.
المكدس (Stack) — LIFO (Last In, First Out)
يعمل المكدس وفق مبدأ "آخر من يدخل هو أول من يخرج". سنقوم بتنفيذه باستخدام مصفوفة والأدوية العامة في TypeScript:
class Stack<T> { private items: T[] = [];
push(item: T): void { this.items.push(item); }
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; }}
// مثال على الاستخدامconst numberStack = new Stack<number>();numberStack.push(10);numberStack.push(20);console.log(numberStack.pop()); // 20console.log(numberStack.peek()); // 10قائمة الانتظار (Queue) — FIFO (First In, First Out)
تعمل قائمة الانتظار وفق مبدأ "أول من يدخل هو أول من يخرج". التنفيذ باستخدام TypeScript:
class Queue<T> { private items: T[] = [];
enqueue(item: T): void { this.items.push(item); }
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; }}
// مثال على الاستخدامconst stringQueue = new Queue<string>();stringQueue.enqueue('A');stringQueue.enqueue('B');console.log(stringQueue.dequeue()); // 'A'console.log(stringQueue.front()); // 'B'هام: عملية shift() في JavaScript لها تعقيد O(n)، لأنها تنقل جميع العناصر. للحصول على قائمة انتظار أكثر كفاءة، استخدم قائمة مرتبطة أو مخزن دائري.
2. القائمة المرتبطة (Linked List)
القائمة المرتبطة هي سلسلة من العقد، حيث تخزن كل عقدة بيانات ومرجعًا للعقدة التالية. في TypeScript، يمكننا استخدام الواجهات للكتابة الصارمة.
interface ListNode<T> { value: T; next: ListNode<T> | null;}
class LinkedList<T> { private head: ListNode<T> | null = null;
append(value: T): void { const newNode: ListNode<T> = { value, next: null }; if (!this.head) { this.head = newNode; return; } let current = this.head; while (current.next) { current = current.next; } current.next = newNode; }
prepend(value: T): void { const newNode: ListNode<T> = { value, next: this.head }; this.head = newNode; }
delete(value: T): void { if (!this.head) return; if (this.head.value === value) { this.head = this.head.next; return; } let current = this.head; while (current.next) { if (current.next.value === value) { current.next = current.next.next; return; } current = current.next; } }
print(): void { let current = this.head; const values: T[] = [];