Stacks from Scratch (Stack ကို အစကနေ ကိုယ်တိုင် တည်ဆောက်ခြင်း)

B4.1.1 (HL): Explain the properties and purpose of ADTs in programming. Implement a stack as an ADT using linked list nodes.
မြန်မာလို: programming မှာ ADT (abstract data type: operation တွေနဲ့ သတ်မှတ်တဲ့ ဒေတာ အမျိုးအစား) တွေရဲ့ ဂုဏ်သတ္တိတွေနဲ့ ရည်ရွယ်ချက်ကို ရှင်းပြနိုင်ရပါမယ်။ Linked list (node တွေ ချိတ်ဆက်ထားတဲ့ list) ရဲ့ node (ဒေတာ သိမ်းထားတဲ့ အကွက်) တွေကို သုံးပြီး stack (အပေါ်ကနေပဲ ထည့်၊ ထုတ်တဲ့ အထပ်) ကို ADT တစ်ခုအဖြစ် ကိုယ်တိုင် ရေးနိုင်ရပါမယ်။

ဒီစာမျက်နှာက HL အတွက်ပဲ ဖြစ်ပါတယ်။ SL (Standard Level) နဲ့ HL (Higher Level) ဆိုတာ IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) သင်တန်းရဲ့ အဆင့်နှစ်ဆင့်ဖြစ်ပြီး HL အပိုင်းတွေက ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အပိုင်းတွေပါ။


အဓိက အယူအဆများ

Stacks စာမျက်နှာမှာ Java မှာ အသင့်ပါတဲ့ Stack class (object တွေ ဖန်တီးဖို့ ပုံစံခွက်) ကို သုံး တတ်အောင် လေ့လာခဲ့ပါတယ်: push (stack ရဲ့ အပေါ်ဆုံးမှာ ထည့်ခြင်း)၊ pop (stack ရဲ့ အပေါ်ဆုံးကနေ ဖယ်ထုတ်ခြင်း) နဲ့ peek (stack ရဲ့ အပေါ်ဆုံးက တန်ဖိုးကို မဖယ်ဘဲ ကြည့်ခြင်း) ကို အထဲမှာ ဘယ်လို အလုပ်လုပ်လဲ မစဉ်းစားဘဲ ခေါ်သုံးခဲ့တာပါ။ ဒီစာမျက်နှာမှာတော့ linked list node တွေကို သုံးပြီး stack တစ်ခုကို အစကနေ ကိုယ်တိုင် တည်ဆောက် မှာ ဖြစ်ပြီး implementation (အထဲမှာ တကယ် အလုပ်လုပ်အောင် ရေးထားတဲ့ code) ရဲ့ line တိုင်းကို နားလည်အောင် လေ့လာပါမယ်။

သုံးခြင်းနဲ့ တည်ဆောက်ခြင်း

အချက် သုံးခြင်း (B2.2.3) တည်ဆောက်ခြင်း (B4.1.1)
Code Stack<String> s = new Stack<>(); ကိုယ်ပိုင် LinkedStack class ကို ရေးတယ်
အာရုံစိုက်တဲ့ အချက် ဘယ် operation (လုပ်ဆောင်ချက်) တွေ သုံးလို့ရလဲ Operation တွေ အထဲမှာ ဘယ်လို အလုပ်လုပ်လဲ
သိရမယ့် အရာ Interface (class တစ်ခု implement လုပ်ရမယ့် method စာရင်း) ပဲ Interface + implementation
Node class Java library (အသင့်ရေးထားတဲ့ code အစု) ထဲမှာ ဖုံးထားတယ် ကိုယ်တိုင် ရေးရတယ်

Stack ရဲ့ Operation များကို ပြန်နွှေးခြင်း

Stack က LIFO (Last In, First Out: နောက်ဆုံးဝင်တာ အရင်ထွက်) စည်းမျဉ်းအတိုင်း အလုပ်လုပ်ပါတယ်:

Operation ဖော်ပြချက် ကြာချိန်
push(item) item ကို အပေါ်ဆုံးမှာ ထည့်တယ် O(1) (ကြာချိန် ပုံသေ)
pop() အပေါ်ဆုံးက item (အချက်) ကို ဖယ်ထုတ်ပြီး ပြန်ပေးတယ် O(1)
peek() အပေါ်ဆုံးက item ကို မဖယ်ဘဲ ကြည့်တယ် O(1)
isEmpty() Stack ထဲမှာ element (အစုထဲက အချက်) တစ်ခုမှ မရှိဘူးလား စစ်တယ် O(1)
size() Element အရေအတွက်ကို ပြန်ပေးတယ် O(1)

Linked List ကို ဘာကြောင့် သုံးသလဲ

Linked list နဲ့ တည်ဆောက်ထားတဲ့ stack မှာ ပုံသေ capacity (သိမ်းနိုင်တဲ့ အများဆုံး ပမာဏ) မရှိပါဘူး: လိုသလို ကြီးလာ၊ သေးသွားနိုင်ပါတယ်။ push တစ်ခါစီက node အသစ် တစ်ခု ဖန်တီးပြီး pop တစ်ခါစီက node တစ်ခုကို ဖယ်ထုတ်ပါတယ်။ Stack ရဲ့ အပေါ်ဆုံး (top) က linked list ရဲ့ head (list ရဲ့ ရှေ့ဆုံး node) ဖြစ်လို့ operation အားလုံးက element တွေကို နေရာ ရွှေ့စရာ မလိုဘဲ O(1) ဖြစ်ပါတယ်။

top က Blue ကို ညွှန်းပါတယ်။ Blue က stack ရဲ့ အပေါ်ဆုံး node ဖြစ်ပြီး linked list ရဲ့ head လည်း ဖြစ်ပါတယ်။ Blue ရဲ့ next က Green ကို ညွှန်းပါတယ်၊ Green ရဲ့ next က Red ကို ညွှန်းပါတယ်၊ Red ရဲ့ next က null ပါ။ Red ကို အရင်ဆုံး push လုပ်ခဲ့လို့ နောက်ဆုံးမှ pop လုပ်ပါမယ်။ Blue Green Red null None top top of the stack is the head of the list pushed first, popped last

ပုံထဲက English စာတွေရဲ့ အဓိပ္ပာယ်: “top of the stack is the head of the list” က stack ရဲ့ အပေါ်ဆုံးက list ရဲ့ head ဖြစ်တယ်၊ “pushed first, popped last” က အရင်ဆုံး push လုပ်ခဲ့ပြီး နောက်ဆုံးမှ pop လုပ်မယ့် node လို့ အဓိပ္ပာယ်ရပါတယ်။ အောက်ဆုံးက null (ဘာ object ကိုမှ မညွှန်းတဲ့ တန်ဖိုး) က list ရဲ့ အဆုံးကို ပြပါတယ် (Python မှာ None ပါ)။

Array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) ကို အခြေခံတဲ့ stack လည်း ရေးလို့ ရပါတယ်၊ ဒါပေမယ့် capacity ကို အစကတည်းက ရွေးထားရပါတယ်။ Array ပြည့်သွားရင် ပိုကြီးတဲ့ array အသစ် တစ်ခု ဖန်တီးပြီး element အားလုံးကို copy ကူးရပါတယ်: ဒါက အချိန် ကုန်တဲ့ operation ဖြစ်ပြီး linked list မှာတော့ ဒီလို လုပ်စရာ လုံးဝ မလိုပါဘူး။


အဆင့်ဆင့် ရှင်းပြထားတဲ့ ဥပမာများ

ဥပမာ 1: LinkedStack ရဲ့ Implementation

public class LinkedStack {
    private Node top;    // head of the linked list = top of stack
    private int count;

    public LinkedStack() {
        top = null;
        count = 0;
    }

    // Push: add to the top (front of linked list)
    public void push(String item) {
        Node newNode = new Node(item);
        newNode.next = top;
        top = newNode;
        count++;
    }

    // Pop: remove and return from the top
    public String pop() {
        if (top == null) {
            System.out.println("Stack is empty");
            return null;
        }
        String data = top.data;
        top = top.next;
        count--;
        return data;
    }

    // Peek: view top without removing
    public String peek() {
        if (top == null) {
            System.out.println("Stack is empty");
            return null;
        }
        return top.data;
    }

    public boolean isEmpty() {
        return top == null;
    }

    public int size() {
        return count;
    }

    public void printStack() {
        System.out.print("TOP -> ");
        Node current = top;
        while (current != null) {
            System.out.print(current.data + " -> ");
            current = current.next;
        }
        System.out.println("null");
    }

    public static void main(String[] args) {
        LinkedStack stack = new LinkedStack();
        stack.push("Red");
        stack.push("Green");
        stack.push("Blue");

        stack.printStack();
        System.out.println("Peek: " + stack.peek());
        System.out.println("Size: " + stack.size());

        System.out.println("Pop: " + stack.pop());
        System.out.println("Pop: " + stack.pop());
        stack.printStack();
        System.out.println("Size: " + stack.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 LinkedStack():
    def __init__(self):
        self._top = None    # head of the linked list = top of stack
        self._count = 0     # the leading underscore marks these as private (IB convention)

    # Push: add to the top (front of linked list)
    def push(self, item):
        new_node = Node(item)
        new_node.next = self._top
        self._top = new_node
        self._count = self._count + 1

    # Pop: remove and return from the top
    def pop(self):
        if self._top == None:
            print("Stack is empty")
            return None
        data = self._top.data
        self._top = self._top.next
        self._count = self._count - 1
        return data

    # Peek: view top without removing
    def peek(self):
        if self._top == None:
            print("Stack is empty")
            return None
        return self._top.data

    def isEmpty(self):
        return self._top == None

    def size(self):
        return self._count

    def print_stack(self):
        print("TOP -> ", end="")
        current = self._top
        while current != None:
            print(current.data + " -> ", end="")
            current = current.next
        print("null")    # printed as text -- it marks the end of the chain

stack = LinkedStack()
stack.push("Red")
stack.push("Green")
stack.push("Blue")

stack.print_stack()
print("Peek:", stack.peek())
print("Size:", stack.size())

print("Pop:", stack.pop())
print("Pop:", stack.pop())
stack.print_stack()
print("Size:", stack.size())

Output (program က ထုတ်ပြတဲ့ ရလဒ်):

TOP -> Blue -> Green -> Red -> null
Peek: Blue
Size: 3
Pop: Blue
Pop: Green
TOP -> Red -> null
Size: 1

သတိပြုကြည့်ပါ: push က singly linked list (တစ်ဘက်တည်း ချိတ်ဆက်ထားတဲ့ linked list) ရဲ့ addToFront နဲ့ အတူတူပါပဲ။ pop က head ကို ဖယ်ထုတ်ပြီး သူ့ ဒေတာကို ပြန်ပေးပါတယ်။ နှစ်ခုလုံး O(1) ဖြစ်ပြီး traversal (node ဒါမှမဟုတ် element တိုင်းကို အစဉ်တကျ သွားကြည့်ခြင်း) မလိုပါဘူး။

push("Blue"): Blue ကို သိမ်းထားတဲ့ node အသစ် တစ်ခုကို ဖန်တီးထားပါပြီ။ သူ့ next က အခု top ညွှန်းနေတဲ့ node ဖြစ်တဲ့ Green ကို ညွှန်းပါတယ်။ top ကတော့ မပြောင်းသေးပါဘူး။ Blue Green Red null None newNode new_node top 1 newNode.next = top; new_node.next = self._top top က အခု Blue ကို ညွှန်းလို့ Blue က stack ရဲ့ အပေါ်ဆုံး ဖြစ်သွားပါတယ်: Blue၊ Green၊ Red။ Blue Green Red null None newNode new_node top 2 top = newNode; self._top = new_node pop(): return လုပ်ဖို့ Blue ရဲ့ တန်ဖိုးကို သိမ်းထားပြီး top က Blue ရဲ့ နောက် node ဖြစ်တဲ့ Green ဆီ ရွှေ့သွားပါတယ်။ Blue ကို ဘာကမှ မညွှန်းတော့ပါဘူး (မျဉ်းပြတ်နဲ့ ပြထားပါတယ်)။ Stack က Green၊ Red ဖြစ်ပါတယ်။ Blue Green Red null None returns Blue top 3 top = top.next; self._top = self._top.next

Green၊ Red ပါတဲ့ stack ပေါ်ကို push("Blue") လုပ်ပြီး နောက်မှာ pop() လုပ်ပုံပါ။ အဆင့်တိုင်းမှာ အရောင် ထင်းထားတဲ့ မြှားက အဲဒီ line က ပြောင်းလိုက်တဲ့ reference (object ရှိရာ memory နေရာကို ညွှန်းတဲ့ တန်ဖိုး) ပါ။

ပုံထဲက “returns Blue” က Blue ကို ပြန်ပေးတယ်လို့ အဓိပ္ပာယ်ရပါတယ်။

ဥပမာ 2: ကွင်းစ ကွင်းပိတ် ကိုက်မကိုက် စစ်ခြင်း

Stack ကို အသုံးချတဲ့ နာမည်ကြီး ဥပမာ တစ်ခုပါ: ကွင်းစ ကွင်းပိတ်တွေ balanced (အစုံညီ ကိုက်ညီ) ဖြစ်မဖြစ် စစ်တာပါ။

public class BracketChecker {
    public static boolean isBalanced(String expression) {
        LinkedStack stack = new LinkedStack();

        for (int i = 0; i < expression.length(); i++) {
            char ch = expression.charAt(i);

            if (ch == '(' || ch == '[' || ch == '{') {
                stack.push(String.valueOf(ch));
            } else if (ch == ')' || ch == ']' || ch == '}') {
                if (stack.isEmpty()) {
                    return false;  // closing bracket with no opener
                }
                String opener = stack.pop();
                if (!matches(opener.charAt(0), ch)) {
                    return false;  // mismatched pair
                }
            }
        }
        return stack.isEmpty();  // true if all openers were matched
    }

    private static boolean matches(char open, char close) {
        return (open == '(' && close == ')')
            || (open == '[' && close == ']')
            || (open == '{' && close == '}');
    }

    public static void main(String[] args) {
        System.out.println(isBalanced("((a + b) * c)"));
        System.out.println(isBalanced("{[()]}"));
        System.out.println(isBalanced("(a + b]"));
        System.out.println(isBalanced("((())"));
    }
}
# Python has no char type -- each character is just a one-letter string
def is_balanced(expression):
    stack = LinkedStack()

    for i in range(len(expression)):
        ch = expression[i]

        if ch == "(" or ch == "[" or ch == "{":
            stack.push(ch)
        elif ch == ")" or ch == "]" or ch == "}":
            if stack.isEmpty():
                return False    # closing bracket with no opener
            opener = stack.pop()
            if matches(opener, ch) == False:
                return False    # mismatched pair
    return stack.isEmpty()      # True if all openers were matched

def matches(opener, closer):
    return (opener == "(" and closer == ")") \
        or (opener == "[" and closer == "]") \
        or (opener == "{" and closer == "}")

# Python prints booleans capitalised (True/False) -- Java prints true/false
print(is_balanced("((a + b) * c)"))
print(is_balanced("{[()]}"))
print(is_balanced("(a + b]"))
print(is_balanced("((())"))

Output:

true
true
false
false

ကွင်းစ တစ်ခုစီကို stack ပေါ်ကို push လုပ်ပါတယ်။ ကွင်းပိတ် တစ်ခုစီက နောက်ဆုံး ထည့်ခဲ့တဲ့ ကွင်းစကို pop လုပ်ပြီး နှစ်ခု ကိုက်မကိုက် စစ်ပါတယ်။ အဆုံးမှာ stack ဗလာ ဖြစ်နေရင် ကွင်းစ တိုင်းက သူ့ ကွင်းပိတ်နဲ့ ကိုက်ညီခဲ့ပါတယ်။

ဥပမာ 3: String (စာသား) ကို ပြောင်းပြန်လှန်ခြင်း

Stack က LIFO ဖြစ်လို့ character (စာလုံး ဒါမှမဟုတ် သင်္ကေတ) တွေကို push လုပ်ပြီး ပြန် pop လုပ်ရင် ပြောင်းပြန် အစဉ်ကို ရပါတယ်။

public static String reverse(String input) {
    LinkedStack stack = new LinkedStack();
    for (int i = 0; i < input.length(); i++) {
        stack.push(String.valueOf(input.charAt(i)));
    }
    String result = "";
    while (!stack.isEmpty()) {
        result += stack.pop();
    }
    return result;
}

// reverse("HELLO") returns "OLLEH"
def reverse(text):    # "text", not "input" -- input is a built-in function in Python
    stack = LinkedStack()
    for i in range(len(text)):
        stack.push(text[i])
    result = ""
    while stack.isEmpty() == False:
        result = result + stack.pop()
    return result

# reverse("HELLO") returns "OLLEH"

Quick Check (အမြန် စစ်ဆေးမေးခွန်း)

Q1. Linked list နဲ့ တည်ဆောက်ထားတဲ့ stack မှာ ဘယ် node က stack ရဲ့ အပေါ်ဆုံး (top) ကို ကိုယ်စားပြုသလဲ။

Q2. Linked stack ရဲ့ push operation က linked list ရဲ့ ဘယ် operation နဲ့ အတူတူ ဖြစ်သလဲ။

Q3. Array ကို အခြေခံတဲ့ stack နဲ့ ယှဉ်ရင် linked list stack မှာ ဘာ အားသာချက် ရှိသလဲ။

Q4. Stack ဗလာ ဖြစ်နေရင် pop() က ဘာလုပ်သင့်သလဲ။

Q5. Linked stack မှာ push၊ pop နဲ့ peek ရဲ့ time complexity (input ကြီးလာရင် ကြာချိန် တိုးပုံ) က ဘာလဲ။


Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)

Operation တစ်ခုစီ ပြီးတိုင်း stack ရဲ့ အခြေအနေကို trace (တစ်ဆင့်ချင်း လိုက်ပြီး မှတ်) လုပ်ပါ။

LinkedStack s = new LinkedStack();
s.push("A");
s.push("B");
s.push("C");
s.pop();
s.push("D");
s.pop();
s = LinkedStack()
s.push("A")
s.push("B")
s.push("C")
s.pop()
s.push("D")
s.pop()
လုပ်ပြီးတဲ့ operationtop (peek)Stack (အပေါ်ကနေ အောက်)size()
push("A") A 1
push("B") 2
push("C") C, B, A
pop() က C ကို ပြန်ပေး 2
push("D") D, B, A 3
pop() က D ကို ပြန်ပေး

Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)

Linked stack အတွက် push method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) ကို ပြီးအောင် ဖြည့်ပါ။

Stack ရဲ့ အပေါ်ဆုံးမှာ item တစ်ခု ထည့်ဖို့ ကွက်လပ်တွေကို ဖြည့်ပါ:

public void push(String item) {
    Node newNode = new (item);
    newNode. = top;
     = newNode;
    count++;
}

pop method ကို ပြီးအောင် ဖြည့်ပါ။

အပေါ်ဆုံး item ကို ဖယ်ထုတ်ပြီး ပြန်ပေးဖို့ ကွက်လပ်တွေကို ဖြည့်ပါ:

public String pop() {
    if (top == null) {
        return null;
    }
    String data = top.;
    top = top.;
    --;
    return data;
}

Spot the Error (အမှား ရှာခြင်း)

ဒီ push method က stack ကို print ထုတ်တဲ့အခါ infinite loop (ဘယ်တော့မှ မရပ်တဲ့ loop) ဖြစ်စေပါတယ်:

1public void push(String item) { 2 Node newNode = new Node(item); 3 count++; 4 top = newNode; 5 newNode.next = top; 6}

မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:


ဒီ pop method က မှားတဲ့ item ကို ပြန်ပေးနေပါတယ် (အပေါ်ဆုံး item အစား ဒုတိယ item ကို ပြန်ပေးပါတယ်):

1public String pop() { 2 if (top == null) { 3 return null; 4 } 5 top = top.next; 6 String data = top.data; 7 count--; 8 return data; 9}

မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:


Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)

ဒီ code က ဘာကို print ထုတ်မလဲ။

LinkedStack s = new LinkedStack();
s.push("10");
s.push("20");
s.push("30");
System.out.println(s.pop());
s.push("40");
System.out.println(s.peek());
System.out.println(s.pop());
System.out.println(s.pop());

Output ကို အတိအကျ ရိုက်ထည့်ပါ:


ဒီ code က ဘာကို print ထုတ်မလဲ။

LinkedStack s = new LinkedStack();
String word = "HELLO";
for (int i = 0; i < word.length(); i++) {
    s.push(String.valueOf(word.charAt(i)));
}
String result = "";
while (!s.isEmpty()) {
    result += s.pop();
}
System.out.println(result);

Output ကို အတိအကျ ရိုက်ထည့်ပါ:


Practice Exercises (လေ့ကျင့်ခန်းများ)

Core (အခြေခံ အဆင့်)

  1. တည်ဆောက်ပြီး စမ်းသပ်ခြင်း: LinkedStack တစ်ခု ဖန်တီးပါ၊ item 5 ခုကို push လုပ်ပါ၊ stack ကို print ထုတ်ပါ၊ item 3 ခုကို pop လုပ်ပါ (pop လုပ်လိုက်တဲ့ တန်ဖိုး တစ်ခုစီကို print ထုတ်ပါ)၊ ပြီးရင် ကျန်တဲ့ stack ကို print ထုတ်ပါ။ LIFO အစဉ် မှန်မမှန် စစ်ပါ။
  2. isEmpty နဲ့ size: Item 3 ခုကို push လုပ်ပြီး isEmpty() (false ဖြစ်ရပါမယ်) နဲ့ size() (3 ဖြစ်ရပါမယ်) ကို စစ်ပါ။ Item အားလုံးကို pop လုပ်ပါ။ isEmpty() (true ဖြစ်ရပါမယ်) နဲ့ size() (0 ဖြစ်ရပါမယ်) ကို စစ်ပါ။ ဗလာ ဖြစ်နေတဲ့ stack ပေါ်မှာ pop() ကို စမ်းပြီး null ကို ပြန်ပေးလား စစ်ပါ။
  3. java.util.Stack နဲ့ နှိုင်းယှဉ်ခြင်း: ကိုယ့် LinkedStack နဲ့ java.util.Stack<String> နှစ်ခုလုံးပေါ်မှာ operation 10 ခု အတူတူ လုပ်တဲ့ program တစ်ခု ရေးပါ။ Operation တိုင်းအတွက် နှစ်ခုလုံးက ရလဒ် အတူတူ ထုတ်ပေးလား စစ်ပါ။

Extension (တိုးချဲ့ အဆင့်)

  1. Array ကို အခြေခံတဲ့ stack: ပုံသေ capacity ရှိတဲ့ String[] array ကို သုံးပြီး stack တစ်ခု ရေးပါ။ topIndex variable (တန်ဖိုး သိမ်းထားတဲ့ နာမည်ပေးထားတဲ့ နေရာ) တစ်ခုကို ထိန်းထားပါ။ Linked ပုံစံနဲ့ နှိုင်းယှဉ်ပါ: array ပြည့်သွားရင် ဘာဖြစ်မလဲ။ Trade-off (တစ်ခု ရဖို့ တစ်ခု အလျှော့ပေးရတာ) တွေက ဘာတွေလဲ။
  2. Undo စနစ်: ရိုးရှင်းတဲ့ text editor (စာ ရေးပြီး ပြင်တဲ့ program) အတွက် undo (လုပ်ခဲ့တာကို ပြန်ဖျက်ခြင်း) စနစ် တစ်ခု တည်ဆောက်ပါ။ ပြင်ဆင်မှု (edit) တစ်ခုစီကို (လုပ်ခဲ့တာကို ဖော်ပြတဲ့ String တစ်ခုအဖြစ်) stack ပေါ်ကို push လုပ်ပါ။ undo() method က နောက်ဆုံး လုပ်ခဲ့တဲ့ လုပ်ဆောင်ချက်ကို pop လုပ်ပြီး “Undoing: [action]” ကို print ထုတ်ပါတယ်။ Edit 5 ခုနဲ့ undo 3 ခါနဲ့ စမ်းပါ။

Challenge (စိန်ခေါ်မှု အဆင့်)

  1. Postfix တွက်စက်: "3 4 + 2 *" လို postfix (Reverse Polish Notation: + လို တွက်ချက်မှု သင်္ကေတကို တန်ဖိုးတွေရဲ့ နောက်မှာ ရေးတဲ့ ပုံစံ) expression (ရလဒ် တန်ဖိုးတစ်ခု တွက်ထုတ်ပေးတဲ့ code အပိုင်း) ကို တွက်ပေးတဲ့ method တစ်ခု ရေးပါ။ Space (ကွက်လပ်) တွေနဲ့ ခွဲပါ၊ ဂဏန်းတွေကို push လုပ်ပါ၊ operator (တန်ဖိုးတွေကို တွက်ချက်တဲ့ သင်္ကေတ) တစ်ခု တွေ့ရင် operand (တွက်ချက်မှုထဲက တန်ဖိုး) နှစ်ခုကို pop လုပ်ပြီး တွက်ပါ၊ ပြီးရင် ရလဒ်ကို push လုပ်ပါ။ "5 3 + 8 2 - *" နဲ့ စမ်းပါ (ရရမယ့် ရလဒ်: 48)။
  2. Min stack: push၊ pop၊ peek နဲ့ getMin (အငယ်ဆုံး element ကို ပြန်ပေးခြင်း) အားလုံးကို O(1) အချိန်နဲ့ လုပ်ပေးနိုင်တဲ့ stack တစ်ခုကို ဒီဇိုင်းဆွဲပါ။ အကြံပြုချက်: stack နှစ်ခု သုံးပါ။ တစ်ခုက ဒေတာအတွက်၊ နောက်တစ်ခုက အဆင့် တစ်ခုစီမှာ လက်ရှိ အငယ်ဆုံး တန်ဖိုးကို မှတ်ထားဖို့ပါ။

ဆက်စပ် ခေါင်းစဉ်များ

  • အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Linked Lists: Node class နဲ့ addToFront/removeHead operation တွေ
  • အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Stacks: Stack ADT ကို သုံးခြင်း (B2.2.3)
  • ဆက်စပ် ခေါင်းစဉ်: Queues from Scratch (Queue ကို အစကနေ ကိုယ်တိုင် တည်ဆောက်ခြင်း): FIFO (အရင်ဝင်တာ အရင်ထွက်) နဲ့ အလုပ်လုပ်တဲ့ အတွဲဖက်ပါ၊ သူ့ကိုလည်း node တွေနဲ့ တည်ဆောက်ပါတယ်
  • နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: Queues from Scratch: linked list node တွေကို သုံးပြီး queue (အရင်ထည့်တာ အရင်ထွက်တဲ့ တန်း) ကို တည်ဆောက်ခြင်း