10.10 Lab*: Heap ADT

Now that you have a working implementation of the Heap class, you will convert it to a template.

In this assignment we will create and process a heap of Customer objects. You are encouraged to reuse as much code as possible from previous assignments/labs.

The assignment consists of the following classes/files:

- Customer.cpp (incomplete)
- Customer.h (incomplete)
- Heap.h (template, incomplete)
- main.cpp (incomplete)

Project: An airline company uses the formula shown below to determine the priority of the passengers on the waiting list for overbooked flights.

Priority number = A / 1000 + B – C

Where

- A is the customer’s total mileage in the past year
- B is the customer’s number of years in the flier program
- C is the sequence number representing the customer’s arrival position when the flight was booked (the first customer’s sequence number is 1, second in the file is 2, and so on).

Two or more customers could have the same priority number. For instance, Robert Hill and Tom Martin have the same priority number:

Robert Hill’s priority number: 53000 / 1000 + 5 – 1 = 57
Tom Martin’s priority number: 56000/1000 + 5 – 4 = 57

Customers with the same priority number must be served on a first come first serve basis, therefore build the heap based on a unique serial number determined using the following formula:

serial number = priority * 100 + (100 – C)

In the above example:

Robert Hill’s serial number is: 57 * 100 + (100 – 1) = 5799
Tom Martin’s serial number is: 57 * 100 + (100 – 4) = 5796

Given a file with overbooked customers, write a program that reads the file and determines each customer’s priority number, serial number, and prints a list of waiting customers in priority sequence, including the total number of customers served/rejected. There are two types of lines in the input file: line that begins with 'A' or 'S':

- the letter 'A' represents the arrival of a new customer and it is followed by:
- the number of years in the frequent flier program,
- total mileage in the past year, and the
- name of the customer (see below).

A 5 53000 Robert Hill      // insert into the heap
A 3 89000 Amanda Trapp     // insert into the heap
A 3 90000 Jonathan Nguyen  // insert into the heap
S                          // delete from the heap and print
A 5 56000 Tom Martin       // insert into the heap

The letter 'S' stands for "Serve" and indicates that the next customer from the waiting list will be served (in priority sequence).

Finally, display the overbooked customers that did not get a plain ticket. For each overbooked customer display the number of years in the frequent flier program, total mileage in the past year, the serial number within (), and the name of the customer within [], as shown in the following example.

Example:

Input file name:
3 89000 (9098) [Amanda Trapp]
Served overbooked customers: 1

3 90000 (9097) [Jonathan Nguyen]
5 53000 (5799) [Robert Hill]
5 56000 (5796) [Tom Martin]
Rejected overbooked customers: 3
This commit is contained in:
Iurii Tatishchev 2024-05-29 22:16:05 -07:00
parent 0789614ef1
commit 701d84242d
Signed by: CaZzzer
GPG Key ID: 9A156B7DA6398968
10 changed files with 293 additions and 147 deletions

View File

@ -4,4 +4,4 @@ project(07_heaps)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
add_executable(07_heaps main.cpp add_executable(07_heaps main.cpp
Heap.cpp) )

13
07-heaps/Customer.cpp Normal file
View File

@ -0,0 +1,13 @@
/* *~*~*
Implementation file for the Customer class
Written By: Iurii Tatishchev
Changed by: Iurii Tatishchev
IDE: CLion
*~**/
#include <iostream>
#include <string>
#include "Customer.h"
using namespace std;
/* Write your code here */

44
07-heaps/Customer.h Normal file
View File

@ -0,0 +1,44 @@
/* *~*~*
Specification file for the Customer class
Written By: Iurii Tatishchev
Changed by: Iurii Tatishchev
IDE: CLion
*~**/
#ifndef CUSTOMER_H_
#define CUSTOMER_H_
#include <utility>
using std::string, std::ostream;
class Customer; // Forward Declaration
class Customer {
private:
int year;
int mileage;
int seq;
string name;
int priority;
int serial;
public:
Customer() : year(0), mileage(0), seq(0), name("") {};
Customer(int y, int m, int s, string n) : year(y), mileage(m), seq(s), name(std::move(n)) {
priority = mileage / 1000 + year - seq;
serial = priority * 100 + (100 - seq);
};
int getPriority() const { return priority; }
int getSerial() const { return serial; }
friend ostream &operator<<(ostream &os, const Customer &c) {
os << c.year << " " << c.mileage << " (" << c.getSerial() << ") [" << c.name << "]";
return os;
}
};
#endif

View File

@ -1,87 +0,0 @@
/* *~*~*
Implementation file for the Heap class: min- or max-heap of integers
Written By: Iurii Tatishchev
Changed by: Iurii Tatishchev
IDE: CLion
*~**/
#include <utility>
#include "Heap.h"
/* *~*~*
The private member function _reHeapUp rearranges the heap after insert by moving the
last item up to the correct location in the heap
*~**/
void Heap::_reHeapUp(int lastndx, int (compareFunc)(int, int)) {
// base case, newElement is heap's root
if (lastndx == 0) return;
int parentIndex = _findParent(lastndx);
// base case, newElement satisfies heap property
// min heap - child not less than parent
// max heap - child not greater than parent
if (compareFunc(heapAry[lastndx], heapAry[parentIndex]) != -1) return;
// swap and continue recursing
std::swap(heapAry[lastndx], heapAry[parentIndex]);
_reHeapUp(parentIndex, compareFunc);
}
/* *~*~*
The private member function _reHeapDown rearranges the heap after delete by moving the
data in the root down to the correct location in the heap
*~**/
void Heap::_reHeapDown(int rootdex, int (compareFunc)(int, int)) {
int maxChildIndex = -1;
int left = _findLeftChild(rootdex);
int right = _findRightChild(rootdex);
// if there is a left child
if (left != -1) {
// if there is a right child that is
// min heap - less than the left child
// max heap - greater than the left child
if (right != -1 && compareFunc(heapAry[right], heapAry[left]) == -1) maxChildIndex = right;
else maxChildIndex = left;
}
// base case, heap property satisfied
// min heap - children greater than parent
// max heap - children less than parent
if (maxChildIndex == -1 || compareFunc(heapAry[rootdex], heapAry[maxChildIndex]) == -1) return;
// swap and continue recursing
std::swap(heapAry[rootdex], heapAry[maxChildIndex]);
_reHeapDown(maxChildIndex, compareFunc);
}
/* *~*~*
The public member function insertHeap inserts a new item into a heap.
It calls _reheapUp.
*~**/
bool Heap::insertHeap(int newItem, int (compareFunc)(int, int)) {
if (isFull()) return false;
heapAry[count] = newItem;
_reHeapUp(count, compareFunc);
count++;
return true;
}
/* *~*~*
The public member function deleteHeap deletes the root of the heap and
passes back the root's data. It calls _reheapDown.
*~**/
bool Heap::deleteHeap(int &returnItem, int (compareFunc)(int, int)) {
if (isEmpty()) return false;
returnItem = heapAry[0];
heapAry[0] = heapAry[count - 1];
count--;
_reHeapDown(0, compareFunc);
return true;
}

View File

@ -8,15 +8,16 @@ IDE: CLion
#ifndef HEAP_H_ #ifndef HEAP_H_
#define HEAP_H_ #define HEAP_H_
template<typename T>
class Heap { class Heap {
private: private:
int *heapAry; T *heapAry;
int heapSize; int heapSize;
int count; int count;
void _reHeapUp(int lastndx, int (compareFunc)(int, int)); void _reHeapUp(int lastndx, int (compareFunc)(const T&, const T&));
void _reHeapDown(int rootndx, int (compareFunc)(int, int)); void _reHeapDown(int rootndx, int (compareFunc)(const T&, const T&));
int _findParent(int index) { return (index <= 0) ? (-1) : (index - 1) / 2; } int _findParent(int index) { return (index <= 0) ? (-1) : (index - 1) / 2; }
@ -28,13 +29,13 @@ public:
Heap() { Heap() {
count = 0; count = 0;
heapSize = 128; heapSize = 128;
heapAry = new int[heapSize]; heapAry = new T[heapSize];
} }
Heap(int n) { Heap(int n) {
count = 0; count = 0;
heapSize = n; heapSize = n;
heapAry = new int[heapSize]; heapAry = static_cast<int *>(new T[heapSize]);
} }
~Heap() { delete[] heapAry; } ~Heap() { delete[] heapAry; }
@ -47,10 +48,88 @@ public:
bool isFull() const { return count == heapSize; } bool isFull() const { return count == heapSize; }
bool insertHeap(int itemIn, int (compareFunc)(int, int)); bool insertHeap(T &itemIn, int (compareFunc)(const T&, const T&));
bool deleteHeap(int &itemOut, int (compareFunc)(int, int)); bool deleteHeap(T &itemOut, int (compareFunc)(const T&, const T&));
}; };
template <typename T>
void Heap<T>::_reHeapUp(int lastndx, int (compareFunc)(const T&, const T&)) {
// base case, newElement is heap's root
if (lastndx == 0) return;
int parentIndex = _findParent(lastndx);
// base case, newElement satisfies heap property
// min heap - child not less than parent
// max heap - child not greater than parent
if (compareFunc(heapAry[lastndx], heapAry[parentIndex]) != -1) return;
// swap and continue recursing
std::swap(heapAry[lastndx], heapAry[parentIndex]);
_reHeapUp(parentIndex, compareFunc);
}
/* *~*~*
The private member function _reHeapDown rearranges the heap after delete by moving the
data in the root down to the correct location in the heap
*~**/
template <typename T>
void Heap<T>::_reHeapDown(int rootdex, int (compareFunc)(const T&, const T&)) {
int maxChildIndex = -1;
int left = _findLeftChild(rootdex);
int right = _findRightChild(rootdex);
// if there is a left child
if (left != -1) {
// if there is a right child that is
// min heap - less than the left child
// max heap - greater than the left child
if (right != -1 && compareFunc(heapAry[right], heapAry[left]) == -1) maxChildIndex = right;
else maxChildIndex = left;
}
// base case, heap property satisfied
// min heap - children greater than parent
// max heap - children less than parent
if (maxChildIndex == -1 || compareFunc(heapAry[rootdex], heapAry[maxChildIndex]) == -1) return;
// swap and continue recursing
std::swap(heapAry[rootdex], heapAry[maxChildIndex]);
_reHeapDown(maxChildIndex, compareFunc);
}
/* *~*~*
The public member function insertHeap inserts a new item into a heap.
It calls _reheapUp.
*~**/
template <typename T>
bool Heap<T>::insertHeap(T& newItem, int (compareFunc)(const T&, const T&)) {
if (isFull()) return false;
heapAry[count] = newItem;
_reHeapUp(count, compareFunc);
count++;
return true;
}
/* *~*~*
The public member function deleteHeap deletes the root of the heap and
passes back the root's data. It calls _reheapDown.
*~**/
template <typename T>
bool Heap<T>::deleteHeap(T& returnItem, int (compareFunc)(const T&, const T&)) {
if (isEmpty()) return false;
returnItem = heapAry[0];
heapAry[0] = heapAry[count - 1];
count--;
_reHeapDown(0, compareFunc);
return true;
}
#endif #endif

View File

@ -1,74 +1,105 @@
/* /*
This program will Heaps - ADT
- read integers from the keyboard and insert them into a min-heap and a max-heap
- display the integers as they are deleted from the min-heap.
- display the integers as they are deleted from the max-heap.
Written By: Iurii Tatishchev This program will read data about overbooked customers,
Changed by: Iurii Tatishchev find their priority and serial numbers, build a heap, then display
IDE: CLion customers in priority sequence
Written By: Iurii Tatishchev
Changed By: Iurii Tatishchev
IDE: CLion
*/ */
#include <iostream> #include <iostream>
#include <fstream>
#include <string>
#include "Customer.h"
#include "Heap.h" #include "Heap.h"
using namespace std; using namespace std;
int compareMin(int, int); // Function Prototypes
int compareCustomer(const Customer &c1, const Customer &c2);
int compareMax(int, int); void processArrival(Heap<Customer> &heap, ifstream &inputFile, int seq);
void processServe(Heap<Customer> &heap);
void displayRejected(Heap<Customer> &heap);
int main() { int main() {
Heap minHeap(32); // Get input file name
Heap maxHeap(32); string inputFileName;
cout << "Input file name: ";
// build min- and max-heaps getline(cin, inputFileName);
int num;
cout << "Enter integers [0 - to stop]" << endl;
cin >> num;
while (num != 0) {
minHeap.insertHeap(num, compareMin);
maxHeap.insertHeap(num, compareMax);
cin >> num;
}
// print items as they are deleted from the min-heap (sorted in ascending order)
cout << "Min-Heap: ";
while (!minHeap.isEmpty()) {
minHeap.deleteHeap(num, compareMin);
cout << num << " ";
}
cout << endl; cout << endl;
// print items as they are deleted from the heap (sorted in descending order) // Open input file
cout << "Max-Heap: "; ifstream inputFile(inputFileName);
while (!maxHeap.isEmpty()) { if (!inputFile.good()) {
maxHeap.deleteHeap(num, compareMax); cerr << "Error: could not open file " << inputFileName << "\n";
cout << num << " "; return 1;
} }
cout << endl;
// Create heap
Heap<Customer> heap;
// Process input file
char command;
int seq = 1;
while (inputFile >> command) {
switch (command) {
case 'A':
processArrival(heap, inputFile, seq);
seq++;
break;
case 'S':
processServe(heap);
break;
default:
cerr << "Error: invalid command " << command << "\n";
return 1;
}
}
cout << "Served overbooked customers: " << seq - heap.getCount() - 1 << "\n\n";
// Display rejected customers
int rejectedCustomers = heap.getCount();
displayRejected(heap);
cout << "Rejected overbooked customers: " << rejectedCustomers << "\n";
return 0; return 0;
} }
/* int compareCustomer(const Customer &c1, const Customer &c2) {
compare two data items: needed to build a min-heap if (c1.getSerial() < c2.getSerial()) return 1;
*/ if (c1.getSerial() > c2.getSerial()) return -1;
int compareMin(int x, int y) { return 0;
if (x < y)
return -1;
if (x == y)
return 0;
return 1;
} }
/* void processArrival(Heap<Customer> &heap, ifstream &inputFile, int seq) {
compare two data items: needed to build a max-heap int years, mileage;
*/ string name;
int compareMax(int x, int y) { inputFile >> years >> mileage;
if (x > y) getline(inputFile >> ws, name);
return -1; Customer customer(years, mileage, seq, name);
if (x == y) heap.insertHeap(customer, compareCustomer);
return 0; }
return 1;
void processServe(Heap<Customer> &heap) {
if (heap.isEmpty()) {
cout << "Heap is empty" << endl;
return;
}
Customer customer;
heap.deleteHeap(customer, compareCustomer);
cout << customer << endl;
}
void displayRejected(Heap<Customer> &heap) {
Customer customer;
while (!heap.isEmpty()) {
heap.deleteHeap(customer, compareCustomer);
cout << customer << endl;
}
} }

30
07-heaps/overbooked.txt Normal file
View File

@ -0,0 +1,30 @@
A 5 53000 Robert Hill
A 3 89000 Amanda Trapp
A 3 90000 Jonathan Nguyen
A 5 56000 Tom Martin
A 1 21000 Mary Lou Gilley
S
S
S
A 3 89000 Bob Che
A 7 72000 Warren Rexroad
A 2 65000 Vincent Gonzales
A 3 34000 Paula Hung
S
S
A 6 21000 Lou Masson
A 4 42000 Steve Chu
A 3 99000 Linda Lee
S
S
A 3 69000 Dave Lightfoot
A 3 83000 Daniel Oh
A 5 50000 Sue Andrews
A 2 73000 Joanne Brown
S
A 7 96000 Paul Ng
S
A 5 53000 Steven Chen
A 2 65000 Vladimir Johnson
S
A 7 72000 Peter Edwards

21
07-heaps/overbooked_1.txt Normal file
View File

@ -0,0 +1,21 @@
A 5 53000 Robert Hill
A 3 89000 Amanda Trapp
A 3 90000 Jonathan Nguyen
A 5 56000 Tom Martin
A 1 21000 Mary Lou Gilley
A 3 89000 Bob Che
A 7 72000 Warren Rexroad
A 6 21000 Lou Masson
A 2 65000 Vincent Gonzales
A 3 34000 Paula Hung
A 4 42000 Steve Chu
A 3 99000 Linda Lee
A 3 69000 Dave Lightfoot
A 3 83000 Daniel Oh
A 5 50000 Sue Andrews
A 2 73000 Joanne Brown
A 7 96000 Paul Ng
A 5 53000 Steven Chen
A 2 65000 Vladimir Johnson
A 7 72000 Peter Edwards
A 6 21000 Zoe Smith

10
07-heaps/overbooked_2.txt Normal file
View File

@ -0,0 +1,10 @@
A 5 53000 Robert Hill
A 3 89000 Amanda Trapp
A 2 65000 Vincent Gonzales
S
A 3 34000 Paula Hung
A 4 42000 Steve Chu
S
A 2 65000 Vladimir Johnson
S
A 7 72000 Warren Rexroad

5
07-heaps/test.txt Normal file
View File

@ -0,0 +1,5 @@
A 5 53000 Robert Hill
A 3 89000 Amanda Trapp
A 3 90000 Jonathan Nguyen
S
A 5 56000 Tom Martin