บทที่ 6 คิว

Download Report

Transcript บทที่ 6 คิว

บทที ่ 6 คิว (Queue)
1
บทที่ 6 คิว (Queue)
•
•
•
•
•
•
•
•
•
กล่าวนาคิว
การสร้างคิวด้วยโครงสร้างลิงค์ลสิ ต์
การเพิม่ ข้อมูลในคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การนาข้อมูลออกจากคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
อัลกอริทมึ จัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การสร้างคิวด้วยโครงสร้างอาร์เรย์
อัลกอริทมึ จัดการคิวโครงสร้างอาร์เรย์แบบวงกลม
การนาคิวไปใช้งาน
สรุปเนื้อหาบทที่ 6
2
กล่าวนาคิว
• คิว(Queue) มีหลักการทางานเหมือนกับการเข้าแถวซือ้ ของ คือ คนแรกทีอ่ ยู่ในตาแหน่ง
หัวแถวจะได้รบั บริการก่อนและคนถัดไปจะได้รบั บริการในลาดับต่อไป
• ข้อมูลเข้ามาในคิว ข้อมูลจะถูกเรียงลาดับการเข้ามาก่อนหลังในคิว ข้อมูลทีเ่ ข้ามาก่อนจะ
เป็ นข้อมูลทีถ่ ูกนาไปใช้งานก่อน โดยเรียกหลักการทางานของคิวว่า เข้าก่อนออกก่อน
หรือ ไฟโฟ (first-in, first-out: FIFO)
• หลักการทางานและการจัดการข้อมูลของคิว (ADT Queue Operation)
1.
2.
3.
4.
Create an empty queue. (สร้างคิวว่างเปล่า)
Determine whether a queue is empty. (สนใจข้อมูลในคิวเมือ่ คิวว่าง)
Add a new item to the queue. (เพิม่ ข้อมูลใหม่เข้าไปในคิว)
Remove from the queue the item that was added most earliest. (ลบข้อมูล
ออกจากคิว เมือ่ มีการอ่านข้อมูลออกจากคิวในตาแหน่งเข้าก่อน)
5. Remove all the items from the queue. (ลบข้อมูลทัง้ หมดออกจากคิว)
6. Retrieve from the queue the item that was added most recently. (อ่านข้อมูล
จากคิวทีเ่ พิม่ เข้าไปก่อน)
3
บทที่ 6 คิว (Queue)
• โค้ดรหัสเทียมคิวจากหลักการทางานของคิว ADT
+createQueue()
//สร้างคิวว่างเปล่า
+isEmpty():boolean {query}
//สนใจเมือ่ คิวว่างเปล่า
+enqueue(in newItem:QueueItemType)
//เพิม่ ข้อมูลใหม่ (newItem) ไว้ตาแหน่งสุดท้ายของคิว
+dequeue():StackItemType
//ดึงข้อมูลข้อมูลตาแหน่งหน้าสุดของคิวและลบข้อมูลตาแหน่งหน้าสุดออกจากคิว
+dequeueAll()
//ลบข้อมูลทัง้ หมดออกจากคิว
+peek():QueueItemType{query}
//ดึงข้อมูลตาแหน่งหน้าสุดของคิวแต่ไม่ทาการลบข้อมูลออกจากคิว
4
บทที่ 6 คิว (Queue)
ตัวอย่างที่ 6.1 นา Pseudo code ของคิวมาใช้งาน
5
การสร้างคิวด้วยโครงสร้างลิงค์ลสิ ต์
การสร้างคิวด้วยโครงสร้างลิงค์ลิสต์แบบทิศทางเดียว
 firstNode อ้างอิงตาแหน่งโหนดข้อมูลทีเ่ ข้ามาในคิวก่อน
 lastNode อ้างอิงตาแหน่งโหนดข้อมูลทีเ่ ข้ามาในคิวในลาดับสุดท้าย
6
การสร้างคิวด้วยโครงสร้างลิงค์ลสิ ต์
การสร้างคิวด้วยโครงสร้างลิงค์ลิสต์แบบวงกลม
• เป็ นโครงสร้างทีม่ ปี ระสิทธิภาพในการสร้างคิวลิงค์ลสิ ต์
• การอ้างอิงข้อมูลในคิวลิงค์ลสิ ต์แบบวงกลมจะใช้เพียงตัวแปร lastNode ทาหน้าทีอ่ า้ งอิง
ตาแหน่งโหนดข้อมูลสุดท้ายทีเ่ ข้ามาในคิว
• เมือ่ ต้องการเข้าถึงตาแหน่งข้อมูลทีเ่ ข้ามาในคิวตาแหน่งก่อน จะใช้การอ้างอิงตาแหน่ง
ถัดไปของตัวแปร lastNode ในการอ้างอิงโหนดข้อมูลทีเ่ ข้ามาในคิวก่อน
7
การเพิม่ ข้อมูลในคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การเพิ่มข้อมูลในคิวในกรณี ที่คิวไม่มีข้อมูล
• ตัวแปร lastNode จะมีคา่ เท่ากับ null ก่อนทีจ่ ะเพิม่ ข้อมูลเข้าไปในคิว
• เมือ่ เพิม่ ข้อมูลเข้าไปในคิวลิงค์ลสิ ต์แล้วจะกาหนดให้โหนดใหม่ทเ่ี พิม่ เข้าไปอ้างอิงตัวเอง
Java
1
Node newNode = new Node(3);
2
3
newNode.setNext(newNode);
lastNode = newNode;
C
struct Node *newNode;
newNode = insertNode(3,NULL);
newNode->next = newNode;
lastNode = newNode;
8
การเพิม่ ข้อมูลในคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การเพิ่มข้อมูลในคิวในกรณี ที่คิวมีข้อมูล
• ใช้ลกั ษณะของการเปลีย่ นการอ้างอิงของตัวแปร lastNode จากการอ้างอิงตาแหน่ ง โหนด
สุดท้ายในคิวมาเป็ นการอ้างอิงโหนดข้อมูลใหม่ทต่ี อ้ งการเพิม่ ข้อมูลเข้าไปในคิว
• เปลีย่ นการอ้างอิงโหนดถัดไปของโหนดข้อมูลใหม่ไปยังโหนดข้อมูลแรกในคิว
Java
1
Node newNode = new Node(3);
2
3
4
newNode.setNext(lastNode.getNext());
lastNode.setNext(newNode);
lastNode = newNode;
C
struct Node *newNode;
newNode = insertNode(3,NULL);
newNode->next = lastNode->next;
lastNode->next = newNode;
lastNode = newNode;
9
การนาข้อมูลออกจากคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
• ใช้ตวั แปร firstNode ทาหน้าทีอ่ า้ งอิงตาแหน่งโหนดข้อมูลแรกทีเ่ ข้ามาในคิว
• เลื่อนตาแหน่งการอ้างอิงของ lastNode ไปยังตาแหน่งโหนดถัดไปเพือ่ ทาการลบโหนด
Java
1
firstNode = lastNode.getNext();
2
lastNode.setNext(firstNode.getNext);
C
struct Node *firstNode;
firstNode = lastNode->next;
lastNode->next = firstNode->next;
10
อัลกอริทมึ จัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การจัดการคิวโครงสร้างลิงค์ลิสต์แบบวงกลมด้วยภาษา Java
• นาคลาส Node ในตัวอย่างที่ 4.1 กลับมาใช้ใหม่ในส่วนของการจัดการลิงค์ลสิ ต์
ตัวอย่างที่ 6.3 อัลกอริทมึ สร้างและจัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลมด้วยภาษา Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Queue{
private Node lastNode;
public Queue(){
lastNode = null;
} //end default constructor
public boolean isEmpty(){
return lastNode == null;
}
public void dequeueAll(){
lastNode = null;
}
public void enqueue(int newItem){
Node newNode = new Node(newItem);
if (isEmpty()){
newNode.setNext(newNode);
}else {
newNode.setNext(lastNode.getNext());
lastNode.setNext(newNode);
}
lastNode = newNode;
}
22
23
24
25
26
27
28
29
30
31
32
33
34
35
35
36
37
38
public Object dequeue(){
if (!isEmpty()){
Node firstNode = lastNode.getNext();
if (firstNode == lastNode){
lastNode = null;
}else {
lastNode.setNext(firstNode.getNext());
}
return firstNode.getItem();
}else return -1;
}
public Object peek(){
if (!isEmpty()){
Node firstNode = lastNode.getNext();
return firstNode.getItem();
}else return -1;
}
}
11
อัลกอริทมึ จัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การจัดการคิวโครงสร้างลิงค์ลิสต์แบบวงกลมด้วยภาษา Java
ตัวอย่างที่ 6.3 อัลกอริทมึ สร้างและจัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลมด้วยภาษา Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UserQueue{
public static void main(String[] args){
try{
Queue queue = new Queue();
for (int i = 0;i< 9;i++){
queue.enqueue(i);
}//end for
while (!queue.isEmpty()){
System.out.print(queue.dequeue()+" ");
}
}catch (Exception e){
System.out.println(“error : ”+e);
}
}
}
12
อัลกอริทมึ จัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลม
การจัดการคิวโครงสร้างลิงค์ลิสต์แบบวงกลมด้วยภาษา C
• นาฟงั ก์ชนั Node ตัวอย่าง 4.3 กลับมาใช้งานใหม่ดว้ ยการบันทึกไฟล์ Node.cpp เป็ น
Node.h แล้วนาไปเก็บในโฟลเดอร์ include ก่อนทีจ่ ะเรียกใช้งาน #include <Node.h>
ตัวอย่างที่ 6.5 อัลกอริทมึ สร้างและจัดการคิวโครงสร้างลิงค์ลสิ ต์แบบวงกลมด้วยภาษา C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <Node.h>
#define true 1
#define false 0
typedef int boolean;
struct Node *lastNode = NULL;
boolean isEmpty(){
if(lastNode == NULL)
return true;
else return false;
}
void dequeueAll(){
lastNode = NULL;
}
void enqueue(int newItem){
struct Node *newNode;
newNode = insertNode(newItem,NULL);
if(isEmpty() == true){
newNode->next = newNode;
}else{
newNode->next = lastNode->next;
lastNode->next = newNode;
}
lastNode = newNode;
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
int dequeue(){
if(isEmpty() == false){
struct Node *firstNode;
firstNode = lastNode->next;
if(firstNode == lastNode){
lastNode = NULL;
}else{
lastNode->next = firstNode->next;
}
return firstNode->item;
}else return -1;
}
int peek(){
if(isEmpty() == false){
struct Node *firstNode;
firstNode = lastNode->next;
return firstNode->item;
}else return -1;
}
void main(){
for (int i=0; i<9; i++){
enqueue(i);
}
while(isEmpty() == false){
printf("%d\t",dequeue());
}
}
13
การสร้างคิวด้วยโครงสร้างอาร์เรย์
 front ทาหน้าทีอ่ า้ งอิงตาแหน่งข้อมูลทีเ่ ข้ามาในคิวก่อน
 back ทาหน้าทีอ่ า้ งอิงตาแหน่งข้อมูลทีเ่ ข้ามาในคิวหลังสุด
อธิบายการทางาน
ขัน้ ตอน (a) ตัวแปร front มีค่าเท่ากับ 0 คือ ยังไม่มกี ารนาข้อมูลออกจากคิว และตัวแปร back มี
ค่าเท่ากับ 3 เป็ นตาแหน่ งข้อมูลสุดท้ายทีเ่ ข้ามาในคิว และในส่วนข้อมู ลทีเ่ ป็ นสีเทา
หมายถึงตาแหน่งคิวอาร์เรย์ทย่ี งั ไม่ได้เก็บข้อมูล
ขัน้ ตอน (b) ตัวแปร front มีค่าเท่ากับ 47 คือ มีการนาข้อมูลออกจากคิวจนถึงตาแหน่ งที่ 47 ใน
อาร์เรย์ และตัวแปร back มีคา่ เท่ากับ 49 คือ ตาแหน่ งสุดท้ายทีเ่ ก็บข้อมูลในคิว ซึง่ ก็
คือตาแหน่ ง MAX_QUEUE-1 และเมื่อมีการเพิม่ ข้อมูลในคิวอีกจะทาให้เ กิดปญั หา
คิวเต็ม ทาให้ไม่สามารถเพิม่ ข้อมูลในคิวได้
14
การสร้างคิวด้วยโครงสร้างอาร์เรย์
• จากปญั หาคิวอาร์เรย์เต็มภายในคิวแบบอาร์เรย์ จึงได้จดั โครงสร้างของคิวแบบอาร์เรย์ใหม่
ให้มลี กั ษณะโครงสร้างคิวแบบวงกลม
• กาหนดให้มตี วั แปร front อ้างอิงตาแหน่งข้อมูลทีเ่ ข้ามาในคิวก่อนและจะเป็ นตาแหน่งทีจ่ ะ
ถูกนาข้อมูลออกจากคิวเป็ นอันดับแรก ส่วนตัวแปร back ทาหน้าอ้างอิงตาแหน่ งในการ
เพิม่ ข้อมูลในคิว
15
การสร้างคิวด้วยโครงสร้างอาร์เรย์
ตัวอย่างที่ 6.6 แสดงการเลื่อน front และ back ในการเพิม่ และลบข้อมูลในคิวอาร์เรย์แบบวงกลม
• เมือ่ พิจารณาการเลื่อนตาแหน่งของตัวแปร front และตัวแปร back ในคิวแบบวงกลม
เมือ่ ตัวแปร front หรือตัวแปร back เลื่อนอยู่ทต่ี าแหน่ง MAX_QUEUE – 1 (ตาแหน่ง
สุดท้ายในการเก็บข้อมูลในคิวโครงสร้างอาร์เรย์) ตาแหน่งถัดไปทีจ่ ะเลื่อนการอ้างอิงคือ
ตาแหน่ง 0 (ตาแหน่งแรกในการเก็บข้อมูลในคิวโครงสร้างอาร์เรย์)
• ก่อนทีจ่ ะทาการเลื่อนตาแหน่งตัวแปร front และตัวแปร back ต้องทาการตรวจสอบ
ตาแหน่งทีจ่ ะทาการเลื่อนก่อน
16
การสร้างคิวด้วยโครงสร้างอาร์เรย์
การค้นหาตาแหน่ งในการเพิ่มข้อมูลในคิวอาร์เรย์แบบวงกลม
1. back = (back+1) % MAX_QUEUE;
2. items[back] = newItem;
3. ++count;
อธิบายการทางาน
ขัน้ ตอนที่ 1 ถ้ากาหนด MAX_QUEUE มีค่าเท่ากับ 25 คือจานวนข้อมูลทีส่ ามารถเก็บ
ข้อมูลในคิวอาร์เรย์ได้ 25 ข้อมูล และกาหนดให้ back อ้างอิงตาแหน่ง 24 ใน
คิวอาร์เรย์ ดังนัน้ ตัวแปร back จะอ้างอิงตาแหน่งถัดไปมีค่าเท่ากับ (24+1) %
25 เท่ากับ 0 ซึง่ เป็ นตาแหน่งถัดไปทีจ่ ะเก็บข้อมูลในคิวอาร์เรย์แบบวงกลม
ขัน้ ตอนที่ 2 เพิม่ ข้อมูลใหม่เข้าไปในคิวอาร์เรย์แบบวงกลมในตาแหน่ง back
ขัน้ ตอนที่ 3 เพิม่ ค่าให้กบั ตัวแปรที่ทาหน้าที่นับข้อมูลในคิวขึน้ หนึ่ งข้อมูล เพื่อใช้ในการ
ตรวจสอบว่าคิวเต็มหรือไม่
17
การสร้างคิวด้วยโครงสร้างอาร์เรย์
การค้นหาตาแหน่ งในการนาข้อมูลออกจากคิวอาร์เรย์แบบวงกลม
1. front = (front+1) % MAX_QUEUE;
2. --count;
อธิบายการทางาน
ขัน้ ตอนที่ 1 ถ้ากาหนด MAX_QUEUE มีค่าเท่ากับ 25 และ front อ้างอิงทีต่ าแหน่ง 24 ในคิว
อาร์เรย์ ดังนัน้ ตัวแปร front จะอ้างอิงตาแหน่ งถัดไปมีค่าเท่ากับ (24+1) % 25
เท่ากับ 0 ซึง่ เป็ นตาแหน่งถัดไปทีจ่ ะนาข้อมูลออกจากคิวอาร์เรย์แบบวงกลม
ขัน้ ตอนที่ 2 ลดค่าในตัวแปรทีท่ าหน้าทีใ่ นการนับจานวนข้อมูลในคิวลงหนึ่ง เพื่อตรวจสอบว่า
คิวว่างเปล่าหรือไม่
18
การสร้างคิวด้วยโครงสร้างอาร์เรย์
การตรวจสอบคิวอาร์เรย์แบบวงกลมว่าคิวเต็มหรือคิวว่างเปล่า
• ใช้ตวั แปร 3 ตัวคือ ตัวแปร front, back และ count ในการตรวจสอบคิวเต็มหรือคิวว่างเปล่า
• คิวเต็มและคิวว่างเปล่าค่าของตัวแปร font และตัวแปร back จะมีคา่ เท่ากัน (front == back
• พิจารณาตัวแปร count ทีท่ าหน้าทีน่ บั ข้อมูลในคิวเพิม่ เติมด้วย โดยที่
 คิวเต็ม ตัวแปร count จะมีคา่ เท่ากับค่า MAX_QUEUE
 คิวว่าง ตัวแปร count จะมีคา่ เท่ากับ 0
19
อัลกอริทมึ จัดการคิวโครงสร้างอาร์เรย์แบบวงกลม
การจัดการคิวโครงสร้างอาร์เรย์แบบวงกลมด้วยภาษา Java
ตัวอย่างที่ 6.14 อัลกอริทมึ สร้างและจัดการข้อมูลในคิวอาร์เรย์แบบวงกลมด้วยภาษา Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class QueueArray{
private final int MAX_QUEUE = 5;
private int[] items;
private int front,back,count;
public QueueArray(){
items = new int[MAX_QUEUE];
front = 0;
back = MAX_QUEUE-1;
count = 0;
}
public boolean isEmpty(){
return (count == 0);
}
public boolean isFull(){
return (count == MAX_QUEUE);
}
public boolean enqueue(int newItem){
if (!isFull()){
back = (back+1) % MAX_QUEUE;
items[back] = newItem;
++count;
return true;
}else return false;
}
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public int dequeue(){
if (!isEmpty()){
int queueFront = items[front];
front = (front+1) % MAX_QUEUE;
count--;
return queueFront;
}else return -1;
}
public void dequeueAll(){
items = new int[MAX_QUEUE];
front = 0;
back = MAX_QUEUE-1;
count = 0;
}
public int peek(){
if (!isEmpty()){
return items[front];
}else return -1;
}
}
20
อัลกอริทมึ จัดการคิวโครงสร้างอาร์เรย์แบบวงกลม
การจัดการคิวโครงสร้างอาร์เรย์แบบวงกลมด้วยภาษา C
ตัวอย่างที่ 6.15 อัลกอริทมึ สร้างและจัดการข้อมูลในคิวอาร์เรย์แบบวงกลมด้วยภาษา C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#define MAX_QUEUE 5
#define true 1
#define false 0
typedef int boolean;
int items[MAX_QUEUE];
int front = 0;
int back = MAX_QUEUE-1;
int count = 0;
boolean isEmpty(){
if((count == 0)&&(front == back))
return true;
else return false;
}//end isEmpty
boolean isFull(){
if(count == MAX_QUEUE)
return true;
else return false;
}//end isFull
boolean enqueue(int newItem){
if(!isFull()){
back = (back+1) % MAX_QUEUE;
items[back] = newItem;
++count;
return true;
}else return false;
}//end enqueue
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
int dequeue(){
if(isEmpty() == false){
int queueFront = items[front];
front = (front+1) % MAX_QUEUE;
count--;
return queueFront;
}else return -1;
}//end dequeue
void dequeueAll(){
front = 0;
back = MAX_QUEUE-1;
count = 0;
}//end dequeueall
int peek(){
if(isEmpty() == false){
return items[front];
}else return -1;
}//end peek
21
การนาคิวไปใช้งาน
• ยกตัวอย่างการจัดการลาดับการทางานของระบบปฏิบตั กิ ารในอัลกอริทมึ ชื่อ Round Robin
Scheduler
• Round Robin Scheduler เป็ นการบริการแบบวงกลมเพื่อตอบสนองงานในแต่ละงาน
ยกตัวอย่างเช่นในทุกงานมีความต้องในการตอบสนองของช่วงเวลาการทางานของหน่ วย
ประมวลผล (CPU) ที่เท่ากัน โดยในหนึ่ง ช่วงเวลาการทางานของหน่ วยประมวลผลกลาง
เท่ากับ 100 มิลลิวนิ าที ถ้างานที่ 1 ต้องใช้เวลาในการประมวลผล 250 มิลลิวนิ าทีจงึ จะทางาน
เสร็จ
• หลักการ Round Robin Scheduler จะบริการงานที่ 1 เป็ นเวลา 100 มิลลิวนิ าที ส่วนงานที่
เหลือต้องไปเข้าคิวรอรับบริการ ทาอย่างนี้จนกระทัง้ งานที่ 1 ได้รบั การบริการจากหน่ วย
ประมวลผลกลางจนเสร็จชิน้ งาน
22
สรุปเนื้อหาบทที่ 6
• คิวเป็ นรูปแบบโครงสร้างใช้ในการเก็บข้อมูลทีพ่ บได้ในชีวติ ประจาวัน โดยคิวมีรปู แบบการ
ทางานเป็ นแบบ เข้าก่อนออกก่อน (First-in, First-out) คือข้อมูลทีเ่ ข้ามาก่อนจะเป็ นข้อมูลที่
ถูกนาไปใช้งานก่อน เช่นการเข้าคิวซือ้ สินค้าคนทีอ่ ยูห่ วั แถวจะได้รบั บริการก่อนและคนระดับ
ถัดไปก็จะถูกได้รบั บริการในลาดับถัดไป
• เครือ่ งมือทีใ่ ช้ในการสร้างคิวมี 2 เครือ่ งมือ คือ อาร์เรย์ และลิงค์ลสิ ต์
• การสร้างคิวด้วยอาร์เรย์และลิงค์ลสิ ต์แบบวงกลม เป็ นการแก้ปญั หาการเก็บข้อมูลไปจนถึง
ตาแหน่งสุดท้ายในอาร์เรย์ให้สามารถเก็บข้อมูลในตาแหน่งแรกในคิวอาร์เรย์ใหม่ได้ โดยการ
สร้างคิวด้วยลิงค์ลสิ ต์สามารถเก็บข้อมูลคิวได้อย่างมีประสิทธิภาพ
23