บทที่ 10 ลำดับความสำคัญของคิวและฮีพ

Download Report

Transcript บทที่ 10 ลำดับความสำคัญของคิวและฮีพ

บทที ่ 10 ลำดับควำมสำคัญ
ของคิว และ ฮีพ
(Priority Queue and Heap)
1
บทที่ 10 ลำดับควำมสำคัญของคิว และ ฮีพ
•
•
•
•
ลำดับควำมสำคัญของคิว (Priority Queue)
เครือ่ งมือทีใ่ ช้สร้างคิวของลาดับความสาคัญ
ฮีพ (Heap)
สรุปเนื้อหำบทที่ 10
2
ลำดับควำมสำคัญของคิว (Priority Queue)
• เมื่อนึกถึงห้องฉุ กเฉิน สิง่ ทีส่ ำคัญทีต่ ้องกำรพิจำรณำในกำรรักษำของผูป้ ่วย คือ ลำดับ
ควำมสำคัญของปญั หำ
• เป็ นสิง่ ทีย่ ำกในกำรตัดสินใจในกำรให้ลำดับควำมสำคัญในแต่ละผูป้ ่วย แต่สงิ่ ทีง่ ่ำยใน
กำรจัดลำดับในกำรรักษำของผูป้ ว่ ย คือ กำรเรียงตำมลำดับตัวอักษรของชื่อของผูป้ ่วยที่
เข้ำมำรักษำ หรือ ลำดับกำรมำก่อนหลังในกำรมำรักษำ
• ตัวอย่ำงเช่น ถ้ำในกรณีท่มี นี ำย ก เข้ำมำรักษำที่ห้องฉุ กเฉินด้วยอำกำรไส้ติ่งอักเสบ
อย่ำงรุนแรง แต่ต้องรอนำย ข ที่มำที่ห้องฉุ กเฉินเพื่อเอำเศษไม้ท่ตี ิดอยู่ในแขนออก
เนื่องจำกมำถึงห้องฉุกเฉินก่อนนำย ก
o ในกรณีน้ีเจ้ำหน้ำทีห่ อ้ งฉุ กเฉินต้องพิจำรณำควำมเร่งรีบทีต่ ้องรักษำนำย ก หรือ
นำย ข ก่อน
o เรียกกรณีน้ีเรียกว่ำ ลำดับควำมสำคัญ (Priority) ของคนไขทีร่ อกำรรักษำ และ
เมือ่ จัดลำดับควำมสำคัญแล้ว
o ขัน้ ตอนต่ อ ไปคุ ณ หมอจะรัก ษำคนไขที่ม ีล ำดับ ควำมส ำคัญ สูง สุ ด ที่ ไ ด้จ ำกกำร
จัดลำดับควำมสำคัญในกำรรักษำจำกเจ้ำหน้ำทีห่ อ้ งฉุกเฉิน
3
ลำดับควำมสำคัญของคิว (Priority Queue)
ค่ำของลำดับควำมสำคัญ (Priority value)
• จำกตัวอย่ำงกำรจัดลำดับควำมสำคัญของคนไข้ในกำรรักษำ หรือ ลำดับควำมสำคัญของ
งำนทีจ่ ะต้องทำก่อนทำหลัง
• จะรูไ้ ด้อย่ำงไรว่ำควรจะมีจำนวนของลำดับควำมสำคัญเท่ำไรถึงจะเหมำะสมในงำนนัน้ ซึง่
จำนวนของลำดับควำมสำคัญนัน้ จะขึน้ อยู่กบั ควำมต้องกำรในแต่ละงำนว่ำต้ องมีจำนวน
ลำดับควำมสำคัญเท่ำไร
• ทรำบเพียงว่ำค่ำของลำดับควำมสำคัญทีม่ ำกทีส่ ุดจะหมำยถึงมีควำมสำคัญสูงสุด
• ADT คิวของลำดับควำมสำคัญ (Priority queue)
1.
2.
3.
4.
Create an empty priority queue. (สร้ำงคิวของลำดับควำมสำคัญ)
Determine whether a priority queue is empty. (สนใจเมือ่ คิวของลำดับควำมสำคัญว่ำงเปล่ำ)
Insert a new item into a priority queue. (เพิม่ ข้อมูลใหม่ในคิวของลำดับควำมสำคัญ)
Retrieve and then delete the item in a priority queue with the highest priority value. (กำรนำ
ข้อมูลกลับคืนและกำรลบข้อมูลในคิวของลำดับควำมสำคัญจะทำในตำแหน่งข้อมูลทีม่ ี ลำดับควำมสำคัญ
สูงทีส่ ดุ )
4
ลำดับควำมสำคัญของคิว (Priority Queue)
ค่ำของลำดับควำมสำคัญ (Priority value)
• โค้ดรหัสเทียมลำดับควำมสำคัญของคิวลำดับควำมสำคัญ
//PQItemType เป็ นชนิดของข้อมูลทีเ่ ก็บไว้ในคิวของลำดับควำมสำคัญ
+createPQueue()
//สร้ำงคิวของลำดับควำมสำคัญ
+pqIsEmpty():boolean
//สนใจเมือ่ คิวของลำดับควำมสำคัญว่ำงเปล่ำ
+pqInsert(in newItem:PQItemType) throws Exception
//เพิม่ ข้อมูลเข้ำไปในคิวของลำดับควำมสำคัญจะเกิดควำมผิดพลำดเมือ่ คิวของลำดับควำมสำคัญเต็ม
+pqDelete():PQIemType
//กำรนำข้อมูลกลับคืนและลบข้อมูลในคิวของลำดับควำมสำคัญในตำแหน่งคิวทีม่ ลี ำดับควำมสำคัญสูงทีส่ ดุ
5
เครือ่ งมือทีใ่ ช้สร้ำงคิวของลำดับควำมสำคัญ
โครงสร้ำงอำร์เรย์
• อำร์เรย์เป็ นโครงสร้ำงข้อมูลทีน่ ำมำใช้สร้ำงคิวของลำดับควำมสำคัญได้อย่ำงมี ประสิทธิภำพ เพื่อ
จัดเรียงลำดับควำมสำคัญของข้อมูล
• ข้อมูลทีม่ ลี ำดับควำมสำคัญสูงทีส่ ดุ จะอยูท่ ต่ี ำแหน่ งสุดท้ำยของอำร์เรย์
• เมื่อต้องกำรนำข้อมูลออกไปใช้งำน จะใช้ในตำแหน่ ง items[size - 1] และลบข้อมูลในคิวของ
ลำดับควำมสำคัญด้วยเมธอด/ฟงั ก์ชนั pqDelete โดยจำนวนข้อมูลในคิวหรือขนำดของคิว คือ
ตัวแปร size
• ส่วนเมธอด/ฟงั ก์ชนั pqInsert จะเป็ นกำรเพิม่ ข้อมูลในคิวของลำดับควำมสำคัญในตำแหน่ งที่
เหมำะสม
• เช่นต้องกำรเพิม่ ข้อมูล 85.5 ในคิวของลำดับควำมสำคัญ ข้อมูล 85.5 จะอยู่ระหว่ำงข้อมูล 80 และ
85.9 เป็ นต้น ดังแสดงโครงสร้ำงอำร์เรย์เก็บคิวของลำดับควำมสำคัญในรูปที่ 10-1
6
เครือ่ งมือทีใ่ ช้สร้ำงคิวของลำดับควำมสำคัญ
โครงสร้ำงลิงค์ลิสต์
• กำรใช้ลงิ ค์ลสิ ต์ในกำรสร้ำงคิวของลำดับควำมสำคัญ ข้อมูลทีม่ ลี ำดับควำมสำคัญมำกทีส่ ุดจะ
อยูต่ ดิ กับส่วนหัวของลิงค์ลสิ ต์ และเรียงลำดับควำมสำคัญลงไปเลื่อยๆ
• ในกำรลบข้อมูลในคิว (pqDelete) จะคืนค่ำในตำแหน่ งที่ pqHead และเปลีย่ นกำรอ้ำงอิง
pqHead ไปยังโหนดถัดไป
• ส่วน pqInsert จะท่องเข้ำไปในลิงค์ลสิ ต์ก่อน เมือ่ เจอตำแหน่งทีเ่ หมำะสมในกำรเพิม่ ข้อมูลจึง
แทรกข้อมูลเข้ำไปในตำแหน่งนัน้
7
เครือ่ งมือทีใ่ ช้สร้ำงคิวของลำดับควำมสำคัญ
โครงสร้ำงไบนำรีทรี
• กำรใช้ไบนำรีทรีในกำรสร้ำงคิวของลำดับควำมสำคัญ ข้อมูลในตำแหน่งของโหนดทีม่ คี วิ
ของลำดับควำมสำคัญมำกทีส่ ุดจะเป็ นลูกทำงขวำสุดของไบนำรีทรี
• กำรลบข้อมูลในคิวของลำดับควำมสำคัญจะคืนค่ำในตำแหน่งขวำสุดของทรี และลบ
โหนดในทรี
• ส่วน pqInsert จะเพิม่ ข้อมูลตำมหลักกำรเพิม่ ข้อมูลในไบนำรีทรี
8
ฮีพ (Heap)
• ฮีพเป็ นรูปแบบทีเ่ หมือนกับไบนำรีทรี
• ข้อแตกต่ำงระหว่ำงฮีพกับไบนำรีทรีอยู่ 2 ประกำร คือ
1. ไบนำรีทรีจะจัดเรียงข้อมูลตำมลำดับกำรเข้ำมำ ส่วนฮีพจะจัดเรียงตำมควำมสำคัญ
ของข้อมูล ซึง่ เป็ นคุณสมบัตทิ เ่ี หมำะสมสำหรับคิวของลำดับควำมสำคัญ
2. ไบนำรีจะมีรปู ทรงทีม่ คี วำมหลำกหลำย แต่ฮพี จะเป็ นไบนำรีทรีแบบสมบูรณ์เสมอ
• ฮีพมีโครงสร้ำงกำรเก็บข้อมูล 2 รูปแบบ คือ Max-heap และ Min-heap ซึง่ เป็ นกำร
พิจำรณำตำมควำมสัมพันธ์ระหว่ำงข้อมูลโหนดพ่อแม่กบั ข้อมูลโหนดลูก ดังนี้
o Max-heap โหนดพ่อแม่จะมีขอ้ มูลมำกกว่ำข้อมูลของโหนดลูก ดังแสดงในรูป a
o Min-heap โหนดพ่อแม่จะมีขอ้ มูลน้อยกว่ำข้อมูลของโหนดลูก ดังแสดงในรูป b
(a)
(b)
9
ฮีพ (Heap)
• โค้ดรหัสเทียมหลักกำรทำงำนของฮีพ
//HeapItemType เป็ นชนิดของข้อมูลทีเ่ ก็บไว้ในฮีพ
+createHeap()
//สร้ำงฮีพ
+heapIsEmpty():boolean
//สนใจเมือ่ ฮีพว่ำงเปล่ำ
+heapInsert(in newItem:HeapItemType) throws Exception
//เพิม่ ข้อมูลเข้ำฮีพจะเกิดควำมผิดพลำดเมือ่ ฮีพเต็ม
+heapDelete():HeapIemType
//กำรลบและกำรคืนข้อมูลในตำแหน่งฮีพรำก ซึง่ เป็ นข้อมูลทีม่ ำกทีส่ ดุ ของคีย์
10
ฮีพ (Heap)
กำรสร้ำงข้อมูลในฮีพ
• ฮีพเป็ นไบนำรีท รีแบบสมบูรณ์ ดังนัน้ สำมำรถใช้อำร์เรย์มำสร้ำงฮีพได้ ถ้ำรู้จำนวนคีย์ท่ี
ต้องกำรใช้ในฮีพ
• ในกำรนำอำร์เรย์มำเก็บข้อมูลฮีพจะประกอบด้วย
o ตัวแปร items คือ อำร์เรย์เก็บข้อมูลฮีพ
o ตัวแปร size เก็บจำนวนของคียใ์ นฮีพว่ำมีเท่ำไร
ตัวอย่ำงที่ 10.1 โครงสร้ำงอำร์เรย์เก็บข้อมูลฮีพ
11
ฮีพ (Heap)
กำรลบคียใ์ นฮีพ
• ตำแหน่งทีจ่ ะลบคียใ์ นฮีพ หรือกำรนำข้อมูลออกจำกฮีพจะเป็ นตำแหน่งข้อมูลทีม่ คี ำ่ คียม์ ำกทีส่ ดุ คือข้อมูลในตำแหน่ง
โหนดรำก (กรณีเก็บข้อมูลในฮีพแบบ Max-heap)
• มีขนั ้ ตอนกำรลบข้อมูลในฮีพดังนี้
1. พิจำรณำตำแหน่งกำรลบข้อมูลในฮีพ ในตำแหน่งคียท์ ม่ี คี ำ่ มำกทีส่ ดุ คือ ข้อมูลในตำแหน่ งโหนดรำก ด้วยคำสัง่
rootItem = items[0]
2. ลบโหนดรำก ส่งผลทำให้ฮพี ถูกแยกออกเป็ นสองฮีพดังแสดงในรูป (b) ทำให้ตอ้ งนำโหนดทีต่ ำแหน่ งโหนดลูก
ของโหนดรำกทีถ่ ูกลบออกไปขึน้ มำแทนที่ โดยโหนดทีน่ ำมำแทนทีโ่ หนดทีถ่ ูกลบ คือ โหนดในตำแหน่งสุดท้ำย
ดังแสดงในรูปที่ (c) ด้วยขัน้ ตอนดังนี้
items[0] = items[size - 1] //คัดลอกข้อมูลในตำแหน่งสุดท้ำยมำไว้ในตำแหน่งโหนดรำก
--size
//ลดขนำดของฮีพ
3. เนื่องจำกฮีพเป็ นไบนำรีทรีทส่ี มบูรณ์ทำให้ทรียอ่ ยซ้ำยและขวำทัง้ คูก่ ย็ งั เป็ นฮีพ โดยจะเรียกโครงสร้ำงของทรียอ่ ย
นี้วำ่ ฮีพครึ่ง (Sime heap)
12
ฮีพ (Heap)
กำรลบคียใ์ นฮีพ
• จำกโครงสร้ำงฮีพครึง่ สิง่ ทีต่ อ้ งกำร คือ ต้องเปลีย่ นฮีพครึง่ ไปเป็ นฮีพ โดยอนุญำตให้ขอ้ มูลในตำแหน่งโหนดรำก
หรือคียใ์ นกำรค้นหำถูก เคลื่อนย้ำยลง (Trickle down) ไปในทรีแต่ไม่เกินขอบเขตของทรี และจะหยุดกำร
เคลือ่ นย้ำยตำแหน่งลงในโหนดเมือ่ คียใ์ นกำรค้นหำมำกกว่ำหรือเท่ำกับคียโ์ หนดลูกทุกโหนด
• กำรเปรียบเทียบเริม่ จำกโหนดรำกกับโหนดคียใ์ นกำรค้นหำของฮีพครึง่ ในตำแหน่งโหนดลูก ถ้ำตำแหน่งโหนด
รำกน้อยกว่ำโหนดคียใ์ นกำรค้นหำให้สลับตำแหน่งโหนดรำกกับโหนดลูก
13
ฮีพ (Heap)
กำรลบคียใ์ นฮีพ
ตัวอย่ำงที่ 10.2 โค้ดรหัสเทียมปรับฮีพครีง่ เป็ นฮีพ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+heapRebuild(inout items:ArrayType,in root:integer,in size:integer)
if(the root is not a leaf){
child = 2 * root + 1 //อ้างอิงตาแหน่ งโหนดลูกทางซ้ายของโหนดราก
if(the root has a right child){
rightChild = child + 1
if(items[rightChild] > items[child]){
child = rightChild
}
}
//ถ้าข้อมูลในโหนดรากน้อยกว่าค่าในโหนดลูกให้ทาการสลับข้อมูลกัน
if(items[root] < items[child]){
Swap items[root] and items[child]
heapRebuild(items,child,size)
}
}
//แต่ถา้ โหลดรากเป็ นข้อมูลในตาแหน่ งใบ ดังนัน
้ หยุดการสลับตาแหน่ง
• จำกโค้ดรหัสเทียมเปลีย่ นฮีพครึง่ เป็ นฮีพ นำมำยกตัวอย่ำงในกำรปรับฮีพครึง่ เป็ นฮีพในกำรเรียกใช้เมธอด
heapRebuid
14
ฮีพ (Heap)
กำรเพิ่มคียใ์ นฮีพ
• ข้อมูลใหม่ทเ่ี พิม่ เข้ำไปจะเพิม่ ในตำแหน่งล่ำงสุดของทรี
• แล้วเลือ่ นข้อมูลขึน้ ไปอยูใ่ นตำแหน่งทีเ่ หมำะสมดังแสดงกำรเพิม่ คียใ์ นฮีพในรูป
• ก่อนทีจ่ ะเพิม่ โหนดในฮีพจะต้องตรวจสอบก่อนว่ำข้อมูลทีจ่ ะเพิม่ เข้ำไปมีขอ้ มูลทีซ่ ้ำกับข้อมูลทีม่ อี ยูใ่ นทรีแล้ว
หรือไม่ (เป็ นคุณสมบัตขิ องไบนำรีทรีทไ่ี ม่ให้มขี อ้ มูลซ้ำกันในทรี) ถ้ำไม่ซ้ำให้เพิม่ ข้อมูลในทรีได้
• ตรวจสอบว่ำข้อมูลในฮีพเป็ นไปตำมโครงสร้ำงของฮีพ โดยจะเลือ่ นโหนดทีเ่ พิม่ เข้ำไปขึน้ ไปในทรีถำ้ โหนดพ่อ
แม่มขี อ้ มูลน้อยกว่ำข้อมูลใหม่ทเ่ี พิม่ เข้ำไปในทรี
ตัวอย่ำงที่ 10.3 โค้ดรหัสเทียมเพิม่ โหนดใหม่ในฮีพ
1
2
3
4
5
6
7
8
+ heapInsert(inout items:ArrayType,in newItem:integer,in
size:integer)
items[size] = newItem
//เลือ่ นโหนดใหม่ขน้ึ ในตาแหน่งทีเ่ หมาะสม
place = size
parent = (place-1)/2
while ((parent >= 0) and (items[place] > items[parent])){
Swap items[place] and items[parent]
place = parent
15
ฮีพ (Heap)
กำรเพิ่มคียใ์ นฮีพ
ตัวอย่ำงที่ 10.3 โค้ดรหัสเทียมเพิม่ โหนดใหม่ในฮีพ
1
2
+ heapInsert(inout items:ArrayType,in newItem:integer,in size:integer)
items[size] = newItem
//เลือ่ นโหนดใหม่ขน้ึ ในตาแหน่งทีเ่ หมาะสม
place = size
3
parent
= (place-1)/2
4
while ((parent >= 0) and (items[place] > items[parent])){
5
Swap items[place] and items[parent]
6
place = parent
7
parent = (place-1)/2
8
}//end
while
9
++size
10
16
สรุปเนื้อหำบทที่ 10
• การจัดลาดับความสาคัญของคิว คือ ข้อมูลที่มคี ่ามากที่สุดในกลุ่มข้ อมูลจะถือว่าเป็ น
ข้อมูลทีม่ คี วามสาคัญทีส่ ุด โดยโครงสร้างทีน่ าใช้เก็บข้อมูลคิวของลาดับความสาคัญคือ
อาร์เรย์ ลิงค์ลสิ ต์ และไบนารีทรี
• ฮีพมีโครงสร้างเมือ่ กับไบนารีทรี และฮีพมีโครงสร้างการเก็บข้อมูล 2 แบบ คือ
o Max-heap ข้อมูลในโหนดพ่อแม่จะมีขอ้ มูลมากกว่าข้อมูลในโหนดลูก
o Min-heap ข้อมูลในโหนดพ่อแม่จะมีขอ้ มูลน้อยกว่าข้อมูลในโหนดลูก
• การลบข้อมูลออกจากฮีพ จะทาให้ขอ้ มูลฮีพทีถ่ ูกลบจะเป็ นฮีพครึง่ และให้ปรับฮีพ
ครึง่ กลับมาเป็ นฮีพเหมือนเดิม
• การเพิม่ ข้อมูลในฮีพต้องเพิม่ ในตาแหน่ งใบแล้วค่อยๆ ปรับคียใ์ ห้เป็ นโครงสร้างฮีพ
เหมือนเดิม
17