บทที่ 4: โครงสร้างข้อมูลสแตค (Stack)

วัตถุประสงค์

สแตคคือโครงสร้างข้อมูลที่เก็บข้อมูลชนิดเดียวกัน ที่สามารถเพิ่มและลบข้อมูลได้ทางเดียวเท่านั้น คือด้านบน (top) ของสแตคเท่านั้น โดยข้อมูลที่เพิ่มหลังสุด จะเอาออกจากสแตคได้ก่อนข้อมูลที่เพิ่มมาก่อนหน้า (Last In First Out, LIFO) ตัวอย่างของสแตคในชีวิตประจำวัน เช่นสแตคของจานในโรงอาหาร สแตคของหนังสือ สแตคของวัตถุที่เรียงซ้อนกันเป็นชั้นๆ เป็นต้น

สแตคเป็นโครงสร้างข้อมูลที่ใช้บ่อยมากในระบบคอมพิวเตอร์ การเรียกใช้งานฟังก์ชันต่างๆของโปรแกรมซึ่งเกิดขึ้นตลอดเวลาที่โปรแกรมกำลังทำงานอยู่ ล้วนแล้วแต่เป็นการใช้งานสแตค การเขียนโปรแกรมแบบเรียกซ้ำ (recursion) และการเก็บคำสั่ง การยกเลิกคำสั่ง (Undo/Redo) ในโปรแกรมพิมพ์เอกสาร การตรวจสอบข้อผิดพลาดของโปรแกรมโดยคอมไพเลอร์ การแปลงนิพจน์จาก infix เป็น postfix และการหาค่าของนิพจน์ postfix evaluation เป็นต้น

การดำเนินการกับสแตค -->> Top
วิธีการดำเนินการกับสแตคคือ Push, Pop, Top, IsEmpty, IsFull.
Push: คือวิธีการใส่ข้อมูลเข้าไปในสแตค ต้องตรวจสอบก่อนว่าสแตคไม่เต็มจึงจะ push ได้
Pop: คือวิธีการเอาข้อมูลออกจากสแตค ต้องตรวจสอบก่อนว่าสแตคไม่ว่างจึงจะ pop ได้
Top: คือการตรวจสอบข้อมูลบนสแตค (แต่ไม่เอาออกจากสแตค)
IsEmpty: ตรวจสอบสแตคว่างหรือไม่ก่อนที่จะเอาข้อมูลออกจากสแตค
IsFull: ตรวจสอบว่าสแตคเต็ม (overflow) หรือไม่ก่อนที่จะใส่ข้อมูล
Placeholder image
ตัวอย่างโปรแกรมจำลองการทำงานของสแตค -->> Top
  • • กำหนดขนาดสแตคเป็น 5 จากนั้น push 71,45,20,47,15 บนสแตคจนเต็ม จะแสดงข้อความ Stack Full
  • Placeholder image
  • • Pop สแตค 5 ครั้ง จนสแตคว่าง จะแสดงข้อความ Stack Empty
  • Placeholder image
    การใช้งานสแตคในโปรแกรมคอมพิวเตอร์ -->> Top
    การใช้งานสแตคในโปรแกรมคอมพิวเตอร์
    ตัวอย่างการตรวจสอบเครื่องหมายในโปรแกรม
  • • เราจะรู้ได้อย่างไรว่านิพจน์ต่อไปนี้ถูกต้องตามหลักการเขียนโปรแกรม 7-((X*((X+Y)/(J-3))+Y)/(4-2.5))
  • วิธีการหาคำตอบ
  • 1. จำนวนเครื่องหมายเปิด (ซ้าย) และปิด (ขวา) ต้องเท่ากัน
  • ตัวอย่าง
    โปรแกรมตรวจสอบเครื่องหมายโดยใช้สแตค Balanced Multi-Symbol Algorithm -->> Top
    a) ถ้าสแตคว่าง แสดงว่าเครื่องหมายผิด
    b) ถ้าสแตคไม่ว่าง Pop สแตค ต้องได้เครื่องหมายเปิด (ช้าย) ที่สัมพันธ์กัน ถ้าไม่ใช่แสดงว่าเครื่องหมายผิด
    c) ถ้าเครื่องหมายถูกต้อง ให้ทำต่อไป (ทำซ้ำข้อ 1)
  • 3. ถ้าอ่านจนจบแล้ว สแตคต้องว่าง จึงจะถือว่าเครื่องหมายถูกต้อง มิฉะนั้นเครื่องหมายผิด
  • ตัวอย่าง
    Placeholder image

    อ่านเครื่องหมายจนหมด แล้วสแตคว่าง แปลว่าเครื่องหมายถูกต้อง

    โปรแกรมการตรวจสอบเครื่องหมาย

    Placeholder image

    ตัวอย่างการใช้งานสแตคในนิพจน์ Infix, Postfix

    Infix คือนิพจน์ที่รูปแบบดังนี้

    • Operand operator Operand

    ตัวอย่าง

    A + B * C

    Postfix คือนิพจน์ที่รูปแบบดังนี้

    • Operand operator

    Operator ตามหลัง operands

    ตัวอย่าง

    Placeholder image

    Postfix ไม่จำเป็นต้องใช้วงเล็บในการกำหนดลำดับความสำคัญ

    การคำนวณค่าจากนิพจน์ Postfix -->> Top
  • คอมพิวเตอร์รู้ได้อย่างว่า 3 4 + 5 * = 35 ?
    วิธีการหาคำตอบโดยใช้สแตค

    1. อ่านนิพจน์ ถ้าเจอ operand ให้ Push ลงบนสแตค
    2. ถ้าเจอ operator ให้ Pop สแตค 2 ครั้ง โดยการ Pop ครั้งแรกจะได้ operand ที่อยู่ทางขวาและการ Pop ครั้งที่สองจะได้ operand ที่อยู่ทางซ้าย ของ operator ให้ทำการคำนวณแล้ว Push ผลลัพธ์ลงบนสแตค
    3. อ่านต่อจนจบนิพจน์ (ทำซ้ำข้อ 1 )
    4. Pop สแตค ค่าที่ได้คือผลลัพธ์

    ตัวอย่าง
    หาค่าของนิพจน์: 6 2 3 + - 3 8 2 / + * 2 $ 3 +
    หาค่าของนิพจน์: 6 2 3 + - 3 8 2 / + * 2 $ 3 +

    Placeholder image

    ผลลัพธ์คือ 52


  • โปรแกรมการหาค่าผลลัพธ์ของนิพจน์ postfix

    Placeholder image


    แบบฝึกหัด
    • สมมติว่าตัวเลขแต่ละตัวเป็น operand ให้หาค่าของนิพจน์ต่อไปนี้
    1. 7 6 + 5 4 * 3 2 $ / -
    2. 6 5 3 * +
    3. 1 2 3 * + 1 2 * 3 + 2 * +
    วิธีการแปลงจาก Infix เป็น Postfix
  • เนื่องจากเราจะคุ้นเคยกับนิพจน์ infix มากกว่า postfix แต่ในการคำนวณค่าของนิพจน์ด้วยสแตค ต้องใช้นิพจน์ postfix เท่านั้น ดังนั้นเราจึงต้องทำการแปลงนิพจน์จาก infix เป็น postfix เสียก่อน ซึ่งสามารถทำได้โดยใช้สแตคเช่นเดียวกัน ตามอัลกอริทึมดังนี้

    1. ถ้าอ่านเจอ operand ให้เก็บในสตริงของ postfix
    2. ถ้าอ่านเจอ operator ให้ Push ลงบนสแตคดังนี้
    2.1 ให้ Push $ และ ( เสมอ
    2.2 ถ้าเจอ ) ให้ Pop สแตคทีละตัว แล้วใส่เพิ่มต่อจากสตริงของ postfix จนกระทั่ง Pop จนเจอ (
    2.3 ถ้าบนสแตคมี operator +, -, *, /, ที่เท่ากันหรือสูงกว่าให้ Pop สแตคไปเรื่อยๆแล้วใส่เพิ่มต่อจากสตริงของ postfix จนเจอ operator ที่มีลำดับต่ำกว่าจึงหยุด Pop โดยให้ถือว่า ( มีความสำคัญต่ำสุด เมื่อหยุด Pop ก็ให้ Push operator ลงบนสแตค
    3. ทำซ้ำข้อ 1 จนจบนิพจน์ ก็ให้ Pop สแตคไปเรื่อยๆแล้วใส่เพิ่มต่อจากสตริงของ postfix จนกระทั่งสแตคว่าง

  • ตัวอย่าง

    ตัวอย่างที่ 2: A+B*C+(D*E+F)*G
    Placeholder image

    เมื่อสแตคว่าง นิพจน์ postfix คือสตริงของ postfix str : ABC*+DE*F+G*+


    โปรแกรม แปลงนิพจน์ Infix เป็น Postfix

    Placeholder image
    แบบฝึกหัด
    • แปลงนิพจน์ Infix เป็น Postfix
    1. (A+B)*(C-D)
    2. ((A+B)*C-(D-E))$(F+G)
    3. A-B/(C*D$E)
    การสร้างสแตคของข้อมูลแบบต่างๆ -->> Top
  • การสร้างข้อมูลแบบสแตคจะใช้อาร์เรย์ หรือลิงค์ลิสต์ก็ได้ ถ้าใช้อาร์เรย์ซึ่งเป็นการจัดสรรพื้นที่หน่วยความจำแบบคงที่ ก็จะต้องมีการกำหนดขนาดของสแตคล่วงหน้าว่าจะมีขนาดเท่าใด แต่ถ้าสร้างสแตคด้วยลิงค์ลิสต์ซึ่งเป็นการจัดสรรหน่วยความจำแบบไม่จำกัด สแตคจะไม่เต็ม จะใส่ข้อมูลได้เรื่อยๆขึ้นอยู่กับหน่วยความจำที่เหลืออยู่

    ตัวอย่างข้อมูลที่เก็บในสแตค เช่น ชนิดตัวอักษร (char) ข้อความ (string) จำนวนเต็ม (int) และจำนวนจริง (double)


  • Placeholder image

    ตัวอย่างโปรแกรมสแตคเก็บจำนวนเต็ม ข้อความ และตัวอักษร

    // ArrayStack class
        // Array-based implementation of the stack.
        //
        // CONSTRUCTION: with no initializer
        //
        // ******************PUBLIC OPERATIONS*********************
        // void Push(x)         --[>] Insert x
        // void Pop( )            --[>] Remove most recently inserted item
        // AnyType Top( )         --[>] Return most recently inserted item
        // AnyType TopAndPop( )   --[>] Return and remove most recent item
        // boolean IsEmpty( )     --[>] Return true if empty; else false
        // void MakeEmpty( )      --[>] Remove all items
        // ******************ERRORS********************************
        // Top, Pop, or TopAndPop on empty stack
    
    
    
    	public static void stackOps(ArrayStack[] s)
            {
                Console.WriteLine("Push Stack: ");
                for (int i = 0; i [<] 10; i++)
                {
                    s.Push(i);
                    Console.Write("{0} ", i);
                }
                Console.WriteLine();
                Console.WriteLine("Pop Stack: ");
                while (!s.IsEmpty())
                {
                    Console.Write(s.TopAndPop());
                    Console.Write(" ");
                }
                Console.WriteLine();
            }
    
            public static void Main(string[] args)
            {
                ArrayStack s1 = new ArrayStack();
                ArrayStack s2 = new ArrayStack();
                ArrayStack s3 = new ArrayStack();
    
                Console.WriteLine("Stack Example");
                stackOps(s1);
                // five names
                Console.WriteLine("Push Stack");
                Console.WriteLine("Enter 5 strings");
                for (int i = 0; i [<] 5; i++)
                {
                    Console.Write("Enter string {0}: ", i + 1);
                    s2.Push(Console.ReadLine());
                }
                // 
                Console.WriteLine("Pop Stack");
                while (!s2.IsEmpty())
                    Console.WriteLine(s2.TopAndPop());
    
                // reverse string
                Console.WriteLine("Push String");
                Console.Write("Enter a string: ");
                string s = Console.ReadLine();
                for (int i = 0; i[<]s.Length; i++)
                {
                    s3.Push(s[i]);
                }
                // 
                Console.WriteLine("Pop String");
                while (!s3.IsEmpty())
                    Console.Write(s3.TopAndPop());
                Console.ReadKey();
            }
    
    

    Placeholder image

    การวิเคราะห์ค่า Big O ของ Stack
    การ push และ pop สแตค มีการทำงานเพียงครั้งเดียว ดังนั้นค่า Big O คือ O(1)
    สรุป -->> Top
    • สแตคคือโครงสร้างข้อมูลที่ที่มีคุณสมบัติ Last In First out
    • ข้อมูลที่ใส่เข้าไปครั้งหลังสุด จะถูกนำออกมาใช้ก่อน
    • ก่อนจะใส่ข้อมูล (Push) ต้องตรวจสอบว่า สแตคเต็มหรือไม่
    • ตัวอย่างการใช้งานสแตคในโปรแกรมคอมพิวเตอร์เช่นการตรวจสอบเครื่องหมายในการแปลภาษา การแปลงนิพจน์ การหาค่าของนิพจน์ การเรียกใช้ฟังก์ชัน เป็นต้น

    2020. mnet50.com