Queues from Scratch (Queue ကို အစကနေ ကိုယ်တိုင် တည်ဆောက်ခြင်း)
B4.1.1 (HL): Explain the properties and purpose of ADTs in programming. Implement a queue as an ADT using linked list nodes.
မြန်မာလို: programming မှာ ADT (abstract data type: operation တွေနဲ့ သတ်မှတ်တဲ့ ဒေတာ အမျိုးအစား) တွေရဲ့ ဂုဏ်သတ္တိတွေနဲ့ ရည်ရွယ်ချက်ကို ရှင်းပြနိုင်ရပါမယ်။ Linked list (node တွေ ချိတ်ဆက်ထားတဲ့ list) ရဲ့ node (ဒေတာ သိမ်းထားတဲ့ အကွက်) တွေကို သုံးပြီး queue (အရင်ထည့်တာ အရင်ထွက်တဲ့ တန်း) ကို ADT တစ်ခုအဖြစ် ကိုယ်တိုင် ရေးနိုင်ရပါမယ်။
ဒီစာမျက်နှာက HL အတွက်ပဲ ဖြစ်ပါတယ်။ SL (Standard Level) နဲ့ HL (Higher Level) ဆိုတာ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) သင်တန်းရဲ့ အဆင့်နှစ်ဆင့်ဖြစ်ပြီး HL အပိုင်းတွေက ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အပိုင်းတွေပါ။
အဓိက အယူအဆများ
Queues စာမျက်နှာမှာ Java ရဲ့ LinkedList class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) ကို queue အဖြစ် သုံးပြီး queue တွေကို သုံး တတ်အောင် လေ့လာခဲ့ပါတယ်။ ဒီစာမျက်နှာမှာတော့ queue တစ်ခုကို အစကနေ ကိုယ်တိုင် တည်ဆောက် မှာ ဖြစ်ပြီး enqueue (queue ရဲ့ နောက်ဆုံးမှာ ထည့်ခြင်း) နဲ့ dequeue (queue ရဲ့ ရှေ့ဆုံးကနေ ဖယ်ထုတ်ခြင်း) က node အဆင့်မှာ ဘယ်လို အလုပ်လုပ်လဲ နားလည်အောင် လေ့လာပါမယ်။
Queue ရဲ့ Operation များကို ပြန်နွှေးခြင်း
Queue က FIFO (First In, First Out: အရင်ဝင်တာ အရင်ထွက်) စည်းမျဉ်းအတိုင်း အလုပ်လုပ်ပါတယ်:
| Operation (လုပ်ဆောင်ချက်) | ဖော်ပြချက် | ကြာချိန် |
|---|---|---|
enqueue(item) | item ကို နောက်ဆုံးမှာ ထည့်တယ် | Tail (list ရဲ့ နောက်ဆုံး node) ကို မှတ်ထားရင် O(1) (ကြာချိန် ပုံသေ) |
dequeue() | ရှေ့ဆုံးက item (အချက်) ကို ဖယ်ထုတ်ပြီး ပြန်ပေးတယ် | O(1) |
peek() | ရှေ့ဆုံးက item ကို မဖယ်ဘဲ ကြည့်တယ် | O(1) |
isEmpty() | Queue ထဲမှာ element (အစုထဲက အချက်) တစ်ခုမှ မရှိဘူးလား စစ်တယ် | O(1) |
size() | Element အရေအတွက်ကို ပြန်ပေးတယ် | O(1) |
Linked List ကို သုံးပြီး တည်ဆောက်မယ့် နည်းလမ်း
Queue က အစွန်း နှစ်ဖက်လုံး ကို မြန်မြန် ယူသုံးနိုင်ဖို့ လိုပါတယ်: နောက်ဆုံးမှာ enqueue လုပ်ပြီး ရှေ့ဆုံးကနေ dequeue လုပ်ပါတယ်။ ဒါကြောင့် reference (object ရှိရာ memory နေရာကို ညွှန်းတဲ့ တန်ဖိုး) နှစ်ခုကို ထိန်းထားပါတယ်:
- front (head: list ရဲ့ ရှေ့ဆုံး node): item တွေကို dequeue လုပ်တဲ့ နေရာ
- rear (tail): item တွေကို enqueue လုပ်တဲ့ နေရာ
ဒီလိုဆိုရင် operation နှစ်ခုလုံးက O(1) ဖြစ်ပြီး traversal (node ဒါမှမဟုတ် element တိုင်းကို အစဉ်တကျ သွားကြည့်ခြင်း) မလိုပါဘူး။
ပုံထဲက English စာတွေရဲ့ အဓိပ္ပာယ်: “dequeue here” က ဒီကနေ dequeue လုပ်တယ်၊ “enqueue after here” က ဒီ node ရဲ့ နောက်မှာ enqueue လုပ်တယ်လို့ အဓိပ္ပာယ်ရပါတယ်။ ညာဘက် အစွန်းက null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) က list ရဲ့ အဆုံးကို ပြပါတယ် (Python မှာ None ပါ)။
Stack နဲ့ Queue: Implementation (အထဲမှာ တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ code) နှိုင်းယှဉ်ချက်
| လက္ခဏာ | LinkedStack | LinkedQueue |
|---|---|---|
| ထိန်းထားတဲ့ reference များ | top (head ပဲ) | front (head) + rear (tail) |
| ထည့်ခြင်း | Head မှာ (push: stack ရဲ့ အပေါ်ဆုံးမှာ ထည့်ခြင်း) | Tail မှာ (enqueue) |
| ဖယ်ထုတ်ခြင်း | Head ကနေ (pop: stack ရဲ့ အပေါ်ဆုံးကနေ ဖယ်ထုတ်ခြင်း) | Head ကနေ (dequeue) |
| စည်းမျဉ်း | LIFO (နောက်ဆုံးဝင်တာ အရင်ထွက်) | FIFO |
| Node class | အတူတူ | အတူတူ |
နှစ်ခုလုံးက Node class တစ်ခုတည်းကို သုံးပါတယ်။ တစ်ခုတည်းသော ကွာခြားချက်က item အသစ်တွေကို ဘယ်နေရာမှာ ထည့်လဲ ဆိုတာပါ: stack (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်) က အစွန်း တစ်ဖက်တည်း (head) မှာ ထည့်ပြီး အဲဒီကနေပဲ ဖယ်ထုတ်ပါတယ်၊ queue ကတော့ အစွန်း တစ်ဖက် (tail) မှာ ထည့်ပြီး နောက်တစ်ဖက် (head) ကနေ ဖယ်ထုတ်ပါတယ်။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: LinkedQueue ရဲ့ Implementation
public class LinkedQueue {
private Node front; // head -- dequeue from here
private Node rear; // tail -- enqueue here
private int count;
public LinkedQueue() {
front = null;
rear = null;
count = 0;
}
// Enqueue: add to the back (tail)
public void enqueue(String item) {
Node newNode = new Node(item);
if (rear == null) {
// Empty queue: new node is both front and rear
front = newNode;
rear = newNode;
} else {
rear.next = newNode; // link current rear to new node
rear = newNode; // update rear to new node
}
count++;
}
// Dequeue: remove and return from the front (head)
public String dequeue() {
if (front == null) {
System.out.println("Queue is empty");
return null;
}
String data = front.data;
front = front.next;
if (front == null) {
rear = null; // queue is now empty
}
count--;
return data;
}
// Peek: view front without removing
public String peek() {
if (front == null) {
System.out.println("Queue is empty");
return null;
}
return front.data;
}
public boolean isEmpty() {
return front == null;
}
public int size() {
return count;
}
public void printQueue() {
System.out.print("FRONT -> ");
Node current = front;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null <- REAR");
}
public static void main(String[] args) {
LinkedQueue queue = new LinkedQueue();
queue.enqueue("Alice");
queue.enqueue("Ben");
queue.enqueue("Carlos");
queue.printQueue();
System.out.println("Peek: " + queue.peek());
System.out.println("Size: " + queue.size());
System.out.println("Dequeue: " + queue.dequeue());
System.out.println("Dequeue: " + queue.dequeue());
queue.printQueue();
System.out.println("Size: " + queue.size());
}
}
# The Node class from the Linked Lists page
class Node():
def __init__(self, data):
self.data = data # the value this node stores
self.next = None # reference to the next node
class LinkedQueue():
def __init__(self):
self._front = None # head -- dequeue from here
self._rear = None # tail -- enqueue here
self._count = 0 # the leading underscore marks these as private (IB convention)
# Enqueue: add to the back (tail)
def enqueue(self, item):
new_node = Node(item)
if self._rear == None:
# Empty queue: new node is both front and rear
self._front = new_node
self._rear = new_node
else:
self._rear.next = new_node # link current rear to new node
self._rear = new_node # update rear to new node
self._count = self._count + 1
# Dequeue: remove and return from the front (head)
def dequeue(self):
if self._front == None:
print("Queue is empty")
return None
data = self._front.data
self._front = self._front.next
if self._front == None:
self._rear = None # queue is now empty
self._count = self._count - 1
return data
# Peek: view front without removing
def peek(self):
if self._front == None:
print("Queue is empty")
return None
return self._front.data
def isEmpty(self):
return self._front == None
def size(self):
return self._count
def print_queue(self):
print("FRONT -> ", end="")
current = self._front
while current != None:
print(current.data + " -> ", end="")
current = current.next
print("null <- REAR")
queue = LinkedQueue()
queue.enqueue("Alice")
queue.enqueue("Ben")
queue.enqueue("Carlos")
queue.print_queue()
print("Peek:", queue.peek())
print("Size:", queue.size())
print("Dequeue:", queue.dequeue())
print("Dequeue:", queue.dequeue())
queue.print_queue()
print("Size:", queue.size())
Output (program က ထုတ်ပြတဲ့ ရလဒ်):
FRONT -> Alice -> Ben -> Carlos -> null <- REAR
Peek: Alice
Size: 3
Dequeue: Alice
Dequeue: Ben
FRONT -> Carlos -> null <- REAR
Size: 1
FIFO အစဉ်ကို သတိပြုကြည့်ပါ: Alice ကို အရင်ဆုံး enqueue လုပ်ခဲ့လို့ အရင်ဆုံး dequeue ဖြစ်ပါတယ်။
enqueue("Carlos") လုပ်ပြီး နောက်မှာ dequeue() လုပ်ပုံပါ။ အဆင့်တိုင်းမှာ အရောင် ထင်းထားတဲ့ မြှားက အဲဒီ line က ပြောင်းလိုက်တဲ့ reference ပါ။
ပုံထဲက “returns Alice” က Alice ကို ပြန်ပေးတယ်လို့ အဓိပ္ပာယ်ရပါတယ်။
dequeueမှာ အလွန် အရေးကြီးတဲ့ edge case (ပုံမှန် မဟုတ်တဲ့ အစွန်းရောက် အခြေအနေ)။ နောက်ဆုံး item ကို dequeue လုပ်လိုက်တဲ့အခါfrontကnullဖြစ်သွားပါတယ်။rear = nullလို့လည်း သတ်မှတ်ပေးရပါမယ်။ မဟုတ်ရင်rearက ဖယ်ထုတ်ပြီးသား node ကို ညွှန်းနေဆဲ ဖြစ်ပြီး နောက်တစ်ခါenqueueလုပ်တဲ့အခါ ဘာနဲ့မှ မချိတ်တော့တဲ့ node နဲ့ သွားချိတ်မိပါလိမ့်မယ်။
ဥပမာ 2: Print Queue ကို အတုယူ ပုံဖော်ခြင်း
လက်တွေ့ ဘဝက အသုံးချပုံ တစ်ခုပါ: document တွေကို ရောက်တဲ့ အစဉ်အတိုင်း print ထုတ်ပေးတဲ့ printer queue ကို simulate (အစစ်အမှန်လို အတုယူ ပုံဖော်) လုပ်တာပါ။
public class PrinterQueue {
public static void main(String[] args) {
LinkedQueue printQueue = new LinkedQueue();
// Documents arrive
printQueue.enqueue("Report.pdf");
printQueue.enqueue("Invoice.docx");
printQueue.enqueue("Photo.png");
printQueue.enqueue("Slides.pptx");
System.out.println("Print queue:");
printQueue.printQueue();
// Process documents in FIFO order
while (!printQueue.isEmpty()) {
String doc = printQueue.dequeue();
System.out.println("Printing: " + doc);
}
System.out.println("Queue empty: " + printQueue.isEmpty());
}
}
print_queue = LinkedQueue()
# Documents arrive
print_queue.enqueue("Report.pdf")
print_queue.enqueue("Invoice.docx")
print_queue.enqueue("Photo.png")
print_queue.enqueue("Slides.pptx")
print("Print queue:")
print_queue.print_queue()
# Process documents in FIFO order
while print_queue.isEmpty() == False:
doc = print_queue.dequeue()
print("Printing:", doc)
# Python prints True here -- Java prints true
print("Queue empty:", print_queue.isEmpty())
Output:
Print queue:
FRONT -> Report.pdf -> Invoice.docx -> Photo.png -> Slides.pptx -> null <- REAR
Printing: Report.pdf
Printing: Invoice.docx
Printing: Photo.png
Printing: Slides.pptx
Queue empty: true
ဥပမာ 3: Hot Potato ကစားနည်း (Round-Robin)
Queue ကို သုံးပြီး round-robin (အလှည့်ကျ အချိန်ပေးတဲ့ scheduling) လုပ်ဆောင်ပုံကို simulate လုပ်နိုင်ပါတယ်: ရှေ့ဆုံး item ကို dequeue လုပ်၊ အလုပ်လုပ်ပြီးရင် နောက်ဆုံးမှာ ပြန် enqueue လုပ်ပါတယ်။ Hot Potato (ကစားသူတွေက အာလူးကို အလှည့်ကျ လက်ဆင့်ကမ်းပြီး သတ်မှတ်ထားတဲ့ အကြိမ်ရေ ကမ်းပြီးတိုင်း အာလူး ကိုင်ထားရတဲ့သူ ထွက်ရတဲ့ ကစားနည်း) က ဒီလို ပုံစံ တစ်ခုပါ။
public static String hotPotato(String[] players, int passes) {
LinkedQueue circle = new LinkedQueue();
for (int i = 0; i < players.length; i++) {
String player = players[i];
circle.enqueue(player);
}
// for-each version: for (String player : players) { circle.enqueue(player); }
while (circle.size() > 1) {
// Pass the potato
for (int i = 0; i < passes; i++) {
circle.enqueue(circle.dequeue()); // move front to back
}
String eliminated = circle.dequeue();
System.out.println(eliminated + " is eliminated");
}
return circle.dequeue(); // last player standing
}
// hotPotato(new String[]{"Aiko","Ben","Carlos","Diana","Eve"}, 3)
// Eliminations: Diana, Carlos, Eve, Ben
// Winner: Aiko
def hot_potato(players, passes):
circle = LinkedQueue()
for i in range(len(players)):
player = players[i]
circle.enqueue(player)
# for-each version: for player in players:
while circle.size() > 1:
# Pass the potato
for i in range(passes):
circle.enqueue(circle.dequeue()) # move front to back
eliminated = circle.dequeue()
print(eliminated, "is eliminated")
return circle.dequeue() # last player standing
# hot_potato(["Aiko", "Ben", "Carlos", "Diana", "Eve"], 3)
# Eliminations: Diana, Carlos, Eve, Ben
# Winner: Aiko
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. Linked queue က reference ဘယ်နှစ်ခု ထိန်းထားသလဲ။
Q2. enqueue က item အသစ်ကို ဘယ်မှာ ထည့်သလဲ။
Q3. နောက်ဆုံး item ကို dequeue လုပ်တဲ့အခါ rear ကို null လို့ ဘာကြောင့် သတ်မှတ်ရသလဲ။
Q4. Linked stack နဲ့ linked queue ကြားက ဖွဲ့စည်းပုံ ဆိုင်ရာ အဓိက ကွာခြားချက်က ဘာလဲ။
Q5. Linked queue မှာ enqueue နဲ့ dequeue ရဲ့ time complexity (input ကြီးလာရင် ကြာချိန် တိုးပုံ) က ဘာလဲ။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
Operation တစ်ခုစီ ပြီးတိုင်း queue ရဲ့ အခြေအနေကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပါ။
LinkedQueue q = new LinkedQueue();
q.enqueue("X");
q.enqueue("Y");
q.enqueue("Z");
q.dequeue();
q.enqueue("W");
q.dequeue();
q = LinkedQueue()
q.enqueue("X")
q.enqueue("Y")
q.enqueue("Z")
q.dequeue()
q.enqueue("W")
q.dequeue()
| လုပ်ပြီးတဲ့ operation | front (peek) | rear | Queue (front ကနေ rear) | size() |
|---|---|---|---|---|
| enqueue("X") | X | 1 | ||
| enqueue("Y") | X | 2 | ||
| enqueue("Z") | X | X, Y, Z | ||
| dequeue() က X ကို ပြန်ပေး | Z | 2 | ||
| enqueue("W") | Y | Y, Z, W | 3 | |
| dequeue() က Y ကို ပြန်ပေး | W |
Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)
Linked queue အတွက် enqueue method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) ကို ပြီးအောင် ဖြည့်ပါ။
Queue ရဲ့ rear မှာ item တစ်ခု ထည့်ဖို့ ကွက်လပ်တွေကို ဖြည့်ပါ:
public void enqueue(String item) {
Node newNode = new Node(item);
if (rear == null) {
front = newNode;
= newNode;
} else {
rear. = newNode;
rear = ;
}
count++;
}
dequeue method ကို ပြီးအောင် ဖြည့်ပါ။
Front item ကို ဖယ်ထုတ်ပြီး ပြန်ပေးဖို့ ကွက်လပ်တွေကို ဖြည့်ပါ:
public String dequeue() {
if (front == null) {
return null;
}
String data = front.;
front = front.;
if (front == null) {
= null;
}
count--;
return data;
}
Spot the Error (အမှား ရှာခြင်း)
ဒီ queue က item အများကြီး ရှိနေတုန်းမှာ အလုပ်လုပ်ပေမယ့် နောက်ဆုံး item ကို dequeue လုပ်ပြီး နောက် ပြန် enqueue လုပ်တဲ့အခါ ပျက်သွားပါတယ်:
မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
ဒီ queue က dequeue လုပ်တိုင်း နောက်ဆုံး ထည့်ခဲ့တဲ့ item ကို အမြဲ ပြန်ပေးနေပါတယ် (FIFO အစား LIFO ဖြစ်နေပါတယ်):
Line 6 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
ဒီ code က ဘာကို print ထုတ်မလဲ။
LinkedQueue q = new LinkedQueue();
q.enqueue("1");
q.enqueue("2");
q.enqueue("3");
System.out.println(q.dequeue());
q.enqueue("4");
System.out.println(q.peek());
System.out.println(q.dequeue());
System.out.println(q.size());Output ကို အတိအကျ ရိုက်ထည့်ပါ:
ဒီ code က ဘာကို print ထုတ်မလဲ။
LinkedQueue q = new LinkedQueue();
q.enqueue("A");
q.enqueue("B");
q.enqueue("C");
while (!q.isEmpty()) {
System.out.println(q.dequeue());
}
System.out.println(q.isEmpty());Output ကို အတိအကျ ရိုက်ထည့်ပါ:
Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- တည်ဆောက်ပြီး အလုပ်လုပ်ခိုင်းခြင်း:
LinkedQueueတစ်ခု ဖန်တီးပါ၊ ဝယ်သူ နာမည် 5 ခုကို enqueue လုပ်ပါ၊ ပြီးရင် တစ်ခုချင်း dequeue လုပ်ပြီး print ထုတ်ပါ။ FIFO အစဉ်အတိုင်း ထွက်လာလား စစ်ပါ။ - ဗလာ queue မှာ ဘေးကင်းမှု: Item 2 ခုကို enqueue လုပ်ပါ၊ item 2 ခုကို dequeue လုပ်ပါ၊ ပြီးရင် နောက်တစ်ခါ dequeue လုပ်ကြည့်ပါ။
dequeue()က null ကို ပြန်ပေးပြီးisEmpty()က true ကို ပြန်ပေးလား စစ်ပါ။ ပြီးရင် item အသစ် တစ်ခုကို enqueue လုပ်ပြီး queue က ပြန် မှန်မှန်ကန်ကန် အလုပ်လုပ်လား စစ်ပါ။ - java.util.LinkedList နဲ့ နှိုင်းယှဉ်ခြင်း: ကိုယ့်
LinkedQueueနဲ့java.util.LinkedList<String>(addနဲ့pollကို သုံးပြီး) နှစ်ခုလုံးပေါ်မှာ operation 10 ခု အတူတူ လုပ်ပါ။ ရလဒ်တွေ အတူတူ ဖြစ်လား စစ်ပါ။
Extension (တိုးချဲ့ အဆင့်)
- Array ကို အခြေခံတဲ့ queue: ပုံသေ capacity (သိမ်းနိုင်တဲ့ အများဆုံး ပမာဏ) ရှိတဲ့
String[]array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) ကို သုံးပြီး queue တစ်ခု ရေးပါ။frontနဲ့rearindex (နေရာအမှတ်) တွေက modulo (စားလို့ ကျန်တဲ့ အကြွင်းကို ရှာတဲ့%) ကို သုံးပြီး array ရဲ့ အဆုံးရောက်ရင် အစကို ပြန်လှည့်လာတဲ့ circular (စက်ဝိုင်းပုံ) နည်းကို သုံးပါ။ Linked ပုံစံနဲ့ နှိုင်းယှဉ်ပါ။ - Task scheduler (အလုပ်တွေကို အလှည့်ကျ စီစဉ်ပေးတဲ့ program): ရိုးရှင်းတဲ့ round-robin task scheduler တစ်ခု တည်ဆောက်ပါ။ Task (အလုပ်) 4 ခုကို enqueue လုပ်ပါ။ အလှည့်တိုင်းမှာ task တစ်ခုကို dequeue လုပ်ပါ၊ “execute” လုပ်ပါ (သူ့ နာမည်ကို print ထုတ်ပါ)၊ task က မပြီးသေးရင် (ကျန်တဲ့ အချိန်ကို မှတ်ထားပါ) ပြန် enqueue လုပ်ပါ။ Task တစ်ခုစီက အချိန် ယူနစ် 3 ခုနဲ့ စပြီး အလှည့် တစ်ခါမှာ 1 ခု လျော့ပါတယ်။
Challenge (စိန်ခေါ်မှု အဆင့်)
- Priority queue (ဦးစားပေး အဆင့် မြင့်တာ အရင်ထွက်တဲ့ queue): Item တစ်ခုစီမှာ integer (ကိန်းပြည့်) priority (ဦးစားပေး အဆင့်) တစ်ခု ပါအောင်
LinkedQueueကို ပြင်ပါ။enqueueက item ကို priority ပေါ် မူတည်ပြီး မှန်ကန်တဲ့ နေရာမှာ ထည့်ပါတယ် (priority မြင့်လေ front နဲ့ နီးလေ)။dequeueကတော့ front ကနေပဲ ဆက် ဖယ်ထုတ်ပါတယ်။ Priority အမျိုးမျိုး ရှိတဲ့ task တွေနဲ့ စမ်းပါ။ - Queue နှစ်ခုနဲ့ stack တည်ဆောက်ခြင်း:
LinkedQueueinstance (class တစ်ခုကနေ ဖန်တီးထားတဲ့ object) နှစ်ခုကိုပဲ သုံးပြီး stack တစ်ခု ရေးပါ (array တွေ ဒါမှမဟုတ် linked list တွေကို တိုက်ရိုက် မသုံးရပါ)။ Push နဲ့ pop က LIFO အစဉ်ကို ထိန်းထားရပါမယ်။ အကြံပြုချက်: push လုပ်တိုင်း ဗလာ queue ထဲကို enqueue လုပ်ပါ၊ ပြီးရင် နောက် queue ထဲက item အားလုံးကို ဒီ queue ထဲကို ရွှေ့ပါ။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Linked Lists: Node class နဲ့ အခြေခံ operation တွေ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Queues: Queue ADT ကို သုံးခြင်း (B2.2.4)
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Stacks from Scratch (Stack ကို အစကနေ ကိုယ်တိုင် တည်ဆောက်ခြင်း): LIFO နဲ့ အလုပ်လုပ်တဲ့ အတွဲဖက်ပါ၊ သူ့ကိုလည်း node တွေနဲ့ တည်ဆောက်ပါတယ်
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Binary Search Trees (ဘယ်ဘက် ငယ်၊ ညာဘက် ကြီးတဲ့ binary tree များ): O(log n) နဲ့ ရှာနိုင်တဲ့ hierarchical (အထက်အောက် အဆင့်ဆင့် ဖွဲ့ထားတဲ့) data structure (ဒေတာ သိမ်းဆည်းပုံ)