งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ

งานนำเสนอกำลังจะดาวน์โหลด โปรดรอ

คืออะไร? คือ queue ที่ access element ตามความสำคัญของตัว element นั้น

งานนำเสนอที่คล้ายกัน


งานนำเสนอเรื่อง: "คืออะไร? คือ queue ที่ access element ตามความสำคัญของตัว element นั้น"— ใบสำเนางานนำเสนอ:

1

2 คืออะไร? คือ queue ที่ access element ตามความสำคัญของตัว element นั้น
เช่นคนป่วยขาหักกับหลังหัก ถึงคนหลังหักมาทีหลังก็ควรถูกรักษาก่อน (ไม่งั้นได้เผาก่อนแน่) Printer queue จำนวนหน้าน้อยควรได้ก่อน คือคิว แต่จัดเรียงสมาชิกตามความสำคัญนั่นเอง คือคนสำคัญแซงคิวได้ ที่ให้จำนวนหน้าน้อยได้ก่อนก็เพื่อเพิ่ม อัตราการ output ให้ได้ดีที่สุด

3 Priority โดยทั่วไป ค่าน้อยถือว่าสำคัญกว่าค่ามาก (มี priority สูงกว่านั่นเอง) ถ้าสองตัวมีค่าเท่ากัน ก็น่าจะให้ตัวที่อยู่ในคิวมานานกว่าได้ไป การเปรียบเทียบค่า เราใช้ Comparable interface หรือ Comparator interface ค่าน้อยหรือค่ามากจะสำคัญกว่านั้นแล้วแต่จะมอง แต่ในทางทฤษฎีถือว่าค่าน้อยสำคัญกว่า ส่วนถ้ามีค่าเท่ากัน ตัวที่อยู่ในคิวมาก่อนก็ควรจะได้ชื่อว่าสำคัญกว่า เดี๋ยวจะทวนเรื่องการเปรียบเทียบอีกนิดหน่อยในหน้าต่อไป

4 เหมือน Comparable เพียงแต่มี
Comparator interface เหมือน Comparable เพียงแต่มี int compare(Object o1, Object o2) ต้องเป็น class เดียวกัน หรือ เป็นsubclass กัน ไม่งั้น throw CastCastException Output มาเป็นค่าลบถ้า o1 ถือว่ามีค่าน้อยกว่า o2 ค่าบวกถ้า o1 ถือว่ามีค่ามากกว่าo2 ค่า 0 ถ้า o1 ถือว่ามีค่าเท่ากับ o2

5 ตัว interface // Postcondition: รีเทิร์นจำนวนสมาชิกใน priority queue นี้ // Postcondition: รีเทิร์น true ถ้า priority queue นี้ไม่มีสมาชิก //ไม่งั้นก็รีเทิร์น false ต่อไปนี้เป็นตัวอย่างส่วนโครงสร้างของ priority queue แบบหนึ่ง เราจะใช้แบบนี้เป็นหลักเลย จะมี method ต่างๆที่ priority queue ควรมี เช่นหาจำนวนสมาชิกในคิว หาว่าคิวไม่มีสมาชิกหรือไม่ เติมสมาชิกใหม่ลงในคิว(อย่าลืมว่ามันจะจัดสมาชิกตามความสำคัญเอง) // Postcondition: element จะถูกเติมลงใน priority queue

6 // Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw
// NoSuchElementException // Postcondition: รีเทิร์นออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw // NoSuchElementException // Postcondition: เอาออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // ออกจากคิวและรีเทิร์นออบเจ็คต์นี้เป็นคำตอบของเมธอดด้วย นอกจากนี้ยังต้องมีการดูของที่หัวคิว และเอาของออกจากหัวคิวด้วย

7 วิธีการ implement มีหลายวิธี
ใช้คิวธรรมดา จะไม่ได้ prioriry อาร์เรย์ของคิว ก็ไม่ได้เพราะ priority อาจเยอะมาก ใช้ ArrayList เรียงสมาชิก getMin จะเป็น constant time add กับ removeMin จะใช้ linear time -ซึ่งยังช้าไป อาร์เรย์ของคิวคือมีแต่ละช่องเป็นลิสต์ที่เก็บของแต่ละ priority ไว้ แต่ถ้ามี priority จำนวนมากจะทำให้เปลืองที่มาก ถ้าใช้ arraylist จะทำให้เรียงสมาชิกได้ง่าย แต่ตอนเติมจะเสียเวลาหาตำแหน่งที่เติม และเสียเวลาเลื่อนอาร์เรย์ ตอนเอาออกจะเสียเวลาในการจัดอาร์เรย์(อาจมีการเลื่อนช่องเยอะ) ซึ่งแปรตามขนาดของข้อมูล

8 วิธีการ implement (ต่อ)
ใช้ LinkedList getMin กับ removeMin เป็น constant time add จะเป็น linear time Ok รับได้ ลองทำดู ถ้าใช้ linked list ตอนที่เอาของออกจะไม่ต้องทำอะไรเพิ่ม แค่ update pointer เพราะฉะนั้นเวลาในการ removeMin จะคงที่ แต่ตอนเติมของลงในคิวก็ต้องใช้เวลาหาช่องเติม

9 ใช้ Comparable โดย default
ตัวอย่างนี้เป็น Priority queue ที่สร้างจาก linked list ใช้ Comparable โดย default

10 จะเห็นว่าเราใช้ method ของลิสต์ได้เยอะเลย

11

12 ทำไม? ทำไมจึงต้องย้อน iterator ไปหนึ่ง
อย่าลืมว่าตอนที่ while loop exit ออกนั้น แม้จะได้ compare(element,itr.next()) <0 ก็ตาม ตัว itr.next(); ก็จะทำให้iterator เลื่อนไปอีกหนึ่งตำแหน่งอยู่ดี ทำให้ถ้าแทรกสมาชิกใหม่โดยไม่ถอยหลัง จะเป็นการเติมสมาชิกใหม่เลยที่ที่ควรจะเป็นไปหนึ่งตำแหน่ง ส่วนที่เวลาเป็น O(n) ก็เพราะจำนวนลูปขึ้นอยู่กับ n ทำไม?

13 ทำไมต้อง previous ? ถ้าเรามี 1,2,4,5 และต้องการ add 3
Loop จะหยุดเมื่อ itr.next() เป็น 4 แต่ตัว iterator ได้เลื่อนไปที่ 5 ซะแล้ว ดังนั้น ต้อง previous() กลับมา ก่อนที่จะใส่ 3 หน้านี้เป็นตัวอย่างว่าทำไมต้องใช้ previous

14 ถ้า comparator = null, return elem1.compareTo (elem2);
protected int compare (Object elem1, Object elem2) { return (comparator==null ? ((Comparable)elem1).compareTo(elem2) : comparator.compare (elem1, elem2)); } // method compare ถ้า comparator = null, return elem1.compareTo (elem2); ถ้าไม่งั้น return comparator.compare (elem1, elem2); ถ้าไม่ได้กำหนด comparator ให้ใช้การ compare ของ Comparable interface โดยตัว object ที่เราเอามาเปรียบเทียบกันจะต้อง implement Comparable interface ส่วนถ้ามี comparator ให้ใช้ method ของ comparator ตัวนั้น

15 คราวนี้ใช้เซตบ้าง ดูแผ่นถัดไป

16 หน้านี้เป็นการใช้เซตทำ priority queue โครงสร้างจริงๆคือ treeset และมีการกำหนดตัว comparator ด้วย
ตัว constructor ก็รับ comparator เป็น input

17 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. เราไม่รู้ว่า setเก็บของยังไง รู้แต่ว่ามันเป็น treeset ซึ่งเป็นต้นไม้ ดังนั้นเวลาจึงอยู่ในรูปแบบของ log ส่วน method ต่างๆนั้นเรียกใช้ของ set ได้เลย

18 อีกวิธีนึง คราวนี้ใช้ Heap
ppublic class Heap implements PriorityQueue { ยังไม่อยู่ใน JAVA COLLECTIONS FRAMEWORK ต่อไปจะ implement โดยใช้ heap เดี๋ยวมาดูกันว่า heap คืออะไร

19 Complete Binary tree ยังจำได้หรือไม่
Complete binary tree คือ tree ที่เต็มทุกระดับ ยกเว้นระดับของใบ ซึ่งระดับของใบนี้ จะต้องถูกเติมจากซ้ายไปขวาเท่านั้น จะไม่มีรูว่างเป็นหย่อมๆ

20 Heap คือ complete binary tree
ซึ่งเป็น empty tree หรือ สมาชิกใน root มีค่าน้อยที่สุด (เรียกว่า minHeap) และ left กับ right subtree ก็เป็น heap ด้วย (ไม่ใช่ binary search tree นะ) อย่าลืมว่า min จะอยู่ที่ root เพราะฉะนั้น ยังไงก็ไม่ใช่ binary search tree

21 นี่คือตัวอย่างของ heap จะเห็นว่าค่าน้อยที่สุดจะอยู่ที่ root เสมอไม่ว่าจะเป็น subtree ใดๆ

22 Complete binary tree เอาใส่อาร์เรย์ได้
ง่ายต่อการหา child, parent มีข้อสังเกตที่ดีมากอย่างหนึ่ง นั่นคือ complete binary tree เก็บในอาร์เรย์ได้ง่าย หา parent กับ child ของ node ต่างๆได้ด้วยการใช้ index ดังนั้น heap ก็สามารถเก็บในอาร์เรย์ได้ง่ายเช่นเดียวกัน ในรูปคือ heap จากหน้าที่แล้ว นำมาทำเป็นอาร์เรย์

23 ก่อนอื่นดูการใช้ Heap (GPA น้อยสุดถือว่า highest priority)
ก่อนจะดูวิธีการทำ heap และจัดของใน heap เรามารู้วิธีใช้กันก่อนดีกว่า ตัวอย่างนี้เป็น heap ของข้อมูลนักเรียน โดยให้คนเกรดน้อยมีความสำคัญ ให้ดูส่วนที่ขีดเส้นใต้เท่านั้น ส่วนอี่นๆเป็นแค่ส่วนประกอบที่ให้โปรแกรมทำงานได้เท่านั้น

24 หน้านี้ไม่มีอะไร เป็นแค่ constructor

25 โปรแกรมเป็นโปรแกรมที่เติมนักเรียนหนึ่งคน ซึ่งมีชื่อตาม input s ลงใน heap
ถ้า s ไม่ใช่ sentinel (ค่าที่บอกว่าเลิกรับ input ได้แล้ว) ก็ให้เติมนักเรียนลงใน heap โดยใช้เมธอด add ถ้าเป็น sentinel ให้เคลียร์ heap แล้ว output สิ่งที่อยู่ใน heap ทั้งหมดลงบนจอภาพ โดยวนลูปเรียกเมธอด removeMin เราก็จะได้รายชื่อของนักเรียนโดยคนไม่เก่งจะมีชื่อก่อน

26 // this Student ออบเจ็คต์นั้นน้อยกว่า เท่ากัน หรือมากกว่า GPA ของ o1
// มี constructor ที่รับ string เป็น input และก็มีเมธอด toString ด้วย เวลาทำอย่าลืม // Postcondition: รีเทิร์นจำนวนเต็มที่ < 0, = 0, หรือ > 0 ขึ้นอยู่กับว่า GPA ของ // this Student ออบเจ็คต์นั้นน้อยกว่า เท่ากัน หรือมากกว่า GPA ของ o1 หน้านี้เป็นเมธอด compareTo ของนักเรียน โดยเราดู GPA เป็นหลัก

27 คราวนี้ดู Heap เลย Heap ที่เราทำนี้เป็นอาร์เรย์ที่เก็บ complete binary tree นั่นเอง

28 index ของลูกได้แบบนี้
ถ้า node ใดมี index เป็น j ลูกข้างซ้ายจะเป็น node ที่ 2j+1 ลูกข้างขวาจะเป็น node ที่ 2j+2

29 index ของพ่อได้แบบนี้
ถ้าลูกมี index j หรือ j+1 (สำหรับลูกทางขวา) Parent จะมี index (j-1)/2

30 ดู method ใน Heap Constructor ก็แค่สร้างตัวอาร์เรย์ขึ้นมา

31 // Postcondition: element ถูกเติมเป็นสมาชิกของ heap
// เวลา worst case = O(n) // ส่วนเวลาเฉลี่ยเป็นค่าคงที่ ถ้าเต็มอาร์เรย์ ก็ขยาย ขึ้นกับเวลา percolateUp O(n) เกิดจากการขยายอาร์เรย์ (ในการก็อปปี้อาร์เรย์นั้นเราดึงเอาเมธอดของ system มาใช้) เวลาเฉลี่ยนั้นขึ้นกับ percolateUp ดังนั้นเดี๋ยวเราค่อยดูที่ percolateUp อย่าลืมว่าพอทำเสร็จแล้ว heap ก็ยังเป็น heap อยู่ //เติมลงไปท้ายอาร์เรย์ //แล้วค่อยปรับเลื่อนตำแหน่งขึ้นมา

32 สมมติว่าเราจะเติม 30 ลงไป
สมมติว่าตอนนี้เราเติมสมาชิกใหม่ลงท้ายอาร์เรย์แล้ว ต่อไปเป็นตัวอย่างการ percolateUp 30

33 Percolate up คือ... สลับที่ 30 กับพ่อของเขาเรื่อยๆจนกว่าตัวพ่อจะน้อยกว่า พอทำเสร็จเราก็จะได้ heap นี่คือหลักของการ percolateUp

34 ต่อไปเป็นตัวอย่างการเลื่อนให้ดู

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

36 ความสูงของต้นไม้ เพราะเวลาแย่สุดเกิดตอนที่ต้องเลื่อนจนถึงยอด
// 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 ความสูงของต้นไม้ เพราะเวลาแย่สุดเกิดตอนที่ต้องเลื่อนจนถึงยอด หน้านี้คือโค้ดของ percolateUp จะเห็นว่าเป็นการลูปสลับที่ลูกกับพ่อไปเรื่อยๆ จะออกจากลูปก็เมื่อเจอพ่อซึ่ง น้อยกว่าหรือเท่ากับลูก ในที่นี้ใช้อาร์เรย์ แต่ง่ายเพราะว่าการหา index ของ parent นั้นตายตัว

37 Average time -percolateUp
ก็ต้องให้ครึ่งหนึ่งของสมาชิกทั้งหมดมีค่ามากกว่าตัวใหม่ แต่ครึ่งที่มากก็เป็นใบแน่ๆ ฉะนั้นในการสลับที่ขึ้นเพื่อให้เป็น heap ก็ใช้ไม่กี่ขั้นตอน – constant time เวลาโดยเฉลี่ยคิดโดย สมมติว่าตัวที่เติมเข้าไปนี่มีค่าอยู่ตรงกลางของค่าทั้งหมด ดังนั้นต้องมีสมาชิกของอาร์เรย์ครึ่งหนึ่งที่มากกว่ามัน แต่เพราะเป็นต้นไม้ ดังนั้นครึ่งที่มากกว่านี้จะต้องอยู่ที่ใบแน่ๆ การ percolateUp จึงแค่ต้องเลื่อนให้พ้นระดับของใบเท่านั้น ดังนั้นจึงใช้แค่ 1หรือ 2 ครั้งเท่านั้น ดังนั้นจึงถือว่าเวลาคงที่

38 public Object getMin() {
  if (size == 0) throw new NoSuchElementException(“Empty”); return heap[0];  } // method getMin

39 removeMin() ถ้าไม่ระวัง
4 6 5 8 ต่อไปเป็นการเอาของออกจากหัวคิว (root) ซึ่งจะซับซ้อนกว่าการเติมของ เพราะอาจทำให้เสียรูปของ complete binary tree ถ้าเสียรูปเมื่อไหร่ยุ่งแน่นอน เพราะ percolateUp ซึ่งใช้การคำนวณ index ของ complete binary tree ก็จะเสียไปด้วย เสียความเป็น complete binary tree งั้นทำไงดี??

40 //เอาท้ายอาร์เรย์ใส่ที่ root
// Precondition: ต้องไม่เป็นคิวที่ว่าง ไม่งั้นจะ throw // NoSuchElementException // Postcondition: เอาออบเจ็คต์ตัวที่สำคัญที่สุดใน PriorityQueue นี้ // ออกจากคิวและรีเทิร์นออบเจ็คต์นี้เป็นคำตอบของเมธอดด้วย // เวลาที่แย่ที่สุดจะเป็น O(log n) ขึ้นกับ percolateDown หลักการคือสลับที่ root กับตัวท้ายสุดของอาร์เรย์ แล้วลดขนาดอาร์เรย์ (จริงๆไม่ได้ลดแต่ลดค่า size) เพื่อไม่ให้คนเห็น root ที่สลับไปท้ายอาร์เรย์ ยังไงขนาดของอาร์เรย์ที่เรานับเป็น heap ก็ต้องลดลงอยู่ดี เพราะเราเอาของออกนี่นา จากนั้นปรับอาร์เรย์ด้วยการเลื่อนตัวที่อยู่ที่ root ลงมายังตำแหน่งที่ถูกต้อง ซึ่งเราเรียกว่าการ percolateDown (ในที่นี้ให้เริ่มที่ index 0) สำหรับในบทที่ 12 ของหนังสือ Java Collection Framework จะเป็นเรื่อง heap sort ให้ทุกคนไปดูเพิ่มเติมได้ //เอาท้ายอาร์เรย์ใส่ที่ root //แล้วค่อยปรับเลื่อนตำแหน่ง

41 เมื่อ removeMin( ) ถูกเรียก 48 จะถูกสลับกับ 26
เมื่อ removeMin( ) ถูกเรียก 48 จะถูกสลับกับ 26 ส่วน size ก็จะถูกลดไปหนึ่ง จากนั้นก็จะ percolateDown

42 สลับ 48 กับลูกที่น้อยที่สุด
PercolateDown คือ สลับ 48 กับลูกที่น้อยที่สุด ทำจนกว่าจะสลับไม่ได้ พอทำเสร็จเราก็จะได้ heap อย่าลืมว่า 48 อยู่ที่ root แล้วในตอนจะเริ่ม percolateDown

43

44

45 ถึงตรงนี้ก็จะได้ heap

46 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เป็นลูกซ้ายไว้ก่อน ห้ามเป็นตัวสุดท้าย เพราะจะไม่มีพี่น้องทางขวาให้เทียบ ถ้าลูกขวาน้อยกว่า ก็ปรับ child ให้เป็นลูกขวา หลักการก็เหมือนกับ percolateUp คือวนลูปสลับ child กับ parent เรื่อยๆ จนสลับไม่ได้ก็ออกจากลูป แต่จะต้องทำการเลือกลูกที่น้อยที่สุดมาเป็น child เสมอ ส่วนเรื่องเวลานั้น Worst case ก็คือเมื่อต้องเลื่อนถึงใบ ดังนั้นจึงเป็น log n ตามความสูงของ tree Average case สมมติว่าตัวที่เติมเข้าไปนี่มีค่าอยู่ตรงกลางของค่าทั้งหมด ดังนั้นต้องมีสมาชิกของอาร์เรย์ครึ่งหนึ่งที่มากกว่ามัน แต่เพราะเป็นต้นไม้ ดังนั้นครึ่งที่มากกว่านี้จะต้องอยู่ที่ใบแน่ๆ การ percolatDown จึงต้องเลื่อนให้เกือบระดับของใบ ดังนั้นจึงเกือบเป็น worst case เลยทีเดียว ดังนั้นเวลาจึงเป็น log n ด้วย

47 ลองทำดู

48

49 มาดูปัญหา จะ compress file โดยไม่ให้เสียข้อมูลไปเลยได้อย่างไร
ให้ M เป็น ข้อมูลที่เราต้องการ compress สมมติว่ามันมีขนาด character โดยประกอบไปด้วย a ถึง e เท่านั้น ให้ E คือ version ที่ compress แล้ว

50 มาดูปัญหา (ต่อ) โดยปกติ 1 character จะใช้ 16 bit

51 ลองทำดู จำนวน bit ก็จะเหลือ 3 แสน
ในเมื่อเรารู้ว่ามีแค่ไม่กี่จำนวน เราก็กำหนดโค้ดเองได้ดังในแผ่นใส จำนวน bit ก็จะเหลือ 3 แสน

52 ลดได้อีกไหม? จำนวน bit ก็จะน้อยกว่า3แสน แต่ 001010 อาจเป็นได้ทั้ง
aababa หรือ cbda ก็ได้ อย่างนี้ถึงจะ compress ได้ แต่ก็ไม่มีทางตีความกลับคืนได้ เพราะความหมายไม่แน่นอน

53 แล้วจะให้ไม่มั่วได้ไง
ใช้ prefix-free encoding โดยสร้าง binary tree กิ่งซ้ายถือเป็น 0 กิ่งขวาถือเป็น 1 ให้ character อยู่ที่ใบ ดูตัวอย่างในหน้าถัดไป

54 จะไม่มี character ที่อยู่ path เดียวกันจากรากแน่นอน
b = 11 c = 00 d = 10 e = 011

55 ทำได้อีกแบบนะเนี่ย แล้วแบบไหนดี? ขึ้นกับว่า character นั้นเกิดบ่อยไหม
bit เยอะไม่ควรเกิดบ่อย นี่ก็เป็น a –e เหมือนกัน แล้วแบบไหนจะดีกว่า แนวคิดก็คือ ตัวอักษรที่แทนด้วยจำนวน bit เยอะๆ ไม่ควรจะมีในข้อความของเรามาก

56 สร้าง Huffman tree ซึ่งก็คือ binary tree ของรหัสนี่แหละ แต่ว่าสร้างโดยดูจากความถี่ในการเกิดของแต่ละ character เพื่อให้ตัวอักษรที่มีความถี่มากในข้อความของเรา ใช้จำนวน bit น้อยที่สุด

57 สมมติมีความถี่แบบนี้
a มี 5000 b มี 10000 c มี 20000 d มี 31000 e มี 34000

58 เอาคู่ (character,ความถี่)ใส่Priority Q
แต่ละ node ของ priority Q ก็มี left, right, parent ของมันเอง ตอนแรก คิวของเราจะเป็น (a:5000) (b: 10000) (c: 20000) (d: 31000) (e: 34000) ต่อไป สร้าง Huffman tree ล่ะ ต่อไปนี้เป็นการสร้าง huffman tree โดยใช้ priority queue มาช่วย

59 เอาสองตัวที่น้อยสุดออกจากคิว ตัวแรกเอามาเป็นกิ่งซ้าย ตัวที่สองมาเป็นกิ่งขวา ส่วนผลบวกของความถี่เราเอามาเป็นราก a b 15000 1 สำหรับ ( : 15000) ที่ใส่กลับเข้าไปนั้น มี tree ของมันเป็นสิ่งที่อยู่หน้าตัว : จากนั้นก็เอาผลใส่กลับลงใน priority Q ซึ่งจะกลายเป็น ( :15000) (c: 20000) (d: 31000) (e: 34000)

60 เอาสองตัวที่น้อยสุดออกจากคิว ทำเหมือนเดิม
a b 15000 c 35000 1 เมื่อเอาต้นไม้นี้กลับเข้า priority Q ตัวคิวจะกลายเป็น (d: 31000) (e: 34000) ( : 35000)

61 เอาสองตัวที่น้อยสุดออกจากคิว ทำเหมือนเดิม
d e 65000 1 นี่กลายเป็นอีก tree หนึ่งเลย เมื่อเอาต้นไม้นี้กลับเข้า priority Q ตัวคิวจะกลายเป็น ( : 35000) ( : 65000)

62 เอาสองตัวสุดท้ายออกจากคิว ทำเหมือนเดิม
a b 15000 c 100000 1 d e 65000 35000 ขั้นนี้ถือว่าเสร็จแล้ว ได้ huffman tree ตามต้องการ priority Q จะกลายเป็น (: )

63 ลองทำดู

64 Huffman เป็น Greedy Algorithm
เราเลือกสิ่งที่ดีที่สุดในระบบย่อย ในที่นี้คือเอา min ออกจาก tree มีผลต่อระบบใหญ่ ทำให้ได้ optimal solution ไปด้วย ในที่นี้คือได้ prefix-free code ที่ดีสุด หน้านี้เป็นแค่ความหมายของ greedy algorithm

65 จะเปลี่ยน input ที่ได้ให้เป็นรหัส Huffman ก่อนอื่นดู Entry ก่อนละกัน
Huffman class จะเปลี่ยน input ที่ได้ให้เป็นรหัส Huffman ก่อนอื่นดู Entry ก่อนละกัน ต่อไปลองมาดูโค้ดกัน

66 มีการกำหนดการเปรียบเทียบโดยใช้ความถี่ที่เกิดขึ้น
Code นั้นคือตัวรหัสที่ของ entry หนึ่งๆนั่นเอง

67 ต่อไปก็ทำอาร์เรย์ของใบ
เพื่อให้ access ได้เร็ว ดูให้ดี อย่าสับสน นี่คืออาร์เรย์ของใบนะ ไม่ใช่ของทั้งต้น อาร์เรย์ของใบเป็นคนละตัวกับ heap นะ

68 ตัวอย่างเช่น c มี index 99
ตัวข้างบน Entry ของ c คือ Entry ของ parent แต่มีแค่ reference ไป c เท่านั้นที่ถูกเก็บไว้ในอาร์เรย์ leafEntries เพราะตัว parent ไม่ใช่ใบ นี่คือหนึ่ง Entry

69 // Postcondition: ‘This’ Huffman object ถูก initialize
// Postcondition: ไฟล์ ที่ถูกกำหนดโดย s ถูกจัดการเรียบร้อย // Postcondition: priority queue ถูกสร้างจากข้อมูลของ input //file โดยเวลา worst case = O(n) ผมจะให้ดูหลักๆเท่านั้น พวกเราสามารถไปลองทำเองได้

70 // Postcondition: สร้าง huffman tree เวลาworst case นั้นคงที่
// Postcondition: คำนวณ huffman code ของแต่ละตัวอักษร // เวลาworst case นั้นคงที่ // Postcondition: Huffman codesและข้อความที่แปลงแล้วถูกจัดเก็บใส่ไฟล์ // เวลาworst case นั้น = O (n).

71 Fields ใน Huffman class
Gui priority queue file reader file writer input file name เก็บเพื่อให้เปิดไฟล์ได้ 2 ที คำนวณความถี่ encode ตัวข้อมูล boolean บอกว่ากำลังอ่านไฟล์ไหนอยู่

72

73 Method processInput สร้าง priority Q สร้าง Huffman tree สร้างตัวรหัส เก็บรหัสและตัวข้อความที่แปลงแล้วลงไฟล์

74 Method createPQ สร้าง leafEntries update freq field ของแต่ละ Entry
หลังจากนั้นก็สร้าง priority queue จากการดู freq

75 Method createHuffmanTree
Loop จนกว่า size ของ priority queue จะเหลือ 1 ทำเหมือนที่บอกไปแล้วเป๊ะๆ

76 Method calculateHuffmanCodes
Loop บน leafEntries แต่ละ Entry นั้น มีตัวแปรซึ่งเป็น empty string ดู parent แล้ว เติมเลขที่กำกับ parent ลงไปข้างหน้าของ string เรื่อยๆ (ภาษาอังกฤษเรียก prepend) ไล่ดูไปจนถึง root

77 ตัวอย่างการสร้างรหัส
ถ้ามีต้นไม้แบบซ้ายมือนี้ ดูหน้าถัดไป

78 รหัสของ f ลูปบันทึกย้อนจากใบต้นไม้
f มีค่า int เป็น 102 ดังนั้นเราจึง set ค่า leafEntries[102].code = “1010”;

79 Method saveToFile Loop บน leafEntries แล้วก็อ่าน input file อีกที
ส่ง character กับ code ของมันไปที่ไฟล์ แล้วก็อ่าน input file อีกที รหัสของ input จะถูกสร้างขึ้น และ save ไว้ในไฟล์

80 ดู web เพิ่มได้

81 ถ้ามี output file มา ลองสร้าง Huffman tree ดูและบอกข้อความที่แท้จริง
ตัวข้อความคือเลข 0101 ต่อกันยาวๆสองบรรทัดสุดท้าย

82 จบเรื่อง priority queue


ดาวน์โหลด ppt คืออะไร? คือ queue ที่ access element ตามความสำคัญของตัว element นั้น

งานนำเสนอที่คล้ายกัน


Ads by Google