aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deque.c115
1 files changed, 96 insertions, 19 deletions
diff --git a/deque.c b/deque.c
index 6cf114d..070040b 100644
--- a/deque.c
+++ b/deque.c
@@ -7,7 +7,7 @@
7typedef int T; 7typedef int T;
8 8
9#define START_MAP_CAPACITY 4 9#define START_MAP_CAPACITY 4
10#define CHUNK_CAPACITY 10 10#define CHUNK_CAPACITY 17
11 11
12struct deque { 12struct deque {
13 T **map; 13 T **map;
@@ -15,6 +15,8 @@ struct deque {
15 size_t first_chunk; 15 size_t first_chunk;
16 size_t last_chunk; 16 size_t last_chunk;
17 17
18 size_t start;
19 size_t size;
18 size_t capacity; 20 size_t capacity;
19}; 21};
20 22
@@ -23,6 +25,8 @@ deque_init(struct deque *d)
23{ 25{
24 d->first_chunk = 0; 26 d->first_chunk = 0;
25 d->last_chunk = 0; 27 d->last_chunk = 0;
28 d->start = 0;
29 d->size = 0;
26 30
27 // TODO: Error handling 31 // TODO: Error handling
28 d->map = calloc(START_MAP_CAPACITY, sizeof *d->map); 32 d->map = calloc(START_MAP_CAPACITY, sizeof *d->map);
@@ -50,7 +54,7 @@ deque_free(struct deque *d)
50static void 54static void
51grow_map(struct deque *d) 55grow_map(struct deque *d)
52{ 56{
53 const size_t capacity = d->capacity + (d->capacity / 2); 57 const size_t capacity = d->capacity + d->capacity / 2;
54 T ** map = calloc(capacity, sizeof *map); 58 T ** map = calloc(capacity, sizeof *map);
55 59
56 // copy elements 60 // copy elements
@@ -77,7 +81,7 @@ grow_map(struct deque *d)
77} 81}
78 82
79static void 83static void
80append_chunk(struct deque *d) 84map_append_chunk(struct deque *d)
81{ 85{
82 size_t next = (d->last_chunk + 1) % d->capacity; 86 size_t next = (d->last_chunk + 1) % d->capacity;
83 87
@@ -92,7 +96,7 @@ append_chunk(struct deque *d)
92} 96}
93 97
94static void 98static void
95prepend_chunk(struct deque *d) 99map_prepend_chunk(struct deque *d)
96{ 100{
97 size_t prev = (d->first_chunk + d->capacity - 1) % d->capacity; 101 size_t prev = (d->first_chunk + d->capacity - 1) % d->capacity;
98 102
@@ -107,9 +111,86 @@ prepend_chunk(struct deque *d)
107} 111}
108 112
109static void 113static void
114map_remove_front_chunk(struct deque *d)
115{
116 if ( d->first_chunk == d->last_chunk )
117 return;
118
119 const size_t next = (d->first_chunk + 1) % d->capacity;
120
121 free(d->map[d->first_chunk]);
122 d->map[d->first_chunk] = NULL;
123
124 d->first_chunk = next;
125}
126
127static void
128map_remove_tail_chunk(struct deque *d)
129{
130 if ( d->first_chunk == d->last_chunk )
131 return;
132
133 const size_t prev = (d->last_chunk + d->capacity - 1) % d->capacity;
134
135 free(d->map[prev]);
136 d->map[prev] = NULL;
137
138 d->last_chunk = prev;
139}
140
141void
142deque_get_at(struct deque *d, size_t idx, T *data)
143{
144 const size_t offset = d->start + idx;
145 const size_t chunk_off = offset % CHUNK_CAPACITY;
146 const size_t chunk_num = ((offset / CHUNK_CAPACITY) + d->first_chunk) % d->capacity;
147
148 *data = d->map[chunk_num][chunk_off];
149}
150
151void
152deque_push_back(struct deque *d, T data)
153{
154 const size_t offset = d->start + d->size;
155 const size_t chunk_off = offset % CHUNK_CAPACITY;
156 size_t chunk_num = ((offset / CHUNK_CAPACITY) + d->first_chunk) % d->capacity;
157
158 if ( chunk_num == d->last_chunk ) {
159 map_append_chunk(d);
160 chunk_num = ((offset / CHUNK_CAPACITY) + d->first_chunk) % d->capacity;
161 }
162
163 d->map[chunk_num][chunk_off] = data;
164 ++d->size;
165}
166
167bool
168deque_pop_front(struct deque *d, T *data)
169{
170 if ( d->size == 0 )
171 return false;
172
173 const size_t chunk_off = d->start % CHUNK_CAPACITY;
174 const size_t chunk_num = ((d->start / CHUNK_CAPACITY) + d->first_chunk) % d->capacity;
175
176 *data = d->map[chunk_num][chunk_off];
177
178 --d->size;
179 ++d->start;
180
181 if ( d->size == 0 || d->start == CHUNK_CAPACITY ) {
182 map_remove_front_chunk(d);
183 d->start = 0;
184 }
185
186 return true;
187}
188
189static void
110deque_show(struct deque *d) 190deque_show(struct deque *d)
111{ 191{
112 printf("first: %zu -- last: %zu -- capacity: %zu\n", d->first_chunk, d->last_chunk, d->capacity); 192 printf("first: %zu -- last: %zu -- size: %zu -- capacity: %zu -- start: %zu\n",
193 d->first_chunk, d->last_chunk, d->size, d->capacity, d->start);
113 for ( size_t i = 0; i != d->capacity; ++i ) { 194 for ( size_t i = 0; i != d->capacity; ++i ) {
114 printf("%zu(%p) ", i, (void *) d->map[i]); 195 printf("%zu(%p) ", i, (void *) d->map[i]);
115 } 196 }
@@ -123,20 +204,16 @@ main(void)
123 204
124 deque_init(&c); 205 deque_init(&c);
125 206
126 deque_show(&c); 207 for ( int i = 0; i != 100; ++i ) {
127 append_chunk(&c); 208 deque_push_back(&c, i);
128 deque_show(&c); 209 //deque_show(&c);
129 append_chunk(&c); 210 }
130 deque_show(&c); 211
131 append_chunk(&c); 212 T data;
132 deque_show(&c); 213 while ( deque_pop_front(&c, &data) ) {
133 prepend_chunk(&c); 214 printf("%u, ", data);
134 deque_show(&c); 215 }
135 append_chunk(&c); 216 putchar('\n');
136 deque_show(&c);
137 prepend_chunk(&c);
138 deque_show(&c);
139 prepend_chunk(&c);
140 deque_show(&c); 217 deque_show(&c);
141 218
142 deque_free(&c); 219 deque_free(&c);