implementing heaps bounded priority queues
play

Implementing Heaps Bounded Priority Queues Priority queues : - PowerPoint PPT Presentation

Implementing Heaps Bounded Priority Queues Priority queues : Bounded Priority Queue Interface a type of work list that // typedef void* elem; // Decided by client typedef bool has_higher_priority_fn (elem e1, elem e2); o stores


  1. Implementing Heaps

  2. Bounded Priority Queues  Priority queues : Bounded Priority Queue Interface a type of work list that // typedef void* elem; // Decided by client typedef bool has_higher_priority_fn (elem e1, elem e2); o stores elements // typedef ______* pq_t; o gives back the one with the bool pq_empty(pq_t Q) /*@requires Q != NULL; @*/ ; highest priority bool pq_full(pq_t Q) /*@requires Q != NULL; @*/ ;  How big? pq_t pq_new(int capacity, has_higher_priority_fn* prio) /*@requires capacity > 0 && prio != NULL; @*/ o unbounded /*@ensures \result != NULL && pq_empty(\result); @*/ ; o bounded void pq_add(pq_t Q, elem e) /*@requires Q != NULL && !pq_full(Q) && e != NULL; @*/ /*@ensures !pq_empty(Q); @*/ ; elem pq_rem (pq_t Q) /*@requires Q != NULL && !pq_empty(Q); @*/ /*@ensures \result != NULL && !pq_full(Q); @*/ ; elem pq_peek (pq_t Q) /*@requires Q != NULL && !pq_empty(Q); @*/ /*@ensures \result != NULL && !pq_empty(Q); @*/ ; 1

  3. Priority Queues A priority queue viewed as a heap implemented as an array 1 2 2 3 2 4 4 7 8 9 4 8 4 5 6 7 4 9 0 1 2 3 4 5 6 7 8 9 2 4 8 7 4 9 2

  4. Heaps Invariants higher priority 1. Shape invariant 2. Ordering invariant o The priority of a child is lower than point of view of child or equal to the priority of its parent or equivalently o The priority of a parent is higher than point of view of parent or equal to the priority of its children 3

  5. Heap Operations  Insertion o place the new element in the leftmost open position in the last level to satisfy O(log n) the shape invariant o sift up to restore the ordering invariant  Removal o replace the root with the element in the rightmost filled position on the last level O(log n) to satisfy the shape invariant o sift down to restore the ordering invariant Strategy: • maintain the shape invariant • temporarily break and then restore the ordering invariant 4

  6. Implementing Bounded Heaps 5

  7. Concrete Type 0 1 2 3 4 5 6 next limit 2 4 8 7 4 9  The heap data structure needs to store o the array that contains the heap elements o its true size because we sacrifice index 0  that’s capacity + 1 o the position where to add the next element o the priority function typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL }; 6

  8. Basic Representation Invariants typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL };  We simply translate the field constraints o and preempt overflow because right child of i is 2i+1 bool is_heap_safe(heap* H) { return H != NULL and 2*(int_max()/2) + 1 == int_max() && 1 < H->limit && H->limit <= int_max()/2 && is_array_expected_length(H->data, H->limit) && 1 <= H->next && H->next <= H->limit && H->prior != NULL; }  This checks that basic heap manipulations are safe 7

  9. Heap Invariants Beyond basic safety, we need to check:  the shape invariant o this is automatic 1 2  elements are stored  level by level 2 3 4 8  from left to right 4 5 6 7 4 9 0 1 2 3 4 5 6 7 8 9 2 4 8 7 4 9  the ordering invariant higher priority 8

  10. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 The Ordering Invariant elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL };  The priority of a child is lower than or equal to the priority of its parent  The priority of a parent is higher than or equal to the priority of its children  Let’s introduce an abstraction o Reason about where a node belongs in the tree  not priorities This will also help with the confusion about min-heaps  not arrays  It’s Ok for node e1 to be the parent of e2 if Min-heap version: o e1 has priority higher than or equal to e2 value of e1 ≤ value of e2  but prior tests if a node has strictly higher priority than another o it is not the case that Min-heap version: e2 has strictly higher priority than e1 value of e2 < value of e1 9

  11. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 The Ordering Invariant elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL };  It’s Ok for node e1 to be the parent of e2 if o it is not the case that e2 has strictly higher priority than e1 bool ok_above(heap* H, int i1, int i2) H is safe //@requires is_heap_safe(H); //@requires 1 <= i1 && i1 < H->next; i1 and i2 are in bounds i1 and i2 are in bounds //@requires 1 <= i2 && i2 < H->next; { elem e1 = H->data[i1]; elem e2 = H->data[i2]; return !(*H->prior)(e2, e1); } 10

  12. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 The Ordering Invariant elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL };  The priority of every child is lower than or equal to the priority of its parent 1 2 o Every parent is Ok above its children 2 3 4 8 4 5 6 7 4 9 bool is_heap_ordered(heap* H) H is safe //@requires is_heap_safe(H); 0 1 2 3 4 5 6 7 8 9 { 2 4 8 7 4 9 for (int child = 2; child < H->next; child++) o The root of the tree is //@loop_invariant 2 <= child && child <= H->next; { at index 1 int parent = child/2; if (!ok_above(H, parent, child))  the first child is at index 2 return false; } return true; o Is this code safe? } 11

  13. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 The Ordering Invariant elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL };  Is this code safe? o H->next 1. bool is_heap_ordered(heap* H)  because H != NULL 2. //@requires is_heap_safe(H);  since is_heap_safe(H) 3. { for (int child = 2; child < H->next; child++) 4. o ok_above(H, parent, child) //@loop_invariant 2 <= child && child <= H->next; 5. { 6. int parent = child/2; 7. bool ok_above(heap* H, int i1, int i2) if (!ok_above(H, parent, child)) 8. //@requires is_heap_safe(H); return false; 9. //@requires 1 <= i1 && i1 < H->next; } 10. //@requires 1 <= i2 && i2 < H->next; return true; 11. 12. }  1 <= child && child < H->next  because 2 <= child by line 5  and child < H->next by line 4  1 <= parent && parent < H->next  because parent = child/2 by line 7  and 2 <= child && child < H->next  by lines 4 – 5 and math 12

  14. The Representation Invariant  A value of type heap must satisfy o the basic safety invariants o the shape invariant  automatic o the ordering invariant bool is_heap(heap* H) { return is_heap_safe(H) && is_heap_ordered(H); } 13

  15. Constant-time Operations 14

  16. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 pq_full, pq_empty, pq_peek elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL }; bool pq_full(heap* H) We can fill a bounded 1 2 //@requires is_heap(H); heap to the brim { 2 3 return H->next == H->limit; 4 8 O(1) } 4 5 6 7 4 9 bool pq_empty(heap* H) //@requires is_heap(H); 0 1 2 3 4 5 6 7 8 9 { 2 4 8 7 4 9 return H->next == 1; O(1) } elem pq_peek(heap* H) //@requires is_heap(H) && !pq_empty(H); We sacrificed We sacrificed //@ensures is_heap(H) && !pq_empty(H); index 0 index 0 { return H->data[1]; O(1) } 15

  17. typedef struct heap_header heap; struct heap_header { int limit; // == capacity + 1 pq_new elem[] data; // \length(data) == limit int next; // 1 <= next && next <= limit has_higher_priority_fn* prior; // != NULL }; 1 heap* pq_new(int capacity, has_higher_priority_fn* prior) 2 //@requires 0 < capacity && capacity <= int_max()/2 - 1; //@requires prior != NULL; 2 3 4 8 //@ensures is_heap(\result); O(1) { Overflow! Overflow! 4 5 6 7 4 9 heap* H = alloc(heap); H->limit = capacity + 1; H->next = 1; H->data = alloc_array(elem, H->limit); H->prior = prior; 0 1 2 3 4 5 6 7 8 9 2 4 8 7 4 9 return H; } o To preempt overflow, we must have 1 < H->limit && H->limit <= int_max()/2 but H->limit == capacity + 1 o so 0 < capacity && capacity <= int_max()/2 - 1 16

  18. Implementing pq_add 17

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend