First In First Out : FIFO หมายถึงข้อมูลทีเ่ ข้ามาในลิสต์ก่อน จะ ถูกนาออกจากลิสต์เป็ นลาดับแรก ตัวอย่างได้แก่การยืนรอคิวเพือ่ ซือ้ ตั ๋ว Last In First Out : LIFO หมายถึงข้อมูลทีเ่ ข้ามาในลิสต์เป็ น ลาดับสุดท้าย จะถูกนาออกจากลิสต์เป็ นอันดับแรก ตัวอย่างได้แก่การนาชัน้ ของ ปิ่นโตเข้าและออกจากเถาปิ่นโต เป็ นโครงสร้างข้อมูลแบบเชิงเส้น ที่มีการใส่ข้อมูลเข้า และ นาข้อมูลออกเพียงด้านเดียว ดังนัน้ ข้อมูลทีเ่ ข้าไปอยูใ่ น stack ก่อนจะออกจาก stack หลังข้อมูลทีเ่ ข้าไปใน stack ทีหลัง นันคื ่ อ การ "เข้าทีหลังแต่ออกก่อน" (Last In First Out : LIFO) ปฏิบตั กิ ารพืน ้ ฐานของStackได้แก่ push คือการนาข้อมูลเก็บในStack และ pop คือ การนาข้อมูลออกจากStack ซึง่ ทัง้ สองกระบวนการ จะกระทาทีส่ ว่ นบนสุดของStack เสมอ โดยปกติแล้วมักกาหนดให้มตี วั ชี้ส่วนบนสุดของStack เรียกว่า top ส่วน ปฏิบตั กิ ารอื่น ๆ เป็ นปฏิบตั กิ ารทีเ่ กีย่ วเนื่องกับการ push และ pop มีดงั นี้ การสร้างStack (CREATE) การทดสอบว่า stack ว่างหรือไม่(EMPTY) การทดสอบว่า stack เต็มหรือไม่(FULL) การทาให้ stack เป็ น stack ว่าง(CLEAR) การนาข้อมูลเข้าสู่Stack (Push) กระทาทีส่ ว่ นบนของStack (Top) ซึง่ ต้องมีการ ตรวจสอบก่อนว่าStackเต็มหรือไม่ และการนาข้อมูลออกจากStack (Pop) กระทาทีส่ ว่ นบนของStackเช่นกัน โดย ตรวจสอบว่ามีสมาชิกอยูใ่ นStackหรือไม่ (ตรวจสอบว่าStackว่างเปล่าหรือไม่) เป็ นการดาเนินการทีน ่ าข้อมูลเข้าไปเก็บไว้ดา้ นบนสุดของกอง ซ้อน (Top of the Stack) เรือ่ ย ๆ จนกว่ากองซ้อนไม่สามารถนา ข้อมูลเข้าไปเก็บได้ จะเรียกว่า กองซ้อนเต็ม (Stack Full) การทางานจะตรงข้ามกับ Push จะดึงเอาข้อมูลทีอ่ ยู่บนสุดออกมาก่อน แต่ก่อนทีจ่ ะดึงจะมีการตรวจสอบว่ากองซ้อนว่าง หรือไม่ ถ้าว่างจะไม่สามารถนาข้อมูลออกได้ แสดงว่ากองซ้อนว่าง (Stack Empty) ถ้าไม่วา่ งจะนาเอาข้อมูลออกแล้วเลื่อนตัวชี้ไปยังตาแหน่ งถัดลง ไป ให้ Y เป็ นสแตกเก็บค่าตัวเลขได้ไม่เกิน 6 ตัว Push(‘2’),Push(‘5’),Push(‘3’) Pop(),Push(‘9’), Push(‘0’) Push(‘4’) Push(‘6’),Pop() เริม่ ต้นจากการ สร้างสแตก Y ขึน้ มาทางานจาได้ส แตกว่าง ไม่มี สมาชิกโดยตัวชีส้ แตก Top ยังไม่มี ค่า Top นาค่า 2 เข้ามาเก็บ เป็ นตัวแรกโดยใช้ Push(‘2’) สแตก Y=[2] ตัว ชีส้ แตก Top = 2 2 Top นาค่า 5 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘5’) สแตก Y=[5] ตัวชีส้ แตก Top =5 5 2 Top นาค่า 3 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘3’) สแตก Y=[3] ตัวชีส้ แตก Top = 3 3 5 2 Top ต้องการดึงค่า ออกมาโดยใช้ Pop() สแตก Y=[2,5,3]ตัว ชีส้ แตก Top = 3 2 5 Top นาค่า 9 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘9’) สแตก Y=[9] ตัว ชีส้ แตก Top = 9 9 5 2 Top นาค่า 0 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘0’) สแตก Y=[0] ตัวชีส้ แตก Top = 0 0 9 5 2 Top นาค่า 4 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘4’) สแตก Y=[4] ตัวชีส้ แตก Top = 4 4 0 9 5 2 Top นาค่า 6 เข้ามา เก็บเป็ นตัวแรก โดยใช้ Push(‘6’) สแตก Y=[6] ตัวชีส้ แตก Top = 6 6 4 0 9 5 2 Top Any list implementation could be used to implement a stack Arrays (static: the size of stack is given initially) Linked lists (dynamic: never become full) We will explore implementations based on array and linked list Let’s see how to use an array to implement a stack first Need to declare an array size ahead of time มีทางให้ขอ้ มูลเข้า และ ข้อมูลออก เพียงด้านเดียว Associated with each stack is TopOfStack for an empty stack, set TopOfStack to -1 Push (1) Increment TopOfStack by 1. (2) Set Stack[TopOfStack] = X Pop (1) Set return value to Stack[TopOfStack] (2) Decrement TopOfStack by 1 These operations are performed in very fast constant time เป็ นการเตรียมเนื้อทีใ่ นหน่ วยความจาไว้สาหรับเก็บข้อมูล ตัวอย่างในภาษาซี คือ int Stack[4]; Stack การนาข้อมูลเข้าและออกจากหน่ วยความจาด้วยแถวลาดับ ก็เหมือนกับทีย่ กตัวอย่าง ไปแล้ว class Stack { public: Stack(int size = 10); // constructor ~Stack() { delete [] values; } // destructor bool IsEmpty() { return top == -1; } bool IsFull() { return top == maxTop; } double Top(); void Push(const double x); double Pop(); void DisplayStack(); private: int maxTop; // max stack size = size - 1 int top; // current top of stack double* values; // element array }; Attributes of Stack maxTop: the max size of stack top: the index of the top element of stack values: point to an array which stores elements of stack Operations of Stack IsEmpty: return true if stack is empty, return false otherwise IsFull: return true if stack is full, return false otherwise Top: return the element at the top of stack Push: add an element to the top of stack Pop: delete the element at the top of stack DisplayStack: print all the data in the stack The constructor of Stack Allocate a stack array of size. By default, size = 10. When the stack is full, top will have its maximum value, i.e. size – 1. Initially top is set to -1. It means the stack is empty. Stack::Stack(int size /*= 10*/) { maxTop = size - 1; values = new double[size]; top = -1; } Although the constructor dynamically allocates the stack array, the stack is still static. The size is fixed after the initialization. void Push(const double x); Push an element onto the stack If the stack is full, print the error information. Note top always represents the index of the top element. After pushing an element, increment top. void Stack::Push(const double x) { if (IsFull()) cout << "Error: the stack is full." << endl; else values[++top] = x; } double Pop() Pop and return the element at the top of the stack If the stack is empty, print the error information. (In this case, the return value is useless.) Don’t forgot to decrement top double Stack::Pop() { if (IsEmpty()) { cout << "Error: the stack is empty." << endl; return -1; } else { return values[top--]; } } double Top() Return the top element of the stack Unlike Pop, this function does not remove the top element double Stack::Top() { if (IsEmpty()) { cout << "Error: the stack is empty." << endl; return -1; } else return values[top]; } void DisplayStack() Print all the elements void Stack::DisplayStack() { cout << "top -->"; for (int i = top; i >= 0; i--) cout << "\t|\t" << values[i] << "\t|" << endl; cout << "\t|---------------|" << endl; } result int main(void) { Stack stack(5); stack.Push(5.0); stack.Push(6.5); stack.Push(-3.0); stack.Push(-8.0); stack.DisplayStack(); cout << "Top: " << stack.Top() << endl; stack.Pop(); cout << "Top: " << stack.Top() << endl; while (!stack.IsEmpty()) stack.Pop(); stack.DisplayStack(); return 0; } โครงสร้างข้อมูลแบบ stack มีการประยุกต์ใช้มากในการเขียนโปรแกรมของสาขา วิทยาการคอมพิวเตอร์ เช่น การจัดสรรหน่วยความจาในการประมวลผลโปรแกรม (Function Call) รวมทัง้ โปรแกรมเรียกใช้ตวั เอง (Recursive) การตรวจสอบอักขระสมดุล(Balancing Symbol) การคานวณนิพจน์คณิตศาสตร์ การเรียกใช้ Function หรือ Procedure หรือโปรแกรมย่อยในภาษาที่ ไม่มกี าร Recursive เมือ่ มีการเรียกใช้ Function ก็จะทาการ Push Function to Stack และเมือ่ มีการ Return หรือจบการทางานของ Function แล้วจะต้อง Pop Function from Stack การเรียกโปรแกรมย่อยมีความแตกต่างกับการกระโดดทัวไป ่ เนื่องจากภายหลัง ทีโ่ ปรแกรมย่อยทางานเสร็จ หน่วยประมวลผลจะต้องสามารถกระโดดกลับมาทางานใน โปรแกรมหลักต่อไปได้ ดังนัน้ การเรียกใช้โปรแกรมย่อยนัน้ จะต้องมีการเก็บ ตาแหน่ งของคาสังที ่ ่ทางานอยู่เดิมด้วย และเมื่อจบโปรแกรมย่อยโปรแกรม จะต้องกระโดดกลับมาทางานที่เดิม โดยใช้ขอ้ มูลทีเ่ ก็บไว้ ภาพและอัลกอริทมึ แสดง ตัวอย่างการเรียกใช้โปรแกรมย่อย PROGRAM MAIN ...... CALL Sub1 PRINT Q .... END MAIN PROCEDURE Sub1 .... CALL Sub2 A:=A+B ... END Sub1 PROCEDURE Sub2 ... END Sub2 Example : {x+(y-[a+b])*c-[(d+e)]}/(h-(j-(k-[l-n]))) ในการตรวจสอบอักขระสมดุลนัน้ คอมไพเลอร์ได้นาแนวคิด โครงสร้างข้อมูลแบบ Stack มาประยุกต์ โดยมีวิธีการดังนี้ 1. ให้อ่านอักขระทีละตัว - ถ้าอักขระเป็ นอักขระเปิด เช่น {,(,[ เป็ นต้น ให้ PUSH ลง stack - ถ้าอักขระเป็ นอักขระปิด เช่น },),] เป็ นต้น ให้ตรวจสอบว่า อักขระบน TOP ของ stack เป็ นอักขระเปิดที่ค่กู นั หรือไม่ - ถ้าใช่ ให้ POP อักขระนัน้ ออกจาก stack - ถ้าไม่ใช่ ให้แสดงผล error 2.เมื่ออ่านอักขระหมดแล้ว แต่ stack ไม่เป็ น stack ว่าง ให้แสดงผล error