forked from Variadicism-zz/CSE340Project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
q.h
228 lines (196 loc) · 6.7 KB
/
q.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
//CSE430 Project 1
//@author Zach Josephson and Connor Davey
#ifndef Q_H
#define Q_H
#include <stdio.h>
#define TRUE 1
#define FALSE 0
struct Queue {
struct Element* first;
struct Element* last;
};
struct Queue* run_queue;
struct Element {
void* payload;
struct Element* next;
struct Element* previous;
};
// STATIC UTILITIES
static struct Element* newElement(void* payload) {
struct Element* new_element = malloc(sizeof(struct Element));
new_element->payload = payload;
new_element->next = NULL;
new_element->previous = NULL;
return new_element;
}
// GLOBAL UTILITIES
/** This function determines the size of the given Queue.
*
* @param queue is the Queue which we want the size of.
*
* @return the number of elements in the Queue. */
unsigned int size(struct Queue* queue) {
if (queue->first == NULL)
return 0;
else if (queue->first == queue->last)
return 1;
else {
unsigned int size = 0;
struct Element *element = queue->first;
while (element != NULL) {
size++;
element = element->next;
}
return size;
}
}
/** This function creates a string describing the contents of the queue.
*
* @param queue is the Queue whose contents should be printed (using <b>printf</b>). */
char* toString(struct Queue* queue) {
if (queue->first == NULL)
return "EMPTY!";
else {
char* string = malloc(35 * size(queue) * sizeof(char));
struct Element* element = queue->first;
unsigned int i = 0;
while (element != NULL) {
// use sprintf to construct the string for this specific element
char* substring[35];
sprintf(substring, "0x%08x<-0x%08x->0x%08x\n", element->previous == NULL ? NULL : element->previous->payload, element->payload, element->next == NULL ? NULL : element->next->payload);
// copy the string into the larger final answer
memcpy(&string[35 * i], substring, 35);
// iterate
element = element->next;
i++;
}
return string;
}
}
/** This function adds a new element to the end of the Queue.
* <hr>
* NOTE: This method will not copy the payload into the given Queue; it will only keep the pointer to the payload given.
* Avoid dangling pointers!
*
* @param queue
* is a pointer to the Queue
* @param payload
* is a pointer to the data to put inside the new Queue Element.
*
* @return a pointer to the Element created to contain the given payload.*/
struct Element* enqueue(struct Queue* queue, void* payload) {
// create a new Element with the given payload
struct Element* new_element = newElement(payload);
if (queue->last != NULL) { // if the Queue is not empty, add the new Element to the end of the given Queue
queue->last->next = new_element;
new_element->previous = queue->last;
} else
// if the Queue was empty, new_element is also the first Element
queue->first = new_element;
queue->last = new_element;
// return the new Element
return new_element;
}
/** This function removes the Element at the beginning the given Queue.
*
* @param queue
* is a pointer to the Queue that will have its first element dequeued.
* @param free_payload
* determines whether or not the payload of the dequeued Element should be removed from memory. <br>
* The <b>char</b> here is used according to C truthiness: 0 = false, anything else = true.
*
* @return a pointer to the payload of the Element that was removeed from the Queue. */
void* dequeue(struct Queue* queue, char free_payload) {
// if the Queue is empty, return NULL
if (queue->first == NULL)
return NULL;
// make a copy of the payload pointer for safe keeping
void* payload = queue->first->payload;
// if the Queue only has one Element, leave it as am empty Queue
if (queue->first == queue->last) {
free(queue->first);
queue->first = queue->last = NULL;
} else { // otherwise, remove the first Element
struct Element* new_first = queue->first->next;
free(queue->first);
queue->first = new_first;
}
if (free_payload)
free(payload);
return payload;
}
/** This function "peeks" at the first Element in the Queue.
*
* @param queue
* is a pointer to the queue which we want the payload of the first Element from.
*
* @return a pointer to the payload of the first Element in the Queue */
void* peek(struct Queue* queue) {
return queue->first->payload;
}
/** This function creates and initializes a new Queue.
*
* @return a pointer to the new Queue struct.*/
struct Queue* newQueue() {
struct Queue* new_queue = malloc(sizeof(struct Queue));
new_queue->first = NULL;
new_queue->last = NULL;
return new_queue;
}
/** This function deletes the given Queue.
*
* @param queue
* is a pointer to the Queue to be deleted.
* @param free_payloads
* determines whether or not the payloads of the Elements in this Queue should be removed from memory. <br>
* The <b>char</b> here is used according to C truthiness: 0 = false, anything else = true.
*
* @return the number of Elements that were present in the deleted Queue. */
unsigned int deleteQueue(struct Queue* queue, char free_payloads) {
// if the Queue is empty, just free its pointers and return 0
if (queue->first == NULL) {
free(queue);
return 0;
}
// keep track of the number of Elements removed to return it at the end
unsigned int size_of_queue = 1; // init to 1 since we know we have 1+ Elements anyway
// first, keep removing Elements until we're down to one
while (queue->first != queue->last) {
size_of_queue++;
void* payload = dequeue(queue, 1);
if (free_payloads)
free(payload);
}
// finally, free the last Element, free the Queue, and return the number of Elements we removed
free(queue->first);
free(queue);
return size_of_queue;
}
/** This function effectively shifts the given Queue forward one item, making the third item the second, the second item the first, and
* moving the first item down to the end of the Queue.
*
* @param queue
* is the Queue that will be rotated.
*
* @return a pointer to the payload of the Element that was first in the given Queue prior to rotation (at the end of the Queue after rotation).
* */
void* rotateQueue(struct Queue* queue) {
// if the given Queue is empty, do nothing and return a NULL payload
if (queue->first == NULL)
return NULL;
// if the given Queue only has one Element, do nothing and return that Element's payload
else if (queue->first == queue->last)
return queue->first->payload;
// keep track of the Element to be moved to the end
struct Element* rotated_element = queue->first;
// disconnect the rotated Element from the front of the Queue
queue->first = queue->first->next;
rotated_element->next = NULL;
queue->first->previous = NULL;
// connect the rotated Element to the end of the Queue
queue->last->next = rotated_element;
rotated_element->previous = queue->last;
queue->last = rotated_element;
return rotated_element->payload;
}
#endif