Data-Structures-and-Algorithms / Triage / PriorityQueue / PriorityQueue.h
PriorityQueue.h
Raw
#pragma once

#include "LinkedList.h"
/*  File Name: PriorityQueue.h
	Author: Essam Fahmy
	Date: 2023-11-01

	PriorityQueue declarations and implementations
*/

#include "Patient.h"
#include <stdexcept>

template <typename T>
class PriorityQueue {

	LinkedList<T> patients_;

	bool isDuplicate(const T& patient) {
		typename LinkedList<T>::Node* current = patients_.begin();
		while (current != nullptr) {
			if (current->data == patient) {
				return true;
			}
			current = current->next;
		}
		return false;
	}

public:
	PriorityQueue() {}

	bool empty() const {
		return patients_.empty();
	}

	size_t size() const {
		return patients_.size();
	}

	void enqueue(const T& patient) {
		if (isDuplicate(patient)) {
			throw std::invalid_argument("Duplicate patient");
		}

		// If the list is empty or the new patient has a higher score than the first patient
		if (empty() || patient.get_score() > patients_.begin()->data.get_score()) {
			patients_.push_front(patient);
		}
		else {
			typename LinkedList<T>::Node* current = patients_.begin();

			// Traverse the list until the right position is found
			while (current->next != nullptr && current->next->data.get_score() >= patient.get_score()) {
				current = current->next;
			}

			// Insert the new patient
			typename LinkedList<T>::Node* newNode = new typename LinkedList<T>::Node();
			newNode->data = patient;
			newNode->next = current->next;
			newNode->previous = current;

			if (current->next != nullptr) {
				current->next->previous = newNode;
			}
			else {
				// If we're at the end, update the end pointer
				patients_.push_back(patient);
				delete newNode;
				return;
			}

			current->next = newNode;
		}
	}

	typename LinkedList<T>::Node* begin() {
		return patients_.begin();
	}

	typename LinkedList<T>::Node* end() {
		return nullptr;
	}

	T dequeue() {
		if (empty()) {
			throw std::out_of_range("Queue is empty");
		}

		return patients_.pop_front();
	}

};