บทที่ 5: โครงสร้างข้อมูลคิว (Queue)

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

คิวคือโครงสร้างข้อมูลที่เก็บข้อมูลชนิดเดียวกัน ที่ใช้ใส่ข้อมูลทางด้านหลัง (back) และเอาข้อมูลออกทางด้านหน้า (front) เท่านั้น ข้อมูลที่ใส่ก่อนจะเอาออกมาได้ก่อน เรียกว่า First In First Out (FIFO) ตัวอย่างของคิว เช่นการเข้าคิวใช้บริการต่างๆ เช่นแถวในธนาคาร แถวที่ป้ายรถเมล์ แถวรถที่ด่านเก็บเงิน การใช้คู่สายโทรศัพท์ เป็นต้น

ลักษณะของโครงสร้างแบบคิวจะเหมือนกับการเข้าแถวคอยหรือเข้าคิว ข้อมูลที่เข้ามาก่อนจะได้รับบริการก่อน ตัวอย่างการใช้คิวในระบบคอมพิวเตอร์เช่น การสั่งพิมพ์งานพร้อมกันหลายๆคน โดยใช้เครื่องพิมพ์เครื่องเดียวกัน ใครสั่งพิมพ์ก่อนก็จะเข้าคิวไปรอการพิมพ์ในลำดับแรก คนต่อไปก็จะต้องเข้าคิวรอจนกว่างานแรกจะพิมพ์เสร็จ จึงจะมาทำงานกับคิวที่รออยู่ต่อไป หรือการทำงานของระบบปฏิบัติการแบบ multi-tasking ซึ่งสามารถประมวลผลหลายๆโปรแกรมพร้อมๆกันด้วยระบบการแบ่งปันเวลาเท่าๆกัน ตามลำดับของโปรแกรมที่เข้ามาในคิวของระบบปฏิบัติการ

การดำเนินการกับ Queues -->> Top
วิธีการดำเนินการกับคิวคือ Enqueue, Dequeue, getFront, IsEmpty, IsFull
• Enqueue: คือการใส่ข้อมูลเข้าไปทางด้านหลัง (back) ของคิว
• Dequeue: คือวิธีการเอาข้อมูลออกจากด้านหน้า (front) ของคิว
• getFront: คือการตรวจสอบข้อมูลด้านหน้าของคิว (แต่ไม่เอาออกจากคิว)
• IsEmpty: ตรวจสอบว่าคิวว่างหรือไม่ก่อนที่จะเอาข้อมูลออกจากคิว
• IsFull: ตรวจสอบว่าคิวเต็ม (overflow) หรือไม่ก่อนที่จะใส่ข้อมูลในคิว
Placeholder image
ตัวอย่างโปรแกรมจำลองการทำงานของคิวที่เก็บจำนวนเต็ม
  • ใส่ตัวเลข 35, 94, 9, 86, 68, 39 เข้าไปในคิวหรือ Enqueue 6 ครั้ง ตามลำดับ
  • Placeholder image
  • นำข้อมูลจากคิวไปใช้ หรือ Dequeue 2 ครั้ง
  • Placeholder image
    รูปแบบของคิว Queue Model -->> Top
    • มี 2 แบบคือ คิวเส้นตรง (Linear Queue) และคิววน (Circular Queue)
    ตัวอย่างคิวเส้นตรง
    Placeholder image

    โดยมีวิธีการจัดการกับข้อมูลดังนี้
    คิวเส้นตรง Linear Queue
    Placeholder image
    คิววน Circular Queue
    ถ้าคิวยังไม่เต็ม และ front หรือ back อยู่ที่ตำแหน่งสุดท้าย ก็ให้เลื่อนมาที่ตำแหน่งแรก และบันทึกจำนวนข้อมูลในคิวเพื่อใช้ตรวจสอบว่าคิวเต็มหรือว่าง
    Placeholder image
    Placeholder image
    วิธีการใส่ข้อมูลในคิว (Enqueue) -->> Top
    ก่อนใส่ข้อมูลต้องตรวจสอบก่อนว่าคิวเต็มหรือไม่ ถ้าไม่เต็ม ให้พิ่มค่า back แล้วใส่ข้อมูลที่ตำแหน่งนั้น
    Placeholder image
    วิธีการเอาข้อมูลออกจากคิว (Dequeue)

    ก่อนเอาข้อมูลออก ต้องตรวจสอบว่าคิวว่างหรือไม่ ถ้าไม่ว่างก็ให้เพิ่มค่า front 1 ตำแหน่ง
    Placeholder image
    การใช้งานคิวในระบบคอมพิวเตอร์ -->> Top
    ตัวอย่างการใช้งานคิวระบบคอมพิวเตอร์ เช่นการจัดการกับโปรแกรมที่ทำงานพร้อมๆกันหลายๆโปรแกรม
    Placeholder image


    ระบบคอมพิวเตอร์ที่มีการทำงานแบบหลายผู้ใช้หรือหลายโปรแกรมพร้อมๆกันและแบ่งเวลาเท่าๆกัน โดยมีหน่วยผลกลาง (ซีพียู) และหน่วยความจำหลักเพียงอย่างละ 1 ชุด วิธีการประมวลผลแบบนี้เราเรียกว่า ระบบแบ่งกันใช้เวลา (Time sharing) ซึ่งลักษณะการใช้ซีพียูจะเป็นไปตามลำดับคือ “มาก่อนได้ก่อน” (first – come – first – serve) และมีลำดับการทำงานดังนี้

    1. เมื่อโปรแกรมขอใช้เวลาซีพียู โปรแกรมนั้นจะถูกนำไปต่อด้านหลังของคิวประมวลผล
    2. โปรแกรมที่อยู่ด้านหน้าของคิวจะถูกส่งไปทำงาน จนครบเวลาก็จะถูกนำไปต่อด้านหลังของคิว หรือถ้าจบการทำงาน ก็จะถูกนำออกจากคิว

    อีกตัวอย่างคือการใช้เรียงลำดับคำสั่งของ input จากคีย์บอร์ดหรือเมาส์ ที่ส่งเข้ามา แล้วประมวลผลตามลำดับ เช่นคิวคำสั่ง (command queue)

    Placeholder image

    ผู้ใช้กดเมาส์บนรูปบ้านเพื่อกำหนดตำแหน่งในการเคลื่อที่บนหน้าจอ เพื่อที่จะนำเด็กทารกไปส่งที่บ้าน เนื่องจากบ้านจะถูกสุ่มเพื่อเปลี่ยนตำแหน่งทุกๆ 1 วินาที ทุกครั้งที่กดเมาส์ตำแหน่งจะถูกเก็บในคิวคำสั่ง แล้วโปรแกรมก็จะวาดรูปเด็กทารกเคลื่อนที่จากตำแหน่งปัจจุบันไปยังตำแหน่งถัดไปในคิวตามที่กดเมาส์ ถ้ากดเร็วมากพอก็จะนำเด็กทารกไปส่งที่บ้านได้

    Placeholder image

    ตัวอย่างโปรแกรมสร้างคิวด้วยอาร์เรย์ -->> Top

    using System;
    
    	namespace queue
    	{
        // ArrayQueue class
        //
        // Array-based implementation of the queue.
        //
        // ******************PUBLIC OPERATIONS*********************
        // void Enqueue( x )      --[>] Insert x
        // AnyType GetFront( )    --[>] Return least recently inserted item
        // AnyType Dequeue( )     --[>] Return and remove least recent item
        // boolean IsEmpty( )     --[>] Return true if empty; else false
        // void MakeEmpty( )      --[>] Remove all items
        // ******************ERRORS********************************
        // GetFront or Dequeue on empty queue
        public class ArrayQueue : IQueue
        {
            // Construct the queue.
            public ArrayQueue( )
            {
                theArray = new AnyType[ DEFAULT_CAPACITY ];
                MakeEmpty( );
            }
            // Tests if the queue is logically empty.
            // Returns true if empty, false otherwise.
            public bool IsEmpty( )
            {
                return currentSize == 0;
            }
    
            // Makes the queue logically empty.
            public void MakeEmpty( )
            {
                currentSize = 0;
                front = 0;
                back = -1;
            }
    
            // Removes and returns the least recently inserted item from the queue.
            // Throws UnderflowException if the queue is empty.
            public AnyType Dequeue( )
            {
                if( IsEmpty( ) )
                    throw new UnderflowException( "ArrayQueue dequeue" );
                currentSize--;
    
                AnyType returnValue = theArray[ front ];
                Increment( ref front );
                return returnValue;
            }
    
            // Returns the least recently inserted item in the queue.
            // Throws UnderflowException if the queue is empty.
            public AnyType GetFront( )
            {
                if( IsEmpty( ) )
                    throw new UnderflowException( "ArrayQueue getFront" );
                return theArray[ front ];
            }
    
            // Inserts x into the queue.
            public void Enqueue( AnyType x )
            {
                if( currentSize == theArray.Length )
                    DoubleQueue( );
                Increment( ref back );
                theArray[ back ] = x;
                currentSize++;
            }
    
            // Internal method to increment with wraparound.
            // x is any index in theArray's range.
            // Returns x+1, or 0 if x is at the end of theArray.
            private void Increment( ref int x )
            {
                if( ++x == theArray.Length )
                    x = 0;
            }
    
            // Internal method to expand theArray.
            private void DoubleQueue( )
            {
                AnyType[ ] newArray = new AnyType[ theArray.Length * 2 + 1 ];
    
                // Copy elements that are logically in the queue
                for( int i = 0; i [<] currentSize; i++, Increment( ref front ) )
                    newArray[ i ] = theArray[ front ];
    
                theArray = newArray;
                front = 0;
                back = currentSize - 1;
            }
    
            private AnyType[ ] theArray;
            private int currentSize;
            private int front;
            private int back;
    
            private const int DEFAULT_CAPACITY = 10;
        }
    	}
    
    	class Program
        {
            public static void queueOps(string type, IQueue s)
            {
                Console.WriteLine(type + " output: ");
                for (int i = 0; i [<] 10; i++)
                    s.Enqueue(i);
    
                while (!s.IsEmpty())
                    Console.WriteLine(s.Dequeue());
            }
            static void Main(string[] args)
            {
                IQueue q1 = new ArrayQueue();
                queueOps("ArrayQueue", q1);
                Console.ReadKey();
             }
        }
    
    

    Placeholder image

    การวิเคราะห์ค่า Big O ของ Queue
    การ enqueu และ dequeue มีการทำงานเพียงครั้งเดียว ดังนั้นค่า Big O คือ O(1)
    สรุป -->> Top
    • คิวคือโครงสร้างข้อมูลที่มีคุณสมบัติ First In First out
    • ข้อมูลที่ใส่เข้าไปก่อน จะถูกนำออกมาใช้ก่อน
    • ก่อนจะใส่ข้อมูล (Enqueue) ต้องตรวจสอบว่า สแตคเต็มหรือไม่
    • ก่อนเอาข้อมูลออก (Dequeue) ต้องตรวจสอบว่า คิวว่างหรือไม่
    • ตัวอย่างการใช้งานคิวในโปรแกรมคอมพิวเตอร์เช่นการประมวลผลโปรแกรมในระบบที่มีการทำงานพร้อมๆกันหลายๆโปรแกรม เช่นบน Windows เป็นต้น

    2020. mnet50.com