Queues (အရင်ထည့်တာ အရင်ထွက်တဲ့ တန်းများ)
B2.2.4: Explain the concept of a queue as a “first in, first out” (FIFO) data structure: enqueue, dequeue, front and isEmpty, and how queue operations affect performance and memory usage.
မြန်မာလို: Queue (အရင်ထည့်တာ အရင်ထွက်တဲ့ တန်း) ကို “first in, first out” (FIFO: အရင်ဝင်တာ အရင်ထွက်) data structure (ဒေတာ သိမ်းဆည်းပုံ) တစ်ခုအဖြစ် သူ့သဘောတရားကို ရှင်းပြနိုင်ရပါမယ်။ Enqueue (queue ရဲ့ နောက်ဆုံးမှာ ထည့်ခြင်း)၊ dequeue (queue ရဲ့ ရှေ့ဆုံးကနေ ဖယ်ထုတ်ခြင်း)၊ front (ရှေ့ဆုံး item ကို မဖယ်ဘဲ ကြည့်ခြင်း) နဲ့ isEmpty (အလွတ် ဖြစ်မဖြစ် စစ်ခြင်း) တို့နဲ့ queue operation (queue ပေါ်မှာ လုပ်တဲ့ လုပ်ဆောင်ချက်) တွေက performance (စွမ်းဆောင်ရည်) နဲ့ memory (မှတ်ဉာဏ်) သုံးစွဲမှုကို ဘယ်လို သက်ရောက်လဲ ဆိုတာ ပါဝင်ပါတယ်။
အဓိက အယူအဆများ
Queue ဆိုတာ ဘာလဲ
Queue ဆိုတာ First In, First Out (FIFO) စည်းမျဉ်းကို လိုက်နာတဲ့ abstract data structure (operation တွေနဲ့ သတ်မှတ်တဲ့ data structure) တစ်ခုပါ: အရင်ဆုံး ထည့်ခဲ့တဲ့ item (အချက်) ကို အရင်ဆုံး ဖယ်ထုတ်ပါတယ်။ Item တွေကို back (နောက်ဆုံး၊ rear လို့လည်း ခေါ်ပါတယ်) မှာ ထည့်ပြီး front (ရှေ့ဆုံး) ကနေ ဖယ်ထုတ်ပါတယ်။
လက်မှတ် ရောင်းတဲ့ ကောင်တာမှာ တန်းစီနေတာကို စဉ်းစားကြည့်ပါ: တန်းထဲမှာ ရှေ့ဆုံးက လူကို အရင်ဆုံး ဝန်ဆောင်မှု ပေးပါတယ်။
Queue Operation များ (queue ပေါ်မှာ လုပ်တဲ့ လုပ်ဆောင်ချက်များ)
| Operation | ဘာလုပ်လဲ | Java method |
|---|---|---|
| Enqueue | Back မှာ item တစ်ခု ထည့်ပါတယ် | queue.add(value) |
| Dequeue | Front item ကို ဖယ်ထုတ်ပြီး ပြန်ပေးပါတယ် | queue.poll() |
| Front / Peek | Front item ကို မဖယ်ဘဲ ကြည့်ပါတယ် | queue.peek() |
| isEmpty | Queue ထဲမှာ element (အစုထဲက အချက်) တစ်ခုမှ မရှိဘူးလား စစ်ပါတယ် | queue.isEmpty() |
| Size | Element အရေအတွက်ကို ယူပါတယ် | queue.size() |
Queue အလွတ်မှာ poll() က null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) ကို ပြန်ပေးပါတယ်။ remove() ကတော့ exception (program run နေစဉ် ဖြစ်တဲ့ အမှား) ကို throw (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်ပါတယ်။ poll() ကို သုံးပြီး null ဟုတ်မဟုတ် စစ်ပါ၊ ဒါမှမဟုတ် isEmpty() နဲ့ အရင် စစ်ပါ။ (Python မှာ list ကို queue အဖြစ် သုံးရင် list အလွတ်ကို pop(0) လုပ်တဲ့အခါ IndexError ကို raise လုပ်ပါတယ်၊ ဒါကြောင့် list ရဲ့ အရှည်ကို အရင် စစ်ပါ။)
Java မှာ Queue ကို သုံးခြင်း
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
// Enqueue (add to back)
queue.add("Alice"); // queue: [Alice]
queue.add("Bob"); // queue: [Alice, Bob]
queue.add("Charlie"); // queue: [Alice, Bob, Charlie]
// Peek at the front (does not remove)
System.out.println(queue.peek()); // Alice
// Dequeue (remove from front)
System.out.println(queue.poll()); // Alice queue: [Bob, Charlie]
System.out.println(queue.poll()); // Bob queue: [Charlie]
// Check state
System.out.println(queue.isEmpty()); // false (Charlie is still there)
System.out.println(queue.size()); // 1
# Python has no built-in Queue class - a plain list is the usual
# implementation choice: append() adds at the back, pop(0) removes the front.
queue = []
# Enqueue (add to back)
queue.append("Alice") # queue: [Alice]
queue.append("Bob") # queue: [Alice, Bob]
queue.append("Charlie") # queue: [Alice, Bob, Charlie]
# Peek at the front (does not remove)
print(queue[0]) # Alice
# Dequeue (remove from front)
print(queue.pop(0)) # Alice queue: [Bob, Charlie]
print(queue.pop(0)) # Bob queue: [Charlie]
# Check state
print(len(queue) == 0) # False (Charlie is still there) - Python capitalises booleans
print(len(queue)) # 1
Java မှာ Queue က interface (class တစ်ခု implement လုပ်ရမယ့် method စာရင်း) တစ်ခုပါ။ LinkedList ကို implementation (interface ကို တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ class) အဖြစ် သုံးပြီး ဖန်တီးပါတယ်: Queue<Type> q = new LinkedList<>()။ ဒီ site မှာ ဒီပုံစံကိုပဲ သုံးပါတယ်။
Queue Operation တွေကို ပုံနဲ့ ကြည့်ခြင်း
Item တွေက back ကနေ ဝင်ပြီး (item အသစ် တစ်ခုစီကို အစိမ်းရောင်နဲ့ ပြထားပါတယ်) front ကနေ ထွက်ပါတယ်။ Queue က item တွေ ရောက်လာတဲ့ အစဉ်ကို ထိန်းထားပါတယ်။ ပုံထဲက front ဆိုတာ ရှေ့ဆုံး၊ back ဆိုတာ နောက်ဆုံး၊ returns ဆိုတာ ပြန်ပေးတယ်လို့ ဆိုလိုပါတယ်။
Stack (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်) နဲ့ Queue နှိုင်းယှဉ်ချက်
| အချက် | Stack (LIFO: နောက်ဆုံးဝင်တာ အရင်ထွက်) | Queue (FIFO) |
|---|---|---|
| ယူသုံးတဲ့ နေရာ | Top (အပေါ်ဆုံး) မှာပဲ | Front (ဖယ်ထုတ်) နဲ့ Back (ထည့်) |
| ထည့်တဲ့ operation | Push (top မှာ) | Enqueue (back မှာ) |
| ဖယ်ထုတ်တဲ့ operation | Pop (top ကနေ) | Dequeue (front ကနေ) |
| အစဉ် | နောက်ဆုံး ထည့်တာ = အရင်ဆုံး ဖယ်ထုတ် | အရင်ဆုံး ထည့်တာ = အရင်ဆုံး ဖယ်ထုတ် |
| ဥပမာ | ပန်းကန်ပြား အထပ် | ကောင်တာမှာ တန်းစီခြင်း |
| Java class | Stack<Type> | Queue<Type> = new LinkedList<>() |
IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) စာမေးပွဲအတွက် အကြံပြုချက်: မေးခွန်းထဲမှာ “first come, first served” (အရင်ရောက် အရင်ရ) ဒါမှမဟုတ် “order of arrival” (ရောက်လာတဲ့ အစဉ်) လို့ ပါရင် queue ပါ။ “most recent first” (နောက်ဆုံးဟာ အရင်) ဒါမှမဟုတ် “undo” (လုပ်ခဲ့တာကို ပြန်ဖျက်ခြင်း) လို့ ပါရင် stack ပါ။
လက်တွေ့ အသုံးချပုံများ
Print Queue (print ထုတ်ဖို့ စောင့်နေတဲ့ document တန်း)
Printer ကို ပို့လိုက်တဲ့ document တွေကို ရောက်လာတဲ့ အစဉ်အတိုင်း လုပ်ဆောင်ပါတယ်။ အရင်ဆုံး ပို့တဲ့ document ကို အရင်ဆုံး print ထုတ်ပါတယ်။
CPU Scheduling (ဘယ် process ကို CPU အချိန် ပေးမလဲ ဆုံးဖြတ်ခြင်း)
OS (operating system: ကွန်ပျူတာကို စီမံတဲ့ အဓိက software) က CPU (ကွန်ပျူတာရဲ့ အဓိက processor) အချိန်ကို စောင့်နေတဲ့ process (run နေတဲ့ program) တွေကို စီမံဖို့ queue တွေကို သုံးပါတယ်။ FCFS (First Come, First Served: အရင်ရောက် အရင်ရ scheduling) မှာ process တွေကို queue ထဲ ထည့်ထားပြီး ရောက်လာတဲ့ အစဉ်အတိုင်း run ပါတယ်။
Message Queue များ (message တွေကို ပို့တဲ့ အစဉ်အတိုင်း တန်းစီထားတဲ့ queue)
Chat app တွေနဲ့ notification (အသိပေးချက်) စနစ်တွေက message တွေကို ပို့ခဲ့တဲ့ အစဉ်အတိုင်း ရောက်အောင် ပို့ပေးဖို့ queue တွေကို သုံးပါတယ်။
Network Buffer များ (ဆက်ပို့ဖို့ စောင့်နေတဲ့ ဒေတာကို ခဏ သိမ်းထားတဲ့ နေရာ)
Router (network တွေကြား packet ကို လမ်းကြောင်းပြတဲ့ စက်) တွေက ဝင်လာတဲ့ packet (network ပေါ် ပို့တဲ့ ဒေတာ အစိတ်အပိုင်းငယ်) တွေကို ဆက်ပို့ဖို့ စောင့်နေတုန်း queue ထဲမှာ ထားပြီး ရောက်လာတဲ့ အစဉ်အတိုင်း ပို့ပါတယ်။ (Message တစ်ခုထဲက packet တွေက မတူတဲ့ လမ်းကြောင်းတွေကနေ သွားခဲ့ရင် အစဉ်မမှန်ဘဲ ရောက်လာနိုင်ပါသေးတယ်၊ လက်ခံတဲ့ ကွန်ပျူတာက အစဉ်မှန်အောင် ပြန်စီပါတယ်။)
စာမေးပွဲ မေးခွန်းမှာ FIFO ကို တွေ့ရင် queue ကို သတိရပါ။
အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: ဖောက်သည် ဝန်ဆောင်မှု simulation (လက်တွေ့ အခြေအနေကို အတုလုပ်ပြခြင်း)
ဖောက်သည်တွေ ရောက်လာပြီး အစဉ်အတိုင်း ဝန်ဆောင်မှု ရတဲ့ လက်မှတ် ကောင်တာ တစ်ခုကို simulate လုပ်ပါ (အတုလုပ်ပြပါ)။
import java.util.LinkedList;
import java.util.Queue;
public class TicketCounter {
public static void main(String[] args) {
Queue<String> customers = new LinkedList<>();
// Customers arrive
customers.add("Alice");
customers.add("Bob");
customers.add("Charlie");
customers.add("Diana");
System.out.println("Waiting: " + customers.size()); // 4
// Serve customers in order
while (!customers.isEmpty()) {
String next = customers.poll();
System.out.println("Now serving: " + next);
}
System.out.println("All served: " + customers.isEmpty()); // true
}
}
# No class or main wrapper needed in Python - a plain list is the queue
customers = []
# Customers arrive
customers.append("Alice")
customers.append("Bob")
customers.append("Charlie")
customers.append("Diana")
print("Waiting:", len(customers)) # 4
# Serve customers in order
while len(customers) > 0:
# next is a built-in name in Python, so we call it next_customer
next_customer = customers.pop(0) # pop(0) removes the front
print("Now serving:", next_customer)
print("All served:", len(customers) == 0) # True - Python capitalises booleans
Output (program က ထုတ်ပြတဲ့ ရလဒ်):
Waiting: 4
Now serving: Alice
Now serving: Bob
Now serving: Charlie
Now serving: Diana
All served: true
ဥပမာ 2: Task Scheduler (လုပ်ရမယ့် အလုပ်တွေကို အစဉ်လိုက် လုပ်ပေးတဲ့ program)
Task (လုပ်ရမယ့် အလုပ်) တွေကို ရောက်လာတဲ့ အစဉ်အတိုင်း လုပ်ဆောင်ပါ၊ လုပ်ဆောင်နေစဉ်မှာ task အသစ်တွေ ထပ်ထည့်လို့လည်း ရပါတယ်။
public static void processJobs(Queue<String> jobs) {
while (!jobs.isEmpty()) {
String current = jobs.poll();
System.out.println("Processing: " + current);
// Simulate a task that generates a follow-up
if (current.equals("Print report")) {
jobs.add("Email report"); // new task added to the back
}
}
}
def process_jobs(jobs):
while len(jobs) > 0:
current = jobs.pop(0) # pop(0) removes the front (implementation choice)
print("Processing:", current)
# Simulate a follow-up; == compares string content (replaces .equals)
if current == "Print report":
jobs.append("Email report") # new task added to the back
ဒါက အသုံးများတဲ့ ပုံစံ တစ်ခုပါ: item တစ်ခုကို လုပ်ဆောင်ရင်း item အသစ်တွေ ပေါ်လာနိုင်ပြီး အဲဒါတွေကို queue ရဲ့ back မှာ ထည့်ပါတယ်။ Item အသစ်တွေက သူတို့ အလှည့်ကို စောင့်ရပါတယ်။
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. FIFO ဆိုတာ ဘာကို ဆိုလိုသလဲ။
Q2. X, Y, Z ကို (ဒီအစဉ်အတိုင်း) enqueue လုပ်ပါတယ်။ ပြီးရင် dequeue()၊ ပြီးရင် peek() လုပ်ပါတယ်။ peek() က ဘာကို ပြန်ပေးမလဲ။
Q3. ဘယ် အခြေအနေကို queue နဲ့ အကောင်းဆုံး ပုံဖော်နိုင်သလဲ။
Q4. Java မှာ Queue တစ်ခုကို ဘယ်လို ဖန်တီးမလဲ။
Q5. Print queue အတွက် stack က ဘာကြောင့် မသင့်တော်သလဲ။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
Operation တစ်ခုစီ ပြီးတိုင်း queue ထဲက တန်ဖိုးတွေကို trace လုပ်ပါ။
Trace: Queue ထဲက တန်ဖိုးတွေနဲ့ ပြန်ပေးတဲ့ တန်ဖိုးတွေကို မှတ်ပါ။ Queue ထဲက တန်ဖိုးတွေကို ဇယားထဲက ပုံစံအတိုင်း ရိုက်ထည့်ပါ။ -- ဆိုတာ ပြန်ပေးတဲ့ တန်ဖိုး မရှိဘူးလို့ ဆိုလိုပါတယ်။
Queue<Integer> q = new LinkedList<>();
q.add(10); // Op 1
q.add(20); // Op 2
q.add(30); // Op 3
q.poll(); // Op 4
q.add(40); // Op 5
q.poll(); // Op 6
q.peek(); // Op 7| Op ပြီးနောက် | Queue (front ကနေ back) | ပြန်ပေးတဲ့ တန်ဖိုး |
|---|---|---|
| 1 | [10] | -- |
| 2 | [10, 20] | -- |
| 3 | [10, 20, 30] | -- |
| 4 | ||
| 5 | -- | |
| 6 | ||
| 7 |
Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)
Queue ထဲက ဖောက်သည် အားလုံးကို ဝန်ဆောင်မှု ပေးတဲ့ method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) ကို ဖြည့်ပါ။
ကွက်လပ် ဖြည့်ပါ: Queue အလွတ် ဖြစ်တဲ့အထိ ဖောက်သည် တစ်ယောက်ချင်းစီကို ဝန်ဆောင်မှု ပေးပါ။
public static void serveAll(Queue<String> customers) {
while (!customers.) {
String next = customers.;
System.out.println("Serving: " + next);
}
} Spot the Error (အမှား ရှာခြင်း)
ဒီ code က item တွေကို FIFO အစဉ်နဲ့ လုပ်ဆောင်ရမှာ ဖြစ်ပေမယ့် LIFO အစဉ်နဲ့ လုပ်ဆောင်နေပါတယ်။
Bug ရှာပါ: ဒီ code က task တွေကို ထည့်ခဲ့တဲ့ အစဉ်အတိုင်း လုပ်ဆောင်ရမှာ ဖြစ်ပေမယ့် နောက်ဆုံးမှ ထည့်ခဲ့တဲ့ task ကို အရင် run နေပါတယ်။
Line 1 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)
ကြိုခန့်မှန်းပါ: ဒီ code က ဘာကို print ထုတ်မလဲ။
Queue<String> q = new LinkedList<>();
q.add("A");
q.add("B");
q.add("C");
System.out.println(q.poll());
q.add("D");
System.out.println(q.poll());
System.out.println(q.peek()); Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
-
Queue ကို အဆင့်ဆင့် လိုက်ကြည့်ခြင်း။ Queue အလွတ် တစ်ခုကနေ စပြီး ဒီ operation တွေကို လုပ်ပါ၊ operation တစ်ခုစီ ပြီးတိုင်း queue ထဲက တန်ဖိုးတွေကို ရေးပါ: enqueue(A), enqueue(B), enqueue(C), dequeue(), enqueue(D), dequeue(), peek(), dequeue()။
- Stack လား Queue လား။ အခြေအနေ တစ်ခုစီအတွက် stack နဲ့ queue ထဲက ဘယ်ဟာ ပိုသင့်တော်လဲဆိုတာ ဖော်ပြပြီး ဘာကြောင့်လဲဆိုတာ ရှင်းပြပါ:
- (a) စားသောက်ဆိုင်မှာ ဖောက်သည်တွေ မှာထားတဲ့ အစားအသောက်တွေကို လုပ်ဆောင်ခြင်း
- (b) Browser ရဲ့ back ခလုတ် history
- (c) CPU scheduling (FCFS)
- (d) Nested (တစ်ခုထဲမှာ တစ်ခု) ကွင်းတွေကို တွက်ခြင်း
- ဖောက်သည် အသစ်တွေ ရောက်လာတဲ့ ဝန်ဆောင်မှု program။ ဖောက်သည် နာမည် သုံးခုနဲ့ queue တစ်ခုကို စတင်တဲ့ program ကို ရေးပါ။ ဖောက်သည် တစ်ယောက်ကို ဝန်ဆောင်မှု ပေးပါ၊ ပြီးရင် အခုမှ ရောက်လာတဲ့ ဖောက်သည် နှစ်ယောက်ကို ထည့်ပါ၊ ပြီးရင် ကျန်တဲ့ ဖောက်သည် အားလုံးကို ဝန်ဆောင်မှု ပေးပါ။ တစ်ယောက်ကို ဝန်ဆောင်မှု ပေးတိုင်း “Now serving: [name]” ကို print ထုတ်ပြီး စောင့်နေတဲ့သူ ဘယ်နှစ်ယောက် ကျန်သေးလဲ print ထုတ်ပါ။ Program ကို မ run ခင် ဖောက်သည်တွေ ဘယ်အစဉ်နဲ့ ဝန်ဆောင်မှု ရမယ်လို့ ထင်လဲဆိုတာ ချရေးထားပါ။
Extension (တိုးချဲ့ အဆင့်)
-
ဦးစားပေးမှု simulation။ ဖောက်သည် ဝန်ဆောင်မှု program ကို ပြင်ပါ: ရိုးရိုး ဖောက်သည်တွေက queue ရဲ့ back မှာ ဝင်ရပေမယ့် VIP ဖောက်သည်တွေက position 1 (လက်ရှိ ဝန်ဆောင်မှု ရနေတဲ့သူရဲ့ နောက်) မှာ ဝင်ရပါမယ်။ VIP ကို ထည့်ဖို့ LinkedList ရဲ့
add(index, value)ကို သုံးပါ။ -
Hot potato ဂိမ်း။ “Hot potato” ဂိမ်းကို ရေးပါ: လူ n ယောက်က စက်ဝိုင်းပုံ ရပ်နေပါတယ် (queue တစ်ခုနဲ့ ပုံဖော်ပါ)။ k အထိ ရေတွက်ပြီး front က လူကို ဖယ်ထုတ်ပါ။ လူ တစ်ယောက်ပဲ ကျန်တဲ့အထိ ဆက်လုပ်ပါ။ ရေတွက်တဲ့အခါ front က လူကို k-1 ကြိမ် back ကို ပြန်ပို့ပြီး k ကြိမ်မြောက် ရေတွက်တဲ့အခါ ဖယ်ထုတ်ပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
- Queue နှစ်ခုနဲ့ stack။ Queue နှစ်ခုကို သုံးပြီး stack (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်) တစ်ခုကို ရေးပါ (Stack class အစစ်ကို သုံးခွင့် မရှိပါ)။ Push၊ pop နဲ့ peek ကို လုပ်နိုင်ရပါမယ်။ အကြံပြုချက်: queue တစ်ခုက “main” (အဓိက) သိမ်းဆည်းရာ ဖြစ်ပြီး နောက်တစ်ခုကို push ဒါမှမဟုတ် pop လုပ်နေစဉ် ခဏ သုံးပါတယ်။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: ArrayList (ကြီးလာ၊ သေးသွားနိုင်တဲ့ list): dynamic collection တွေနဲ့ Java generics (သိမ်းမယ့် ဒေတာ type ကို ထောင့်ကွင်း
< >ထဲမှာ သတ်မှတ်ပေးတဲ့ ပုံစံ) - ဆက်စပ် ခေါင်းစဉ်: Stacks (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်များ): queue နဲ့ ဆန့်ကျင်ဘက်ဖြစ်တဲ့ LIFO structure
- ဆက်စပ် ခေါင်းစဉ်: Scheduling (ဘယ် process ကို CPU အချိန် ပေးမလဲ ဆုံးဖြတ်ခြင်း): FCFS scheduling က queue ကို သုံးပါတယ်
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: ADTs: Queues from Scratch (queue ကို အစကနေ ကိုယ်တိုင် တည်ဆောက်ခြင်း)၊ HL (Higher Level: IB သင်တန်းမှာ ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အဆင့်) အတွက်ပါ: ကိုယ်ပိုင် queue ကို တည်ဆောက်ခြင်း