diff --git a/labs/priority_queues/README.md b/labs/priority_queues/README.md new file mode 100644 index 0000000..d650e33 --- /dev/null +++ b/labs/priority_queues/README.md @@ -0,0 +1,25 @@ +# Lab 10 — Priority Queues + +In this lab, you will use binary heaps to implement the priority queue container. Start by downloading the files: + +[priority_queue.h](priority_queue.h) [test_pq.cpp](test_pq.cpp) + +The code provided in these files is straightforward. test_pq.cpp is a driver and test program, while priority_queue.h is a skeleton implementation. Please take a careful look. You will complete the implementation and add to the main program in lab. In your implementation, be careful when subtracting 1 from an unsigned int whose value is 0; it is not -1! + +## Checkpoint 1: + +Implement and test the push (a.k.a. insert) and the check_heap functions. Recall that push depends on the percolate_up functionality. check_heap, which works either with the heap member variable or with a vector provided from the outside, determines if the vector is properly a heap, meaning that each value is less than or equal to the values of both of its children (if they exist). + +**To complete this checkpoint**: Show a TA or mentor your debugged implementation and discuss the running time of both insert and check_heap. + +## Checkpoint 2: + +Implement and test the pop (a.k.a. delete_min) function and the constructor that builds a valid heap from a vector of values that is in no particular order. Both of these depend on proper implementation of the percolate_down function. + +**To complete this checkpoint**: Show a TA or mentor these additions and the test output. + +## Checkpoint 3: + +Finally, write and test the non-member function that sorts a vector by doing a heap sort. This code should sort the data “in place” and not require a large scratch space (e.g., another vector or list or another priority queue) to store a copy of the data as it is being sorted. + +**To complete this checkpoint**: Show a TA or mentor your completed and debugged heap sort code. diff --git a/labs/priority_queues/priority_queue.h b/labs/priority_queues/priority_queue.h new file mode 100644 index 0000000..a4689ca --- /dev/null +++ b/labs/priority_queues/priority_queue.h @@ -0,0 +1,68 @@ +#ifndef priority_queue_h_ +#define priority_queue_h_ + +#include +#include +#include + + +template +class priority_queue { +private: + std::vector m_heap; + +public: + priority_queue() {} + + priority_queue( std::vector const& values ) + { + } + + const T& top() const + { + assert( !m_heap.empty() ); + return m_heap[0]; + } + + void push( const T& entry ) + { + } + + void pop() + { + assert( !m_heap.empty() ); + } + + int size() { return m_heap.size(); } + bool empty() { return m_heap.empty(); } + + + // The following three functions are used for debugging. + + // Check to see that internally the heap property is realized. + bool check_heap( ) + { + return this->check_heap( this->m_heap ); + } + + // Check an external vector to see that the heap property is realized. + bool check_heap( const std::vector& heap ) + { + } + + // A utility to print the contents of the heap. Use it for debugging. + void print_heap( std::ostream & ostr ) + { + for ( unsigned int i=0; i +void heap_sort( std::vector & v ) +{ +} + +#endif diff --git a/labs/priority_queues/test_pq.cpp b/labs/priority_queues/test_pq.cpp new file mode 100644 index 0000000..36f633e --- /dev/null +++ b/labs/priority_queues/test_pq.cpp @@ -0,0 +1,104 @@ +#include +#include + +#include "priority_queue.h" + + +int main() { + + priority_queue pq_int; + + std::cout << "****************\n" + << "* Checkpoint 1 *\n" + << "****************" << std::endl; + + std::vector heap_vector, empty_vector, one_vector; + one_vector.push_back( 4 ); + heap_vector.push_back( 2); heap_vector.push_back(11); heap_vector.push_back( 7); + heap_vector.push_back(13); heap_vector.push_back(29); heap_vector.push_back( 8); + heap_vector.push_back( 9); heap_vector.push_back(27); heap_vector.push_back(21); + heap_vector.push_back(37); heap_vector.push_back(40); heap_vector.push_back(16); + std::vector non_heap_vector( heap_vector ); + non_heap_vector[5] = 23; // less than its parent + + std::cout << "Testing if check_heap works." << std::endl + << "An empty vector is a heap. check_heap = " << pq_int.check_heap(empty_vector) << std::endl + << "A one-element vector is also a heap. check_heap = " + << pq_int.check_heap(one_vector) << std::endl + << "A manually constructed heap. check_heap = " << pq_int.check_heap(heap_vector) << std::endl + << "A change at one location creates a non-heap. check_heap = " + << pq_int.check_heap(non_heap_vector) << std::endl; + + pq_int.push( 5 ); + pq_int.push( 13 ); + pq_int.push( 3 ); + pq_int.push( 11 ); + pq_int.push( 6 ); + pq_int.push( 23 ); + pq_int.push( 8 ); + pq_int.push( 12 ); + + std::cout << "After 8 push operations the size is " << pq_int.size() << std::endl + << "The top, which should be 3, is " << pq_int.top() << std::endl + << "The call to pq.int.empty() returns " << pq_int.empty() << std::endl + << "pq_int.check_heap() = " << pq_int.check_heap() << std::endl; + + std::cout << "\nHere is the actual heap. Values should be 3, 6, 5, 12, 11, 23, 8, 13\n"; + pq_int.print_heap( std::cout ); + + /* + std::cout << "\n\n" + << "****************\n" + << "* Checkpoint 2 *\n" + << "****************" << std::endl; + + pq_int.pop(); + std::cout << "After one pop, the size should be 7. It is " << pq_int.size() << std::endl + << "and the top value should be 5. It is " << pq_int.top() << std::endl; + pq_int.pop(); pq_int.pop(); + std::cout << "After two more pops, the size should be 5. It is " << pq_int.size() << std::endl + << "and the top value should be 8. It is " << pq_int.top() << std::endl; + pq_int.push( 1 ); + std::cout << "Another push should make the top value 1. It is " << pq_int.top() << std::endl; + pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop(); + std::cout << "After six more pops, the pq should be empty. pq_int.empty() = " << pq_int.empty() << std::endl; + + std::vector v; + priority_queue pq_f(v); + std::cout << '\n' << "Now we are trying construction from a vector.\n" + << "When the vector is empty, here is the value of pq_f.empty() = " << pq_f.empty() << std::endl; + + v.push_back(13.5); v.push_back(11.1); v.push_back(11.1); v.push_back(-4); + v.push_back(14.3); v.push_back(4.5); v.push_back(8.5); v.push_back(27.6); + v.push_back(2.3); v.push_back(15.2); v.push_back(23.1); v.push_back(12.5); + priority_queue pq_float(v); + std::cout << "After constructing from a 12-value vector, the size is " << pq_float.size() << std::endl + << "the top, which should be -4 is " << pq_float.top() << std::endl + << "and check_heap returns " << pq_float.check_heap() << std::endl; + */ + + /* + std::cout << "\n\n" + << "****************\n" + << "* Checkpoint 3 *\n" + << "****************" << std::endl; + + heap_sort( v ); + int order_errors = 0; + for ( unsigned int i=0; i v[i+1] ) order_errors ++ ; + + std::cout << "After running heap sort, the size of the vector, which still should be 12 is " << v.size() + << "\nand there are " << order_errors << " ordering errors\n" + << "The resulting vector is\n"; + for ( unsigned int i=0; i