الخوارزميات وهياكل البيانات بلغة JavaScript: دليل عملي

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

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

ابدأ الدورة

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

\n

القدرة على العمل مع الخوارزميات وهياكل البيانات هي مهارة أساسية لأي مطور، بغض النظر عن لغة البرمجة. JavaScript (خاصة في بيئة Node.js) ليست استثناءً. في هذه المقالة، سنشرح هياكل البيانات الأساسية والخوارزميات الكلاسيكية، وننفذها باستخدام JavaScript الخالص. سترى كيف يتم تطبيق المكدس، والطابور، والقائمة المرتبطة، والشجرة، وخوارزميات الترتيب/البحث في المهام الواقعية لتطوير الواجهة الخلفية باستخدام Node.js.

\n\n

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

\n

المكدس (Stack) والطابور (Queue) هما هيكلان خطيان للبيانات يختلفان في قواعد إضافة وإزالة العناصر. يعمل المكدس وفق مبدأ LIFO (آخر دخول، أول خروج)، بينما يعمل الطابور وفق مبدأ FIFO (أول دخول، أول خروج).

\n\n

تنفيذ المكدس بلغة JavaScript

\n

في JavaScript، يمكن تنفيذ المكدس باستخدام مصفوفة أو قائمة مرتبطة. لنلقِ نظرة على نسخة بسيطة باستخدام المصفوفة:

\n
class Stack {\n    constructor() {\n        this.items = [];\n    }\n\n    push(element) {\n        this.items.push(element);\n    }\n\n    pop() {\n        if (this.isEmpty()) return null;\n        return this.items.pop();\n    }\n\n    peek() {\n        if (this.isEmpty()) return null;\n        return this.items[this.items.length - 1];\n    }\n\n    isEmpty() {\n        return this.items.length === 0;\n    }\n\n    size() {\n        return this.items.length;\n    }\n}\n\n// مثال على الاستخدام\nconst stack = new Stack();\nstack.push('A');\nstack.push('B');\nstack.push('C');\nconsole.log(stack.pop());  // 'C'\nconsole.log(stack.peek()); // 'B'
\n

يُستخدم المكدس غالبًا للتحقق من توازن الأقواس، وتنفيذ زر "الرجوع" في المتصفح، أو لاجتياز الأشجار بالعمق أولاً.

\n\n

تنفيذ الطابور بلغة JavaScript

\n

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

\n
class Queue {\n    constructor() {\n        this.items = [];\n    }\n\n    enqueue(element) {\n        this.items.push(element);\n    }\n\n    dequeue() {\n        if (this.isEmpty()) return null;\n        return this.items.shift();\n    }\n\n    front() {\n        if (this.isEmpty()) return null;\n        return this.items[0];\n    }\n\n    isEmpty() {\n        return this.items.length === 0;\n    }\n\n    size() {\n        return this.items.length;\n    }\n}\n\n// مثال على الاستخدام\nconst queue = new Queue();\nqueue.enqueue(1);\nqueue.enqueue(2);\nqueue.enqueue(3);\nconsole.log(queue.dequeue()); // 1\nconsole.log(queue.front());   // 2
\n

تُستخدم الطوابير في أنظمة إدارة المهام، وفي خوارزميات BFS (البحث بالعرض أولاً)، ولتخزين البيانات مؤقتًا في Node.js (مثل التدفقات).

\n\n

2. القائمة المرتبطة: هيكل ديناميكي للإدراج المتكرر

\n

القائمة المرتبطة (Linked List) هي سلسلة من العقد، تحتوي كل عقدة على بيانات ومرجع إلى العقدة التالية. على عكس المصفوفة، يتم إدراج وحذف العناصر في منتصف القائمة بتعقيد O(1) عند وجود مرجع إلى العقدة.

\n\n

تنفيذ قائمة مرتبطة أحادية الاتجاه

\n
class ListNode {\n    constructor(value, next = null) {\n        this.value = value;\n        this.next = next;\n    }\n}\n\nclass LinkedList {\n    constructor() {\n        this.head = null;\n        this.tail = null;\n        this.length = 0;\n    }\n\n    append(value) {\n        const newNode = new ListNode(value);\n        if (!this.head) {\n            this.head = newNode;\n            this.tail = newNode;\n        } else {\n            this.tail.next = newNode;\n            this.tail = newNode;\n        }\n        this.length++;\n        return this;\n    }\n\n    prepend(value) {\n        const newNode = new ListNode(value, this.head);\n        this.head = newNode;\n        if (!this.tail) this.tail = newNode;\n                

المدونات

توصيات الكتب