184 lines
4.8 KiB
C
184 lines
4.8 KiB
C
/*----------------------------------------------------------
|
|
* HTBLA-Leonding / Class: 2IHIF
|
|
* ---------------------------------------------------------
|
|
* Exercise Number: S03
|
|
* Title: Queue implementation
|
|
* Author: Marc Tismonar
|
|
* ----------------------------------------------------------
|
|
* Description:
|
|
* Implementation of a queue based on an advanced singly linked list.
|
|
* ----------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
Implementation notes:
|
|
|
|
1) The 'QueueData' struct SHALL encapsulate the underlying list
|
|
to decouple queue and queue interfaces. No further members are required.
|
|
|
|
2) Queue allocation:
|
|
Use functions `mem_alloc(…)` and `mem_free(…)`
|
|
declared in `allocator.h`. DO NOT use `malloc(…)` and `free(…)` directly
|
|
as unit tests will fail.
|
|
|
|
3) Avoid code duplication wherever (reasonably) possible.
|
|
The implemenation of each function mostly delegates
|
|
to the corresponding queue function (one-liners).
|
|
|
|
Implement the combined functionality of 'dequeue' and 'peek'
|
|
as a single private function which is used by 'dequeue' and 'peek'.
|
|
|
|
*/
|
|
|
|
/* includes */
|
|
#include <stdbool.h>
|
|
#include "queue.h"
|
|
#include "advanced_singly_linked_list.h"
|
|
#include "allocator.h"
|
|
|
|
/** The implementation of queue data */
|
|
struct IntQueueData {
|
|
IntList list;
|
|
};
|
|
|
|
/* ===================================================================== */
|
|
/* private queue functions */
|
|
|
|
/* ===================================================================== */
|
|
|
|
/**
|
|
* Obtains ('creates') and provides a 'new' queue instance.
|
|
* Any queue obtained via this function MUST be released using
|
|
* function `release_queue()`.
|
|
*
|
|
* Note: This function does not make any assumptions
|
|
* about how queue components, esp. nodes, are allocated.
|
|
*
|
|
* @return IntQueue The queue instance or 0, if no queue could by instantiated.
|
|
*/
|
|
IntQueue queue_obtain() {
|
|
IntQueue queue = (IntQueue)alloc_mem(sizeof(struct IntQueueData));
|
|
if (queue != 0) {
|
|
queue->list = list_obtain();
|
|
}
|
|
|
|
return queue;
|
|
}
|
|
|
|
/**
|
|
* Releases a queue that was obtained earlier via function `obtain_queue`.
|
|
* Released queues MUST NOT be used anymore.
|
|
*
|
|
* Note: The implementation of this function does not make any assumptions
|
|
* about the allocation method of queue elements, but MUST match the implementation
|
|
* of function `obtain_queue` as its inverse function.
|
|
*
|
|
* @param p_queue The pointer to the queue to release. The value of the pointer
|
|
* is set to 0, if the queue was successfully released, otherwise it is left untouched.
|
|
*/
|
|
IntQueue queue_release(IntQueue* p_queue) {
|
|
if (p_queue == 0 || *p_queue == 0) {
|
|
return 0;
|
|
}
|
|
|
|
IntQueue queue = *p_queue;
|
|
list_release(&queue->list);
|
|
free_mem(queue);
|
|
*p_queue = 0;
|
|
|
|
return queue;
|
|
}
|
|
|
|
/**
|
|
* Determines whether or not the given queue is valid.
|
|
*
|
|
* @param queue The queue to evaluate.
|
|
* @return `True` if the queue is valid, false otherwise.
|
|
*/
|
|
bool queue_is_valid(IntQueue queue) {
|
|
return queue != 0 && queue->list != 0;
|
|
}
|
|
|
|
/**
|
|
* Determines whether or not the queue contains at least one item.
|
|
*
|
|
* @param queue The queue to evaluate.
|
|
* @return `False` if the queue contains one or more items, `true` otherwise.
|
|
*/
|
|
bool queue_is_empty(IntQueue queue) {
|
|
return !queue_is_valid(queue) || list_is_empty(queue->list);
|
|
}
|
|
|
|
/**
|
|
* Provides the number of values stored in the queue.
|
|
*
|
|
* @param queue The queue to evaluate.
|
|
* @return The number of values the queue contains.
|
|
*/
|
|
int queue_get_size(IntQueue queue) {
|
|
if (!queue_is_valid(queue)) {
|
|
return 0;
|
|
}
|
|
|
|
return list_get_size(queue->list);
|
|
}
|
|
|
|
/**
|
|
* Clears the given queue by removing all values from the queue.
|
|
*
|
|
* @param queue The queue to clear.
|
|
*/
|
|
void queue_clear(IntQueue queue) {
|
|
if (!queue_is_valid(queue)) {
|
|
return;
|
|
}
|
|
|
|
list_clear(queue->list);
|
|
}
|
|
|
|
/**
|
|
* Inserts the given value to the queue (as new tail).
|
|
*
|
|
* @param queue The queue to which the value shall be appended.
|
|
* @param value The value to append to the queue.
|
|
*/
|
|
void queue_enqueue(IntQueue queue, int value)
|
|
{
|
|
if (!queue_is_valid(queue)) {
|
|
return;
|
|
}
|
|
|
|
list_insert(queue->list, value);
|
|
}
|
|
|
|
/**
|
|
* Provides the value that 'dequeue' would provided but WITHOUT removing
|
|
* this value from the queue.
|
|
*
|
|
* @param queue The queue from which the value shall be peeked.
|
|
* @return The next value or 0, if the queue is empty.
|
|
*/
|
|
int queue_peek(IntQueue queue) {
|
|
if (!queue_is_valid(queue)) {
|
|
return 0;
|
|
}
|
|
|
|
return list_get_at(queue->list, 0);
|
|
}
|
|
|
|
/**
|
|
* Provides AND removes the next value from the queue.
|
|
*
|
|
* @param queue The queue from which the value shall be removed and returned.
|
|
* @return The value or 0, if the queue is empty.
|
|
*/
|
|
int queue_dequeue(IntQueue queue) {
|
|
if (!queue_is_valid(queue)) {
|
|
return 0;
|
|
}
|
|
|
|
int value = list_get_at(queue->list, 0);
|
|
list_remove_at(queue->list, 0);
|
|
return value;
|
|
}
|
|
|