820 likes | 1.03k Views
คืออะไร?. คือ queue ที่ access element ตามความสำคัญของตัว element นั้น เช่นคนป่วยขาหักกับหลังหัก ถึงคนหลังหักมาทีหลังก็ควรถูกรักษาก่อน (ไม่งั้นได้เผาก่อนแน่) Printer queue จำนวนหน้าน้อยควรได้ก่อน. Priority. โดยทั่วไป ค่าน้อยถือว่าสำคัญกว่าค่ามาก (มี priority สูงกว่านั่นเอง)
E N D
คืออะไร? • คือ queue ที่ access element ตามความสำคัญของตัว element นั้น • เช่นคนป่วยขาหักกับหลังหัก ถึงคนหลังหักมาทีหลังก็ควรถูกรักษาก่อน (ไม่งั้นได้เผาก่อนแน่) • Printer queue จำนวนหน้าน้อยควรได้ก่อน
Priority • โดยทั่วไป ค่าน้อยถือว่าสำคัญกว่าค่ามาก (มี priority สูงกว่านั่นเอง) • ถ้าสองตัวมีค่าเท่ากัน ก็น่าจะให้ตัวที่อยู่ในคิวมานานกว่าได้ไป • การเปรียบเทียบค่า เราใช้ Comparable interface หรือ Comparator interface
Comparator interface • เหมือน Comparable เพียงแต่มี int compare(Object o1, Object o2) ต้องเป็น class เดียวกัน หรือ เป็นsubclass กัน ไม่งั้น throw CastCastException
ตัว interface // Postcondition: รีเทิร์นจำนวนสมาชิกใน priority queue นี้ // Postcondition: รีเทิร์น true ถ้า priority queue นี้ไม่มีสมาชิก //ไม่งั้นก็รีเทิร์น false // Postcondition: element จะถูกเติมลงใน priority queue
// Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw // NoSuchElementException // Postcondition: รีเทิร์นออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw // NoSuchElementException // Postcondition: เอาออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // ออกจากคิวและรีเทิร์นออบเจ็คต์นี้เป็นคำตอบของเมธอดด้วย
วิธีการimplement มีหลายวิธี • ใช้คิวธรรมดา จะไม่ได้ prioriry • อาร์เรย์ของคิว ก็ไม่ได้เพราะ priority อาจเยอะมาก • ใช้ ArrayListเรียงสมาชิก • getMin จะเป็นconstant time • add กับremoveMin จะใช้ linear time -ซึ่งยังช้าไป
วิธีการimplement(ต่อ) • ใช้ LinkedList • getMin กับ removeMin เป็น constant time • add จะเป็น linear time • Ok รับได้ ลองทำดู
ใช้ Comparable โดย default
ทำไมต้องprevious ? • ถ้าเรามี 1,2,4,5 และต้องการ add 3 • Loop จะหยุดเมื่อ itr.next() เป็น 4 • แต่ตัว iterator ได้เลื่อนไปที่ 5 ซะแล้ว • ดังนั้นต้อง previous() กลับมา ก่อนที่จะใส่ 3
protected int compare (Object elem1, Object elem2) { return (comparator==null ? ((Comparable)elem1).compareTo(elem2) : comparator.compare (elem1, elem2)); } // method compare ถ้าcomparator = null, returnelem1.compareTo (elem2); ถ้าไม่งั้น returncomparator.compare (elem1, elem2);
คราวนี้ใช้เซตบ้าง • ดูแผ่นถัดไป
public void add (Object element) { set.add (element); } // method add public Object getMin ( ) { return set.first( ); } // method getMin public Object removeMin ( ) { Object temp = set.first( ); set.remove (set.first( )); return temp; } // method removeMin ทั้ง 3 method นี้มี worstTime(n) เป็น LOGARITHMIC ของ n.
อีกวิธีนึง คราวนี้ใช้Heap ppublic class Heap implements PriorityQueue{ ยังไม่อยู่ใน JAVA COLLECTIONS FRAMEWORK
Complete Binary tree ยังจำได้หรือไม่
Heap คือ complete binary tree • ซึ่งเป็น empty tree หรือ • สมาชิกใน root มีค่าน้อยที่สุด (เรียกว่า minHeap) และ • left กับ right subtree ก็เป็น heap ด้วย • (ไม่ใช่ binary search tree นะ)
26 40 31 48 50 85 36 107 48 55 57 88 Complete binary tree เอาใส่อาร์เรย์ได้ ง่ายต่อการหา child, parent
ก่อนอื่นดูการใช้Heap (GPA น้อยสุดถือว่า highest priority)
// มี constructor ที่รับ string เป็น input และก็มีเมธอด toString ด้วย เวลาทำอย่าลืม // Postcondition: รีเทิร์นจำนวนเต็มที่ < 0, = 0, หรือ > 0 ขึ้นอยู่กับว่า GPA ของ // this Student ออบเจ็คต์นั้นน้อยกว่า เท่ากัน หรือมากกว่า GPA ของ o1
// Postcondition: element ถูกเติมเป็นสมาชิกของ heap // เวลา worst case = O(n) // ส่วนเวลาเฉลี่ยเป็นค่าคงที่ ถ้าเต็มอาร์เรย์ ก็ขยาย ขึ้นกับเวลา percolateUp //เติมลงไปท้ายอาร์เรย์ //แล้วค่อยปรับเลื่อนตำแหน่งขึ้นมา
สมมติว่าเราจะเติม 30 ลงไป 30
Percolate upคือ... สลับที่ 30 กับพ่อของเขาเรื่อยๆจนกว่าตัวพ่อจะน้อยกว่า พอทำเสร็จเราก็จะได้ heap
// Postcondition: จัด heap โดยเลื่อนตัวท้ายสุดขึ้นต้นไม้ เวลาที่แย่ที่สุดจะเป็น //O(log n) ส่วนเวลาเฉลี่ยจะเป็นค่าคงที่ protected void percolateUp() { int parent; int child = size-1; Object temp; while (child>0) { parent = (child-1)/2; if(compare(heap[parent],heap[child]) <=0) break; temp = heap[parent]; heap[parent] = heap[child]; heap[child] = temp; child = parent; } // while } // method percolateUp ความสูงของต้นไม้ เพราะเวลาแย่สุดเกิดตอนที่ต้องเลื่อนจนถึงยอด
Average time -percolateUp • ก็ต้องให้ครึ่งหนึ่งของสมาชิกทั้งหมดมีค่ามากกว่าตัวใหม่ • แต่ครึ่งที่มากก็เป็นใบแน่ๆ • ฉะนั้นในการสลับที่ขึ้นเพื่อให้เป็น heap ก็ใช้ไม่กี่ขั้นตอน – constant time
public Object getMin() { if (size == 0) throw new NoSuchElementException(“Empty”); return heap[0]; } // method getMin
4 4 8 8 5 6 6 5 removeMin() ถ้าไม่ระวัง เสียความเป็น complete binary tree งั้นทำไงดี??
// Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw // NoSuchElementException // Postcondition: เอาออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // ออกจากคิวและรีเทิร์นออบเจ็คต์นี้เป็นคำตอบของเมธอดด้วย // เวลาที่แย่ที่สุดจะเป็น O(log n) ขึ้นกับ percolateDown //เอาท้ายอาร์เรย์ใส่ที่ root //แล้วค่อยปรับเลื่อนตำแหน่ง
26 107 48 เมื่อremoveMin( )ถูกเรียก 48 จะถูกสลับกับ 26 ส่วน size ก็จะถูกลดไปหนึ่ง จากนั้นก็จะ percolateDown 30 31 32 50 85 36
PercolateDown คือ สลับ 48 กับลูกที่น้อยที่สุด ทำจนกว่าจะสลับไม่ได้ พอทำเสร็จเราก็จะได้ heap
ตอนแรกให้ childเป็นลูกซ้ายไว้ก่อน protected void percolateDown(int start) { int parent = start; int child = 2*parent+1; Object temp; while (child<size) { if(child<size-1&&compare(heap[child],heap[child+1]) >0) child++; if (compare(heap[parent],heap[child]) <=0) break; temp = heap[child]; heap[child] = heap[parent]; heap[parent] = temp; parent = child; child= 2*parent+1; } // while } // method percolateDown // Postcondition:จัด heap โดยเลื่อนตัวบนสุดลงต้นไม้ // เวลาที่แย่ที่สุดและเวลาเฉลี่ยจะเป็น O(log n) ทั้งคู่ ห้ามเป็นตัวสุดท้าย เพราะจะไม่มีพี่น้องทางขวาให้เทียบ ถ้าลูกขวาน้อยกว่าก็ปรับ child ให้เป็นลูกขวา
มาดูปัญหา • จะ compress file โดยไม่ให้เสียข้อมูลไปเลยได้อย่างไร • ให้ M เป็น ข้อมูลที่เราต้องการ compress สมมติว่ามันมีขนาด 100000 character โดยประกอบไปด้วย a ถึง e เท่านั้น • ให้ E คือ version ที่ compress แล้ว
มาดูปัญหา (ต่อ) • โดยปกติ 1 character จะใช้ 16 bit • ฉะนั้น 100000 character -_-’’ก็คูณเข้าไปดิ • ต้องหาทางลดจำนวน bit