الخوارزميات وهياكل البيانات في JavaScript (Node.js): من المبتدئ إلى المحترف
كل مطور JavaScript يواجه عاجلاً أم آجلاً الحاجة إلى فهم عميق للخوارزميات وهياكل البيانات. بغض النظر عما إذا كنت تكتب الواجهة الأمامية باستخدام React أو الخلفية باستخدام Node.js، فإن معرفة كيفية تنظيم البيانات ومعالجتها بكفاءة هي مهارة أساسية. في هذه المقالة، سنشرح هياكل البيانات الأساسية والخوارزميات الشائعة مع أمثلة عملية بلغة JavaScript لبيئة Node.js.
لماذا دراسة الخوارزميات وهياكل البيانات؟
الخوارزميات وهياكل البيانات هي الأساس الذي يُبنى عليه أي تطبيق. الاختيار الصحيح لهيكل البيانات يمكن أن يسرّع تنفيذ البرنامج بعشرات المرات. على سبيل المثال، البحث عن عنصر في مصفوفة تحتوي على 10,000 عنصر قد يستغرق ما يصل إلى 10,000 عملية، بينما في جدول التجزئة (hash table) يستغرق عملية واحدة فقط. فهم هذه المبادئ يساعد على:
- كتابة كود أكثر كفاءة في الأداء
- استخدام الذاكرة بشكل فعال
- اجتياز المقابلات التقنية
- فهم البنية الداخلية للمكتبات والأطر الشائعة
هياكل البيانات الأساسية في JavaScript
المصفوفات (Arrays)
المصفوفات هي أكثر هياكل البيانات شيوعاً في JavaScript. تخزن العناصر بترتيب متسلسل وتوفر الوصول إليها بواسطة الفهرس (index) بتعقيد O(1). في Node.js، المصفوفات مفيدة بشكل خاص للعمل مع تدفقات البيانات.
// مثال على العمل مع المصفوفات في Node.jsconst numbers = [5, 2, 9, 1, 5, 6];
// إضافة عنصر إلى النهايةnumbers.push(10); // [5, 2, 9, 1, 5, 6, 10]
// حذف آخر عنصرconst last = numbers.pop(); // 10
// البحث عن عنصرconst index = numbers.findIndex(num => num === 9); // 2
// التصفيةconst filtered = numbers.filter(num => num > 5); // [9, 6]
console.log(`نتيجة التصفية: ${filtered}`);المكدس (Stack)
المكدس يعمل وفق مبدأ LIFO (Last In, First Out - آخر ما يدخل هو أول ما يخرج). هذا هيكل مثالي للمهام التي تحتاج الوصول إلى آخر عنصر تمت إضافته: سجل الإجراءات (تراجع/إعادة)، التحقق من الأقواس، اجتياز الرسوم البيانية.
class Stack { constructor() { this.items = []; }
push(element) { this.items.push(element); }
pop() { if (this.isEmpty()) return null; return this.items.pop(); }
peek() { if (this.isEmpty()) return null; return this.items[this.items.length - 1]; }
isEmpty() { return this.items.length === 0; }
size() { return this.items.length; }}
// مثال: التحقق من صحة الأقواسfunction isValidParentheses(str) { const stack = new Stack(); const pairs = { '(': ')', '{': '}', '[': ']' };
for (let char of str) { if (pairs[char]) { stack.push(char); } else { const last = stack.pop(); if (pairs[last] !== char) return false; } }
return stack.isEmpty();}
console.log(isValidParentheses("({[]})")); // trueconsole.log(isValidParentheses("({[})")); // falseالطابور (Queue)
الطابور يعمل وفق مبدأ FIFO (First In, First Out - أول ما يدخل هو أول ما يخرج). لا غنى عنه لمعالجة المهام بترتيب وصولها: جدولة المهام، قوائم انتظار الرسائل، BFS (البحث بالعرض).
class Queue { constructor() { this.items = {}; this.front = 0; this.rear = 0; }
enqueue(element) { this.items[this.rear] = element; this.rear++; }
dequeue() { if (this.isEmpty()) return null; const item = this.items[this.front]; delete this.items[this.front]; this.front++; return item; }
isEmpty() { return this.front === this.rear; }
size() { return this.rear - this.front; }}
// مثال: محاكاة طابور الطباعةconst printQueue = new Queue();printQueue.enqueue("document1.pdf");printQueue.enqueue("document2.pdf");printQueue.enqueue("photo.jpg");
while (!printQueue.isEmpty()) {