เน้น ตรรกะ ล้วน — ทำไมต้อง pop ตอนไหน ทำไมต้อง push ตอนไหน · ทุกขั้นตอนของการแปลง Infix → Postfix เดินทีละตัวอักษรพร้อมเหตุผลที่ตัดสินใจ
ทุกหัวข้อมีภาพเคลื่อนไหวประกอบ · อ่าน bullet แล้วดูภาพก็พอ
topclearStack — array: top=0 · list: top=NULLemptyStack — เช็คก่อน pop ทุกครั้ง กัน UnderflowfullStack — เช็คก่อน push กัน Overflow (แบบ list ไม่ต้องมี — dynamic)push — วางของก่อน แล้ว top++pop — top-- ก่อน แล้วค่อยอ่านค่า ← สลับไม่ได้int stack[MAXSIZE]; int top;stack[top]=d; top++;top--; d=stack[top];struct node{int data; struct node *next;}; struct node *top;current->next=top; top=current;top=top->next; free();push() กับ pop() ว่างไว้void push(int num)
{
if(fullStack()){
printf("
STACK FULL
");
}
else
{
stack[top] = num; // วางที่ช่อง top
top = top + 1; // แล้วเลื่อน top ขึ้น
}
}int pop()
{
int d;
if(emptyStack()){
printf("
STACK EMPTY
");
return 0;
}
else
{
top = top - 1; // ลด top ก่อน
d = stack[top]; // แล้วค่อยอ่านค่า
stack[top] = '\0'; // เคลียร์ช่อง (ให้เมนู 3 แสดงผลถูก)
return d;
}
}stack[top] ก่อนลด top จะได้ช่องว่างที่ยังไม่มีข้อมูลemptyStack() เขียนว่า top <= 0 — ต่างจากสไลด์หน้า 19 ที่เขียน top <= -1clearStack() ตั้ง top = 0 (top = จำนวนสมาชิก = ช่องว่างถัดไป) → ว่างเมื่อ top = 0 · ถ้าใช้แบบสไลด์ต้องเริ่ม top = −1 แทน · ยึดตามไฟล์ที่ต้องส่งหัวใจของบทนี้ · พิมพ์นิพจน์เองได้ — ทุก step บอกเหตุผลที่ตัดสินใจ push หรือ pop
| ลำดับ | Operator | ทิศทางการคำนวณ | ตัวอย่าง |
|---|---|---|---|
| สูงสุด | ( ) | ในวงเล็บก่อนเสมอ | (A+B)*C → ทำ A+B ก่อน |
| 3 | ^ | ขวา → ซ้าย | A^B^C = A^(B^C) |
| 2 | * / | ซ้าย → ขวา | A*B/C = (A*B)/C |
| ต่ำสุด | + − | ซ้าย → ขวา | A+B−C = (A+B)−C |
A−B−C กับ A^B^C ผลต่างกัน) หรือจบสตริง( ที่ไล่ไม่ออก( ไม่ได้( แล้วทิ้ง ( ไปเลย( ค้างอยู่ตอนนี้ = วงเล็บไม่สมดุล| Operator | ^ | * | / | + | − | ( | ) | \0 |
|---|---|---|---|---|---|---|---|---|
| ค่าตอนอ่านเข้ามา (Infix) | 4 | 2 | 2 | 1 | 1 | 4 | 0 | −1 |
| ค่าตอนอยู่ในสแตก | 3 | 2 | 2 | 1 | 1 | 0 | — | −1 |
( ถึงมี 2 ค่า (4 กับ 0)?( ออกได้ ต้องรอ ) มาเท่านั้น^ เป็น 4/3? เพราะ 4 <= 3 ไม่จริง → เจอ ^ ซ้อน ^ จะไม่ pop = คำนวณจากขวาไปซ้าย (right-associative) ถูกต้องตามคณิตศาสตร์* เป็น 2/2? 2 <= 2 จริง → เจอ * ซ้อน * จะ pop ตัวเก่าออกก่อน = คำนวณซ้ายไปขวา (left-associative)\0 = −1 คือ "สแตกว่าง" — ไม่มีอะไรให้ pop(A+B)*C · ไล่ทีละตัวที่อ่านเข้ามา แล้วจดว่าตอนนั้น สแตกมีอะไร กับ postfix ได้อะไรแล้ว| ตัวที่อ่านเข้ามา | Operator stack | นิพจน์ Postfix |
|---|---|---|
| ( | ( | ว่าง |
| A | ( | A |
| + | (+ | A |
| B | (+ | AB |
| ) | ว่าง | AB+ |
| * | * | AB+ |
| C | * | AB+C |
| \0 | ว่าง | AB+C* |
\0) = pop ที่เหลือทั้งหมด → ช่อง Postfix แถวนี้คือคำตอบ( กับ ) ไม่เคยโผล่ในคอลัมน์ Postfix เลยสักแถว| เจออะไร | ทำอะไร |
|---|---|
| operand A B C 1 2 | ต่อเข้า postfix ทันที — ไม่ต้องคิดอะไรเลย |
| ( | push ลงสแตกเลย |
| ) | pop ออกมาต่อ postfix เรื่อยๆ จนเจอ ( · แล้วทิ้ง ( ไป (ไม่ต่อ postfix)วงเล็บไม่เคยโผล่ใน postfix |
| operator | เทียบ precedence: pop ตัวที่มีค่า ≥ ออกก่อน แล้วค่อย push ตัวใหม่ |
| จบสตริง | pop ที่เหลือทั้งหมดออกมาต่อ postfix |
พิมพ์ลงตารางทุกช่องแล้วกดตรวจ · หรือจะร่างในกระดาษทดก่อน (ปุ่มมุมขวาล่าง / กด D)
ใช้สแตกอีกรอบ — แต่คราวนี้เก็บ ค่า ไม่ใช่ operator
- กับ / สลับแล้วผิดทันทีอ่าน bullet 6 บรรทัด แล้วดูต้นไม้ประกอบ — เข้าใจว่าทำไม 3 แบบถึงเป็นนิพจน์เดียวกัน
A+B-C — operator ตรงกลาง · คนอ่านง่าย ภาษาโปรแกรมเขียนแบบนี้AB+C- — operator ข้างหลัง · ไม่ต้องมีวงเล็บ เครื่องคำนวณรอบเดียวจบ-+ABC — operator ข้างหน้า( ) > ^ > * / > + −ท่องก่อนเข้าห้องสอบ
( = 4/0)− กับ /