-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdouble_ended_queue.c
More file actions
200 lines (152 loc) · 5.89 KB
/
double_ended_queue.c
File metadata and controls
200 lines (152 loc) · 5.89 KB
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
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
typedef struct {
size_t rear;
size_t front;
size_t len;
size_t capacity;
int *data;
} Deque;
Deque* deque_init(size_t capacity) {
Deque *deque = malloc(sizeof(Deque));
if (!deque) {
fprintf(stderr, "error: memory allocation failed!\n");
exit(-1);
}
deque->data = (int*)malloc(capacity * sizeof(int));
if (!(deque->data)) {
fprintf(stderr, "error: memory allocation failed!\n");
free(deque);
exit(-1);
}
deque->capacity = capacity;
deque->len = 0;
deque->front = 0;
deque->rear = 0;
return deque;
}
void deque_deinit(Deque **self) {
free((*self)->data); // Deallocate the data array
free(*self); // Deallocate the double-ended queue
*self = NULL; // Remove the pointer reference to the double-ended queue
}
int deque_is_empty(Deque *self) {
return (self->len <= 0);
}
int deque_is_full(Deque *self) {
return (self->len >= self->capacity);
}
size_t deque_len(Deque *self) {
return self->len;
}
int deque_peek(const Deque *self) {
if (self->len <= 0) {
return -1;
}
return self->data[self->front];
}
void deque_enqueue_front(Deque *self, int val) {
if (self->len >= self->capacity) {
fprintf(stderr, "error: fail to enqueue, deque is full!\n");
return;
}
// The following condition is necessary to handle the circular nature of the deque.
// It ensures that the front pointer moves in a circular manner, accounting for the
// special case where the rear starts at '0' instead of '-1' in the array.
if (self->len > 0) {
// If the front reaches the first index, set it to the last index
self->front = self->front == 0 ? self->capacity - 1 : self->front - 1;
}
self->data[self->front] = val;
self->len++;
}
void deque_enqueue_rear(Deque *self, int val) {
if (self->len >= self->capacity) {
fprintf(stderr, "error: fail to enqueue, deque is full!\n");
return;
}
// The following condition is necessary to handle the circular nature of the deque.
// It ensures that the rear pointer moves in a circular manner, accounting for the
// special case where the rear starts at '0' instead of '-1' in the array.
if (self->len > 0) {
// If the rear reaches the last index, reset it to 0
self->rear = (self->rear + 1) % self->capacity;
}
self->data[self->rear] = val;
self->len++;
}
int deque_dequeue_front(Deque *self) {
if (self->len <= 0) {
fprintf(stderr, "error: fail to dequeue, deque is empty!\n");
return -1;
}
int temp = deque_peek(self);
// Move the front pointer to the right in a circular manner
self->front = (self->front + 1) % self->capacity;
self->len--;
return temp;
}
int deque_dequeue_rear(Deque *self) {
if (self->len <= 0) {
fprintf(stderr, "error: fail to dequeue, deque is empty!\n");
return -1;
}
int temp = deque_peek(self);
// Move the rear pointer to the left in a circular manner
self->rear = self->rear == 0 ? self->capacity - 1 : self->rear - 1;
self->len--;
return temp;
}
void deque_display(Deque *self) {
if (self->len <= 0) {
fprintf(stderr, "queue is empty!\n");
return;
}
size_t i = self->front;
for (size_t len = self->len; len > 0; len--) {
printf("|%d", self->data[i]);
i = (i + 1) % self->capacity;
}
printf("\n");
}
int main() {
size_t capacity = 5;
Deque *deque = deque_init(capacity);
// Test case 1: Enqueue elements at the front and rear
deque_enqueue_front(deque, 10);
deque_enqueue_rear(deque, 20);
deque_enqueue_front(deque, 30);
deque_enqueue_rear(deque, 40);
printf("Test Case 1 - Enqueue elements: ");
deque_display(deque); // Expected output: |30|10|20|40|
// Test case 2: Dequeue elements from the front and rear
deque_dequeue_front(deque);
deque_dequeue_rear(deque);
printf("\nTest Case 2 - Dequeue elements: ");
deque_display(deque); // Expected output: |10|20
// Test case 3: Enqueue elements to fill the deque
deque_enqueue_rear(deque, 50);
deque_enqueue_rear(deque, 60);
deque_enqueue_rear(deque, 70);
printf("\nTest Case 3 - Enqueue elements to fill the deque: ");
deque_display(deque); // Expected output: |10|20|50|60|70|
// Test case 4: Attempt to enqueue when the deque is full
deque_enqueue_rear(deque, 80); // Exceeds capacity, error message should be printed
printf("\nTest Case 4 - Attempt to enqueue when the deque is full: \n");
deque_display(deque); // Expected output: |10|50|60|70|
// Test case 5: Dequeue elements to empty the deque
deque_dequeue_front(deque);
deque_dequeue_front(deque);
deque_dequeue_front(deque);
deque_dequeue_front(deque);
deque_dequeue_front(deque);
printf("\nTest Case 5 - Dequeue elements to empty the deque: \n");
deque_display(deque); // Expected output: queue is empty!
// Test case 6: Attempt to dequeue when the deque is empty
deque_dequeue_front(deque); // Deque is empty, error message should be printed
printf("\nTest Case 6 - Attempt to dequeue when the deque is empty: \n");
deque_display(deque); // Expected output: queue is empty!
deque_deinit(&deque);
return 0;
}