بناء الـ Queue عن طريق الـ LinkedList
السلام عليكم ورحمة الله وبركاته
الفهرس
المقدمة
الآن شرحنا الـ LinkedList
وشرحنا الـ Stack
وكيفية بنائها عن طريق الـ LinkedList
الآن سنقوم بشرح الـ Queue
وهو مشابه لشقيقه للـ Stack
مع فارق بسيط
وكما قلت لك في الـ Stack
أنك إذا فهمت الـ LinkedList
وكيفية بنائها
فإنك ستكون قادرًا على بناء الـ Stack
بسهولة وبساطة
وهنا الأمر نفسه مع الـ Queue
فإذا فهمت الـ LinkedList
وكيفية بنائها
فإنك ستكون قادرًا على بناء الـ Queue
بسهولة وبساطة
لكن هناك فارق بسيط بين الـ Stack
والـ Queue
فالـ Stack
يعمل بطريقة LIFO
أي Last In First Out
أما الـ Queue
فهو يعمل بطريقة FIFO
أي First In First Out
أي ما يدخل أولًا يخرج أولًا مثل فكرة طابور العيش
بالطبع كما في الـ Stack
ستجد طبعًا ستجد بعض الأشخاص يقومون ببناء الـ Queue
عن طريق الـ Array
أو الـ Dynamic Array
بطرق معينة
وهي طرق صحيحة ولكن نحن هنا سنقوم ببناء الـ Queue
عن طريق الـ LinkedList
لنبدأ بالشرح
ما هو الـ Queue ؟
الـ Queue
هو كما يوحي اسمه بأنه مثل طابور الانتظار في الحياة الواقعية
له مدخل واحد ومخرج واحد فقط بمعنى أنه يتم إضافة العناصر من البداية ويتم إزالتها من النهاية
وهذا يعني أن العنصر الذي يتم إضافته أولًا هو العنصر الذي يتم إزالته أولًا
فأبسط مثال هو كما قلنا هو الطابور فمثلًا لنتخيل أن هناك طابور للحصول على الطعام في مطعم ما
والأشخاص يدخلون الى الطابور وينتظرون حتى يصل دورهم للحصول على الطعام
والشخص الذي دخل الى الطابور أولًا هو الشخص الذي سيحصل على الطعام أولًا
وهذا هو مفهوم الـ Queue
ببساطة لا أظن أنك ستحتاج لشرح أكثر من هذا
في الحقيقة طالما أنك فهمت الـ LinkedList
والـ Stack
فإنك تستطيع بناء الـ Queue
الآن ولا تحتاج لإكمال القراءة
لكنني بالطبع سأواصل الشرح وسأقوم ببناء الـ Queue
عن طريق الـ LinkedList
لكي تتعلم كيفية بنائه في حالة واجهت مشكلة ما
وأيضًا سنقوم بعمل تطبيق عملي بسيط للـ Queue
ببناء خدمة Ordering System
لمطعم ما
وسنقوم بإضافة الطلبات الى الـ Queue
ومن ثم تنفيذها وإزالتها من الـ Queue
وهذا سنقوم بتطبيقه في نهاية المقالة
سنرى الآن مفهوم الـ Queue
بشكل توضيحي لكي تفهمه بشكل أفضل
تخيل أن هناك خدمة توصيل الطلبات وتقوم بتوصيل الطلبات الى العملاء
وهذه الخدمة تقوم بتوصيل الطلبات بالترتيب الذي تم إضافتها الى الـ Queue
فمثلًا لنفترض أن هناك 3
طلبات وهي Order 1
و Order 2
و Order 3
وتم إضافتها الى الـ Queue
بالترتيب التالي Order 1
ثم Order 2
ثم Order 3
الطلب الذي تم إضافته أولًا وهو Order 1
هو الطلب الذي سيتم توصيله أولًا
ثم بعده Order 2
ثم Order 3
وهكذا
فتخيل الـ Queue
كما في الشكل التالي
حاليًا هو فارغ ولا يحتوي على شيء
+-------------------------------------+
+-------------------------------------+
الآن سنقوم بوضع الطلب رقم 1
في الـ Queue
+-------------------------------------+
| Order 1 |
+-------------------------------------+
الآن سنقوم بوضع الطلب رقم 2
في الـ Queue
+-------------------------------------+
| Order 1 | Order 2 |
+-------------------------------------+
الآن سنقوم بوضع الطلب رقم 3
في الـ Queue
+-------------------------------------+
| Order 1 | Order 2 | Order 3 |
+-------------------------------------+
الآن بعد أن قمنا بوضع الطلبات في الـ Queue
سنقوم بتوصيلها
والطلب الذي تم إضافته أولًا هو الطلب الذي سيتم توصيله أولًا
لنتخيل أننا انتهينا من توصيل الطلب رقم 1
ونحتاج لإزالته من الـ Queue
+-------------------------------------+
| Order 2 | Order 3 |
+-------------------------------------+
الآن سنقوم بتوصيل الطلب رقم 2
والآن نحتاج لإزالته من الـ Queue
+-------------------------------------+
| Order 3 |
+-------------------------------------+
الآن سنقوم بتوصيل الطلب رقم 3
والآن نحتاج لإزالته من الـ Queue
+-------------------------------------+
+-------------------------------------+
هكذا يعمل الـ Queue
وهذا معنى ما يدخل أولًا يخرج أولًا وهو ما نسميه بـ FIFO
أو First In First Out
المكونات الأساسية للـ Queue
الآن بعد أن فهمنا مفهوم الـ Queue
سنقوم بتحديد المكونات الأساسية للـ Queue
والتي سنقوم بإنشائها وهي كالتالي
push
: وهي الدالة التي تقوم بإضافة عنصر جديد الى الـQueue
pop
: وهي الدالة التي تقوم بإزالة العنصر من الـQueue
وعليك أن تعلم أن الـ Queue
له جهتين، جهة للإضافة فقط وجهة أخرى للإزالة فقط وهذا ما يميزه عن الـ Stack
فالـ Stack
له جهة واحدة فقط وهي للإضافة والإزالة من نفس الجهة
فستنتج أن الـ Queue
له head
و tail
لأنك تحتاج للـ head
ليقف عند العنصر الأول و tail
ليقف عند العنصر الأخير
حسنًا في الـ LinkedList
تعلمنا أن الـ push
تأخذ سرعة O(1)
لأن إضافة عنصر جديد ما ناحية الـ tail
تأخذ سرعة O(1)
وهي الدالة التي كانت تدعى push
في الـ LinkedList
وإزالة عنصر من ناحية الـ head
تأخذ سرعة O(1)
وهي الدالة التي كانت تدعى shift
في الـ LinkedList
لذا دالة push
و دالة pop
الذي سنقوم بإنشائها في الـ Queue
سيكونان نفسها دالة push
و shift
في الـ LinkedList
لأننا نحتاج لدالة push
لإضافة عنصر من جهة الـ tail
ودالة shift
لإزالة عنصر من جهة الـ head
وهذه هي العمليات الأساسية للـ Queue
قد يتسائل سائل هل نستطيع استخدام دالة unshift
و pop
في الـ LinkedList
لبناء الـ Queue
؟ أي أننا عكسنا فقط الجهتين
الجواب هو نعم يمكنك استخدامها ولكن لن تكون العمليات سريعة كما في الـ push
و shift
لأنه برغم بأن unshift
تأخذ سرعة O(1)
فالمشكلة تكمن في الـ pop
لأنها تأخذ سرعة O(n)
وهذا ليس مقبول في الـ Queue
لأننا نحتاج لسرعة في الإضافة والإزالة
قد تستخدم Doubly LinkedList
لكن لما نعقد ونزيد مساحة الـ Node
بدون داعي ونحن نستطيع بناء الـ Queue
بسهولة عن طريق الـ LinkedList
بأقل تعقيد باستخدام الـ push
و shift
حسنًا الآن بعد أن فهمنا المكونات الأساسية للـ Queue
سنقوم ببناء الـ Queue
عن طريق الـ LinkedList
بناء الـ Queue عن طريق الـ LinkedList
قبل أن نبدأ ببناء الـ Queue
عن طريق الـ LinkedList
فمثل ما تحديتك في الـ Stack
أتحداك أن تقوم ببناء الـ Queue
بنفسك
أظنك بعد ما بنيت الـ LinkedList
و Stack
في المقالات السابقة
فستكون قادرًا على بناء الـ Queue
بنفسك بسهولة فهمت مفهوم الـ Queue
أريدك أن تتوقف عن القراءة الآن وتحاول بناء الـ Queue
بنفسك
ثم عندما تنتهي تعود لتكملة القراءة
حسنًا الآن بعد أن قمت بمحاولة بناء الـ Queue
بنفسك (أتمنى أن تكون قد فعلت ...)
حسنًا الآن سنقوم ببناء الـ Queue
وأولًا سنقوم بإنشاء الـ Node
بالطبع
class Node {
public data: number;
public next: Node | null;
constructor(data: number, next: Node | null = null) {
this.data = data;
this.next = next;
}
public setNext(next: Node | null) {
this.next = next;
}
}
الآن لدينا الـ Node
وهو يحتوي على data
و next
وهو الشكل البسيط الاعتيادي للـ Node
في الـ LinkedList
الآن لنرى مثال الطلبات السابقة Order 1
و Order 2
و Order 3
في الـ Queue
+-------------------------------------+
| Order 1 | Order 2 | Order 3 |
+-------------------------------------+
الآن كيف سيكون شكلها في الـ Queue
مبنية عن طريق الـ LinkedList
+---------+ +---------+ +---------+
| Order 1 | ------> | Order 2 | ------> | Order 3 |
+---------+ +---------+ +---------+
٨ ٨
| |
head tail
لاحظ أن كل Node
يشير الى الـ Node
الذي بعده لأننا لدينا next
في الـ Node
بالطبع
وبالطبع لدينا head
و tail
لأننا نحتاج لهم لإضافة العناصر وإزالتها من الـ Queue
الآن بعد أن قمنا بإنشاء الـ Node
سنقوم بإنشاء الـ Queue
class Queue {
private head: Node | null;
private tail: Node | null;
private length: number;
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
public isEmpty() {
return this.length === 0;
}
}
الآن لدينا الـ Queue
وهو يحتوي على head
و tail
والطول length
ودالة isEmpty
التي تقوم بإرجاع true
إذا كان الـ Queue
فارغًا و false
إذا كان يحتوي على عناصر
إضافة Node الى الـ Queue
أول شيء سنقوم به بالطبع هو إضافة العناصر الى الـ Queue
بشرح توضيحي
حاليًا لدينا الـ Queue
فارغًا ولا يحتوي على شيء
head = null
tail = null
الآن سنقوم بإضافة Node
بقيمة 10
الى الـ Queue
وبالطبع بسبب أن الـ Queue
فارغًا فسيكون head
و tail
يشيران الى نفس الـ Node
لأنها العنصر الوحيد
+------------+
| 10 | NULL | ----> NULL
+------------+
0x100
٨
|
head
tail
الآن سنقوم بإضافة Node
بقيمة 20
الى الـ Queue
new Node(20)
+------------+ +------------+
| 10 | NULL | ----> NULL | 20 | NULL | ----> NULL
+------------+ +------------+
0x100 0x200
٨
|
head
tail
هنا الـ Node
الجديدة ليست مرتبطة بالـ Node
السابقة بعد
أي أنها ليست ضمن الـ Queue
حتى الآن
لكي نضمها نحتاج لتغيير لفعل خطوتين وهما
- جعل الـ
next
للـNode
السابقة يشير الى الـNode
الجديدة - جعل الـ
tail
يشير الى الـNode
الجديدة
إذا أولًا سنقوم بجعل الـ next
للـ Node
السابقة يشير الى الـ Node
الجديدة
new Node(20)
+------------+ +------------+
| 10 | 0x200 | ---+ | 20 | NULL | ----> NULL
+------------+ | +------------+
0x100 +------> 0x200
٨
|
head
tail
الآن سنقوم بجعل الـ tail
يشير الى الـ Node
الجديدة
new Node(20)
+------------+ +------------+
| 10 | 0x200 | ---+ | 20 | NULL | ----> NULL
+------------+ | +------------+
0x100 +------> 0x200
٨ ٨
| |
head tail
هكذا تمت عملية إضافة الـ Node
الجديدة الى الـ Queue
الآن سنقوم بكتابة الدالة push
التي تقوم بإضافة الـ Node
الى الـ Queue
class Queue {
// ...
public push(data: number) {
const node = new Node(data);
if (this.isEmpty()) {
this.head = node;
this.tail = node;
} else {
this.tail.setNext(node);
this.tail = node;
}
this.length++;
}
// ...
}
الآن لدينا دالة push
التي تقوم بإضافة الـ Node
الى الـ Queue
وهي نفسها دالة push
في الـ LinkedList
دون أي تعديل
وتطبق ما شرحناه سابقًا وهو إذا كانت الـ Queue
فارغة فسيتم إضافة الـ Node
جديدة
وجعل الـ head
والـ tail
يشيران إلى هذه الـ Node
مباشرةً
وإذا كانت الـ Queue
بها عناصر فسيتم إضافة الـ Node
الجديدة
ثم جعل الـ Node
الأخيرة تشير إلى الـ Node
الجديدة عن طريق الـ tail
ثم تحديث الـ tail
ليشير إلى الـ Node
الجديدة
ثم بالطبع تحديث الـ length
ونزيد قيمته بـ 1
الآن نستطيع إضافة العناصر الى الـ Queue
const queue = new Queue();
queue.push(10);
// 10
queue.push(20);
// 10 -> 20
queue.push(30);
// 10 -> 20 -> 30
الآن لدينا الـ Queue
وهي تحتوي على العناصر 10
و 20
و 30
إزالة Node من الـ Queue
الآن بعد أن قمنا بإضافة العناصر الى الـ Queue
سنقوم بإزالتها
لكن تذكر أن الـ Queue
يعمل بطريقة FIFO
أي أن العنصر الذي تم إضافته أولًا هو العنصر الذي يتم إزالته أولًا
بمعنى أننا لو أضفنا العنصر 10
ثم 20
ثم 30
سنقوم بإزالة العنصر 10
أولًا ثم 20
ثم 30
وهذا يعني أننا سنقوم بإزالة العنصر من الـ head
لأنه العنصر الذي تم إضافته أولًا
وكما قلنا فسوف نستخدم دالة shift
التي كانت تقوم بإزالة العنصر من الـ LinkedList
من ناحية الـ head
سنشرها بشكل توضيحي ثم نرى الكود
حاليًا لدينا الـ Queue
تحتوي على العناصر 10
و 20
و 30
+------------+ +------------+ +------------+
| 10 | 0x200 | ---+ | 20 | 0x300 | ---+ | 30 | 0x400 | ----> NULL
+------------+ | +------------+ | +------------+
0x100 +------> 0x200 +------> 0x300
٨ ٨
| |
head tail
الآن نريد إزالة العنصر 10
من الـ Queue
لذا سنبدأ بوضع متغير مؤقت يشير إلى الـ head
+------------+ +------------+ +------------+
| 10 | 0x200 | ---+ | 20 | 0x300 | ---+ | 30 | 0x400 | ----> NULL
+------------+ | +------------+ | +------------+
0x100 +------> 0x200 +------> 0x300
٨ ٨
| |
head tail
temp
ثم نقوم بتحريك الـ head
لتشير إلى الـ Node
التالية لها
+------------+ +------------+ +------------+
| 10 | 0x200 | ---+ | 20 | 0x300 | ---+ | 30 | 0x400 | ----> NULL
+------------+ | +------------+ | +------------+
0x100 +------> 0x200 +------> 0x300
٨ ٨ ٨
| | |
temp head tail
الآن نستطيع حذف والتخلص من الـ Node
القديمة التي كانت تشير إليها الـ head
القديمة
والتي تشير إليها الـ temp
وهذا ما كنا نفعله في الـ LinkedList
temp.next = null
delete temp
+------------+ +------------+ +------------+
| 10 | Null | | 20 | 0x300 | ---+ | 30 | 0x400 | ----> NULL
+------------+ +------------+ | +------------+
0x100 0x200 +------> 0x300
٨ ٨
| |
head tail
وأظن لا داعي لتكرار الكلام عن الـ Garbage Collection
وكيف تعمل لأننا تحدثنا عنها كثيرًا في الـ LinkedList
الآن بعد أن تعرفنا على كيفية إزالة Node
من بداية الـ Queue
بشكل توضيحي
لنرى كيف يمكننا تنفيذ ذلك في الكود
class Queue {
// ...
public pop(): number | null {
if (this.isEmpty()) {
throw new Error('The Queue is empty');
}
if (this.length === 1) {
this.head = null;
this.tail = null;
} else {
let temp = this.head;
this.head = this.head.next;
temp.setNext(null);
}
this.length--;
return this;
}
}
الدالة pop
تقوم بإزالة الـ Node
من بداية الـ Queue
أولًا تحقق إذا كانت الـ Queue
فارغة فسيتم رمي Exception
ثم تحقق إذا كانت الـ Queue
تحتوي على عنصر واحد فقط فسيتم جعل الـ head
والـ tail
يشيران إلى null
بكل بساطة
ثم إذا كانت الـ Queue
تحتوي على أكثر من عنصر فسيتم حفظ الـ Node
القديمة التي تشير إليها الـ head
في متغير مؤقت temp
ثم سيتم تحريك الـ head
لتشير إلى الـ Node
التالية لها
ثم يتم التخلص من الـ Node
القديمة التي كانت تشير إليها الـ head
القديمة
وهذا ما كنا نفعله في الـ LinkedList
والآن نفعله في الـ Queue
تمامًا دون أي تعديل
لأن دالة pop
هذه هي تمامًا دالة shift
في الـ LinkedList
الآن كالعادة يمكنك استخدام هذه الدالة كالتالي:
const queue = new Queue();
queue.push(10).push(20).push(30);
// 10 -> 20 -> 30
queue.pop();
// 20 -> 30
queue.pop();
// 30
أهم شيء أريدك أن تلاحظه أننا بكل نجاح قمنا ببناء الـ Queue
عن طريق الـ LinkedList
مع مراعاة أن الـ Queue
يعمل بطريقة FIFO
أي أن العنصر الذي تم إضافته أولًا هو العنصر الذي يتم إزالته أولًا
فلاحظ هنا أننا قمنا بإضافة العناصر 10
ثم 20
ثم 30
وقمنا بإزالتها بنفس الترتيب
وهذا هو مفهوم الـ Queue
ببساطة
عرض أول وآخر عنصر في الـ Queue
بصراحة هذه الفقرة هي مجرد تحلية لأننا انتهينا من الطبق الرئيسي للتو مع الـ push
والـ pop
الآن نحن فقط لنقوم بإنشاء دالتين لعرض العنصر الأول والعنصر الأخير في الـ Queue
دون إزالتهم بالطبع
class Queue {
// ...
public first(): number | null {
if (this.isEmpty()) {
throw new Error('The Queue is empty');
}
return this.head.data;
}
public last(): number | null {
if (this.isEmpty()) {
throw new Error('The Queue is empty');
}
return this.tail.data;
}
}
الدالة first
تقوم بإرجاع العنصر الأول في الـ Queue
والدالة last
تقوم بإرجاع العنصر الأخير في الـ Queue
بكل بساطة وبدون أي تعقيد
هل تريدني حقًا أن أشرح لك كيف تعمل هذه الدوال ؟ لا أظن ذلك
لذا سأتركك لتجربتها بنفسك
والآن لديك الـ Queue
بكل مكوناتها الأساسية
سنقوم الآن بعمل تطبيق عملي للـ Queue
وهو خدمة Ordering System
لمطعم ما
بناء خدمة Ordering System لمطعم
هذه الفقرة مميزة جدًا لأننا سنقوم ببناء تطبيق عملي للـ Queue
الفكرة هي بناء خدمة Ordering System
لمطعم ما
وهي خدمة حجز الطلبات وتوصيلها بترتيب الحجز
أولًا سنقوم بإنشاء كلاس يسمى OrderingSystem
وسنقوم بإضافة الدوال التالية:
addOrder
: وهي الدالة التي تقوم بإضافة الطلبات الى الـQueue
showNextOrder
: وهي الدالة التي تقوم بعرض الطلب التالي في الـQueue
ولكن لا تقوم بإزالتهgetNextOrder
: وهي الدالة التي تقوم باحضار الطلب التالي من الـQueue
وتزيله من الـQueue
showOrders
: وهي الدالة التي تقوم بعرض الطلبات الموجودة في الـQueue
بترتيب الحجز
وسنقوم ببناء الـ OrderingSystem
الآن
class OrderingSystem {
private queue: Queue;
constructor() {
this.queue = new Queue();
}
}
أولًا سنقوم بإنشاء الـ OrderingSystem
ونجعلها تحتوي على الـ Queue
التي قمنا ببنائها
لاحظ أننا هكذا نستخدم الـ Queue
كأداة تساعدنا لحجز الطلبات وتوصيلها بترتيب الحجز
الآن سنقوم بإضافة الدالة addOrder
التي تقوم بإضافة الطلبات الى الـ Queue
class OrderingSystem {
// ...
public addOrder(order: number) {
this.queue.push(order);
return this;
}
}
الدالة بسيطة جدًا تقوم بإضافة الطلب الى الـ Queue
بكل بساطة
وهي تستخدم الدالة push
التي قمنا ببنائها في الـ Queue
الآن سنقوم بإضافة الدالة showNextOrder
التي تقوم بعرض الطلب التالي في الـ Queue
ولكن لا تقوم بإزالته
class OrderingSystem {
// ...
public showNextOrder() {
return this.queue.first();
}
}
الدالة تقوم بإرجاع الطلب التالي الذي سيتم توصيله
ستفيدنا في حالة أردنا أن نعرف الطلب التالي الذي عليه الدور الآن
وهي تستخدم الدالة first
التي قمنا ببنائها في الـ Queue
الآن سنقوم بإضافة الدالة getNextOrder
التي تقوم بإحضار الطلب التالي من الـ Queue
وتزيله من الـ Queue
class OrderingSystem {
// ...
public getNextOrder() {
return this.queue.pop();
}
}
الدالة تقوم بإرجاع الطلب التالي الذي سيتم توصيله وتزيله من الـ Queue
نستطيع استخدامها لتوصيل الطلبات بالترتيب الصحيح
وهي تستخدم الدالة pop
التي قمنا ببنائها في الـ Queue
الآن سنقوم بإضافة الدالة showOrders
التي تقوم بعرض الطلبات الموجودة في الـ Queue
بترتيب الحجز
class OrderingSystem {
// ...
public showOrders() {
let temp = this.queue.head;
while (temp !== null) {
console.log(temp.data);
temp = temp.next;
}
}
}
الدالة تقوم بعرض الطلبات الموجودة في الـ Queue
بترتيب الحجز
لاحظ أننا لكي نفعل هذا نحتاج للتحرك من الـ head
الى الـ tail
لذا قمنا بإنشاء متغير مؤقت temp
يشير الى الـ head
وهو الذي سنستخدمه للتحرك
ثم قمنا بعمل while
تقوم بالتحرك من الـ head
الى الـ tail
وتقوم بعرض الطلبات طالما أن الـ temp
ليس null
ومع كل لفة فيها ستقوم بطباعة البيانات data
للـ Node
الحالية ثم تنتقل الى الـ Node
التالية عن طريق الـ next
هكذا temp = temp.next
الـ while
سيستمر حتى يصل الى الـ tail
ويكون temp
يشير الى null
ملاحظة: فكرة وجود أكواد متعلقة بعمل عمليات الـ
Queue
في الـOrderingSystem
ليست جيدة وهذا يخالف مبدأ الـSingle Responsibility
وهو يجب على الـOrderingSystem
أن يكون مسؤول عن عمليات الـOrdering
فقط وليس عن عمليات خالصة بالـQueue
لذا علينا نقل الأكواد المتعلقة بالـQueue
فمثلا في دالة تدعىOrderingSystem
class Queue {
// ...
public print() {
let temp = this.head;
while (temp !== null) {
console.log(temp.data);
temp = temp.next;
}
}
}
لكن فكرة وجود أمر طباعة مثل
console.log
في الـQueue
ليست جيدة أيضًا لكن هذا مجرد توضيح للفكرة وليس للتطبيق العملي
إذا أردت التطبيق الصحيح فبدلًا منconsole.log
يمكنك ارجاع البيانات التي داخل الـQueue
في أراي
ثم تقوم بطباعتها في الـOrderingSystem
بالطريقة التي تريدها
أو يمكنك تطبيق مفهوم الـIterator
في الـQueue
وتجعل أي شخص يستطيع عملloop
على الـQueue
هناك أفكار وتفاصيل كثير لكن لنتركها ونكمل ما نقوم به
الآن نحن انتهينا من عمل كلاس الـ Ordering System
OrderingSystem orderingSystem = new OrderingSystem();
orderingSystem.addOrder(10).addOrder(20).addOrder(30);
orderingSystem.showNextOrder(); // 10
const nextOrder = orderingSystem.getNextOrder(); // 10
console.log(nextOrder); // 10
// Process the order
// ...
orderingSystem.showOrders(); // 20 -> 30
الآن لديك خدمة Ordering System
لمطعمك
بالطبع هذا مجرد مثال بسيط وتافه لكنه يوضح لك كيف يمكنك استخدام الـ Queue
في الحياة العملية
فمثلا نظام مثل الـ Ordering System
يجب أن يكون لديك كلاس خاص بالـ Order
وبدلًا من استخدام الأرقام أو الـ string
لتخزينها داخل الـ Queue
يمكننا بناء الـ Queue
لتخزن object
من الـ Order
وهكذا
بالتالي كل Node
في الـ Queue
سيحتوي على Order
وليس number
أو string
OrderingSystem orderingSystem = new OrderingSystem();
const orders = [
new Order('Pizza'),
new Order('Burger'),
new Order('Pasta'),
];
// Loop through the orders and add them to the Queue
for (const order of orders) {
orderingSystem.addOrder(order);
}
orderingSystem.showNextOrder(); // Pizza
const nextOrder = orderingSystem.getNextOrder(); // Pizza
nextOrder.process(); // Process the order
orderingSystem.showOrders(); // Burger -> Pasta
وهكذا يمكنك بناء تطبيقات كبيرة ومعقدة بسهولة باستخدام الـ Queue
وهذا ما يجعل الـ Queue
من الهياكل البيانية المهمة جدًا في البرمجة
خاتمة
كما ترى بناء الـ Queue
ليس بالأمر الصعب على الإطلاق وكما ترى أنها تعتمد على الـ LinkedList
وكما قلت لك سابقًا طالما أنك قمت ببناء الـ LinkedList
وفهمتها جيدًا فأنت تستطيع بناء أي شيء
وأيضًا لا تنسى أن الـ Queue
والـ Stack
مجرد أفكار لتخزين البيانات وتنظيمها والتعامل معها بطريقة معينة
وهذه هي جوهر الـ Data Structures
وهي تساعدك على تنظيم البيانات وتخزينها بشكل منظم وسهل الوصول
وكل Data Structure
لها فكرتها واستخداماتها ومميزاتها وعيوبها ويجب عليك أن تعرفها جيدًا لكي تستطيع استخدامها بشكل جيد
بالنسبة للـ Queue
و الـ Stack
فهما أدوات نستخدمها للتعامل مع البيانات بطريقة معينة كما رأيت في مثال الـ Ordering System
وأيضًا عليك أن تعرف أن يوجد نوع آخر من الـ Queue
يسمى Priority Queue
وهو يعمل بنفس فكرة الـ Queue
لكن يعمل بطريقة Priority
أي نظام يعتمد على الأولوية والأهمية وهذا يعني أن العنصر الذي يتم إضافته يتم ترتيبه بحسب أولويته وأهميته
وهذا يعني أن العنصر الذي يحمل أعلى أولوية سيتم توصيله أولًا وهكذا
يمكنك البحث عن Priority Queue
وتعرف عليها وكيفية بنائها إن أردت
وأخيرًا أتمنى أن تكون قد استفدت من هذا الدرس وأن تكون قد فهمت الـ Queue
جيدًا