1 / 25

แถวคอย ( Queue)

แถวคอย ( Queue). หัวข้อ. นิยามแถวคอย และอินเตอร์เฟส Queue การสร้างแถวคอยด้วยอาเรย์ ตัวอย่างการใช้งานแถวคอย ที่พักข้อมูล การเรียงลำดับแบบฐาน การค้นคำตอบตามแนวกว้าง การหาวิถีสั้นสุด. enqueue. dequeue. A. C. B. A. X. การเพิ่ม / ลบข้อมูลในแถวคอย.

taro
Download Presentation

แถวคอย ( Queue)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. แถวคอย(Queue)

  2. หัวข้อ • นิยามแถวคอย และอินเตอร์เฟส Queue • การสร้างแถวคอยด้วยอาเรย์ • ตัวอย่างการใช้งานแถวคอย • ที่พักข้อมูล • การเรียงลำดับแบบฐาน • การค้นคำตอบตามแนวกว้าง • การหาวิถีสั้นสุด

  3. enqueue dequeue A C B A X การเพิ่ม/ลบข้อมูลในแถวคอย • ข้อมูล เข้าก่อน ออกก่อน (First-In First-Out)

  4. แถวคอย : Queue public interface Queue { public boolean isEmpty(); public int size(); public void enqueue(Object e); public Object peek(); public Object dequeue(); } A A B C * * D E * * * B C * * D E * * * A B C D E

  5. Queue คล้าย List • Queue คือ list ที่เราเพิ่มปลายด้านหนึ่ง และลบที่ปลายอีกด้าน • สร้าง queue ด้วย list แบบง่าย ๆ public class ArrayListQueue implements Queue { private List list = new ArrayList(10); public boolean isEmpty() {return list.isEmpty();} public int size() {return list.size();} public void enqueue(Object e) {list.add(e);} public Object peek() { if (isEmpty()) throw new NoSuchElementException(); return list.get(0); } public Object dequeue() { Object e = peek(); list.remove(0); return e; } } enqueue เพิ่มท้าย list ใช้เวลา O(1) แต่ dequeue ลบหัว list ใช้เวลา O(n)

  6. Queue q; size elementData 0 q = new ArrayQueue(4); 1 A q.enqueue("A"); 2 A B q.enqueue("B"); ArrayQueue : สร้าง Queue ด้วยอาเรย์ 3 A B C q.enqueue("C"); q.dequeue(); 2 B C • เพิ่มที่ท้ายคิว ลบที่หัวคิว • ให้หัวคิวอยู่ที่ index 0 เสมอ • ตอนลบต้องใช้เวลา (n) (n)

  7. Queue q; size front elementData 2 0 A B q.enqueue("B"); 3 0 A B C q.enqueue("C"); q.dequeue(); 2 1 B C ArrayQueue : ตำแหน่งหัวคิวเปลี่ยนได้ q.dequeue(); 1 2 C • จำ index ของหัวคิว • ลบ : อย่าย้ายข้อมูล แต่ใช้วิธีการเลื่อนตำแหน่งหัวคิว (1)

  8. ArrayQueue public class ArrayQueue implements Queue { private Object[] elementData; private int size; private int front; public ArrayQueue(int cap) { elementData = new Object[cap]; size = front = 0; } public boolean isEmpty() { return size == 0; } public int size() { return size; } ...

  9. size front elementData enqueue, peek, dequeue 2 1 B C 1 2 C public class ArrayQueue implements Queue { private Object[] elementData; private int size; private int front; ... public void enqueue(Object e) { // ... ขยายอาเรย์ ถ้าเต็ม elementData[front + size] = e; size++; } public Object peek() { if (isEmpty()) throw new NoSuchElementException(); return elementData[front]; } public Object dequeue() { Object e = peek(); elementData[front++] = null; size--; return e; } ...

  10. size size front front elementData elementData 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 A X X Y Y Z Z 4 3 5 5 3 4 2 5 X 3 4 Y มองอาเรย์เป็นวงวน 2 5 1 6 X Z Y 0 7 1 6 A Z 0 7 • ถ้าตัวท้ายคิวอยู่ท้ายอาเรย์เติมตัวใหม่ไม่ได้ • มองอาเรย์ให้เป็นแบบวงวนจะใช้เนื้อที่ได้เต็มที่ q.enqueue("A"); b = (front + size) % elementData.length; elementData[b] = e; size++;

  11. ArrayQueue : enqueue size front elementData 0 1 2 3 4 5 6 7 C D A B 4 2 A A B B C C D D X 4 5 0 0 public class ArrayQueue implements Queue { ... public void enqueue(Object e) { if (size == elementData.length) { Object[] a = new Object[2 * elementData.length]; for (int i = 0, j = front; i < size; i++, j = (j+1)%elementData.length) a[i] = elementData[j]; front = 0; elementData = a; } int b = (front + size) % elementData.length; elementData[b] = e; size++; }

  12. size front elementData 0 1 2 3 C D A B 4 3 ArrayQueue : dequeue C D A 3 0 public Object dequeue() { Object e = peek(); elementData[front] = null; front = (front + 1) % elementData.length; size--; return e; }

  13. ตัวอย่างการใช้ queue • เป็นที่พักข้อมูล • การเรียงลำดับแบบฐาน • การค้นคำตอบตามแนวกว้าง • การหาวิถีสั้นสุด • ...

  14. งานพิมพ์ threads mouse events ข้อมูล keyboard events packets ระบบปฏิบัติการ router ระบบปฏิบัติการ ฮาร์ดดิกส์ jvm เครื่องพิมพ์ ผู้ใช้ โปรแกรม ผู้ใช้ โปรแกรม network โปรแกรม การใช้แถวคอยเป็นที่พักข้อมูล ผู้ผลิตข้อมูล ผู้ใช้ข้อมูล

  15. เรียงเรียบร้อย Radix Sort 321 81 19 142 5 391 25 321 81 19 321 142 5 25 81 19 5 391 25 142 391 1 2 3 4 5 6 7 8 9 0 81 391 25 25 25 81 391 19 19 391 81 142 142 321 5 321 142 321 5 19 5

  16. ปัญหาคูณสามหารสอง • ให้จำนวนเต็ม v • เริ่มด้วย 1 จะต้องทำการ x3 และหรือ /2 (ปัดเศษทิ้ง) อย่างไร จึงมีค่าเท่ากับ v • เช่น • v = 10 = 1x3x3x3x3/2/2/2 • v = 31 = 1x3x3x3x3x3/2/2/2/2/2x3x3/2 • แก้ปัญหานี้อย่างไร ? • ขอเสนอวิธีลุยทุกรูปแบบ

  17. 0 3 9 4 27 13 2 81 12 6 243 36 39 40 การค้นตามแนวกว้าง ต้องการหา 39 1 3 /2 39 = 1  3  3  3 / 2  3

  18. value prev 3 3 1 9 ปมต่าง ๆ ระหว่างการค้น 3 /2 1 9 class Node { int value; Node prev; Node(int v, Node p) { this.value = v; this.prev = p; } public boolean equals(Object o) { if (!(o instanceof Node)) return false; return this.value == ((Node) o).value; } } สอง nodes เท่ากันก็เมื่อ values ทั้งสองเท่ากัน

  19. 1 0 3 9 4 27 13 2 81 12 ใช้ Set และ Queue • ใช้ queue เก็บเฉพาะ nodes ที่ยังไม่แตกกิ่ง • ใช้ set เก็บทุก nodes ที่เคยผลิต

  20. ตัวโปรแกรม public static void bfsM3D2(int target) { Set set = new ArraySet(100); Queue q = new ArrayQueue(100); Node v = new Node(1,null); // เริ่มด้วย 1 q.enqueue(v); set.add(v); while( !q.isEmpty() ) { v = (Node) q.dequeue(); if (v.value == target) break; Node v1 = new Node(v.value/2, v); // ลองหารสอง (ปัดเศษ) Node v2 = new Node(v.value*3, v); // ลองคูณสาม if (!set.contains(v1)) {q.enqueue(v1); set.add(v1);} if (!set.contains(v2)) {q.enqueue(v2); set.add(v2);} } if (v.value == target) showSolution(v); }

  21. 1 0 3 9 การแสดงผลลัพธ์ 4 27 13 81 2 12 static void showSolution(Node v) { if (v.prev != null) { showSolution(v.prev); System.out.print((v.prev.value / 2 == v.value) ? "/ 2" : " 3"); } else { System.out.print("1 "); } } 1  3  3 / 2  3

  22. การหาวิถีสั้นสุด -1 0 1 2 13 1 3 4 12 5 4 10 11 9 5 9 10 8 6 7 7 8 8 7 9 10

  23. 0 1 2 3 1 3 4 4 การใช้แถวคอยในการหาวิถีสั้นสุด 5 6 5 5 6 6 5 6 6 ใช้แถวคอยเก็บตำแหน่งของช่องที่รอขยาย class Pos { int row, col; Pos(int r, int c) {row = r; col = c;} }

  24. โปรแกรมหาวิถีสั้นสุด static void findPath(int[][] map, Pos source, Pos target) { map[source.row][source.col] = 0; // ต้นทาง map[target.row][target.col] = -1; // ปลายทาง Queue q = new ArrayQueue(map.length); q.enqueue(source); while (!q.isEmpty()) { Pos p = (Pos) q.dequeue(); if (p.row == target.row && p.col == target.col) break; expand(map, q, p.row + 1, p.col, map[p.row][p.col]+1); expand(map, q, p.row - 1, p.col, map[p.row][p.col]+1); expand(map, q, p.row, p.col + 1, map[p.row][p.col]+1); expand(map, q, p.row, p.col - 1, map[p.row][p.col]+1); } } static void expand(int[][] map, Queue q,int r,int c,int k){ if (r<0 || r>=map.length || c<0 || c>=map[r].length || map[r][c] != 0) return; map[r][c] = k; q.enqueue(new Pos(r, c)); }

  25. สรุป • ประยุกต์แถวคอยในการแก้ปัญหาหลากหลาย • การดำเนินการหลัก : enqueue / dequeue / peek • สร้างแถวคอยได้ง่ายด้วยอาเรย์ (มองแบบวงวน) • ถ้าจองขนาดให้เพียงพอ การทำงานทุกครั้งเป็น (1)

More Related