aboutsummaryrefslogtreecommitdiff
path: root/deque.c
diff options
context:
space:
mode:
Diffstat (limited to 'deque.c')
-rw-r--r--deque.c120
1 files changed, 111 insertions, 9 deletions
diff --git a/deque.c b/deque.c
index 903f64f..6cf114d 100644
--- a/deque.c
+++ b/deque.c
@@ -6,29 +6,114 @@
6 6
7typedef int T; 7typedef int T;
8 8
9#define START_CAPACITY 8 9#define START_MAP_CAPACITY 4
10#define CHUNK_CAPACITY 10
10 11
11struct deque { 12struct deque {
12 T ** chunks; 13 T **map;
13 size_t head; 14
14 size_t tail; 15 size_t first_chunk;
16 size_t last_chunk;
17
15 size_t capacity; 18 size_t capacity;
16}; 19};
17 20
18void 21void
19deque_init(struct deque *d) 22deque_init(struct deque *d)
20{ 23{
21 d->head = 0; 24 d->first_chunk = 0;
22 d->tail = 0; 25 d->last_chunk = 0;
23 d->capacity = START_CAPACITY;
24 26
25 d->chunks = calloc(d->capacity, sizeof *d->chunks); 27 // TODO: Error handling
28 d->map = calloc(START_MAP_CAPACITY, sizeof *d->map);
29 if ( d->map != NULL ) {
30 d->capacity = START_MAP_CAPACITY;
31
32 for ( size_t i = 0; i != d->capacity; ++i ) {
33 d->map[i] = NULL;
34 }
35 }
26} 36}
27 37
28void 38void
29deque_free(struct deque *d) 39deque_free(struct deque *d)
30{ 40{
31 free(d->chunks); 41 // free all chunks
42 for ( size_t i = 0; i != d->capacity; ++i ) {
43 free(d->map[i]);
44 }
45
46 // free the map itself
47 free(d->map);
48}
49
50static void
51grow_map(struct deque *d)
52{
53 const size_t capacity = d->capacity + (d->capacity / 2);
54 T ** map = calloc(capacity, sizeof *map);
55
56 // copy elements
57 size_t i;
58 for ( i = 0; i != d->capacity; ++i ) {
59 map[i] = d->map[(i + d->first_chunk) % d->capacity];
60 }
61
62 // initialize the rest (new) elements with NULL
63 for ( ; i != capacity; ++i ) {
64 map[i] = NULL;
65 }
66
67 // free old & assign new map
68 free(d->map);
69 d->map = map;
70
71 // adjust pointers
72 d->first_chunk = 0;
73 d->last_chunk = d->capacity - 1;
74
75 // set new capacity
76 d->capacity = capacity;
77}
78
79static void
80append_chunk(struct deque *d)
81{
82 size_t next = (d->last_chunk + 1) % d->capacity;
83
84 if ( next == d->first_chunk ) { // Resize the map
85 grow_map(d);
86
87 next = d->last_chunk + 1;
88 }
89
90 d->map[d->last_chunk] = calloc(CHUNK_CAPACITY, sizeof **d->map);
91 d->last_chunk = next;
92}
93
94static void
95prepend_chunk(struct deque *d)
96{
97 size_t prev = (d->first_chunk + d->capacity - 1) % d->capacity;
98
99 if ( prev == d->last_chunk ) {
100 grow_map(d);
101
102 prev = d->capacity - 1;
103 }
104
105 d->map[prev] = calloc(CHUNK_CAPACITY, sizeof **d->map);
106 d->first_chunk = prev;
107}
108
109static void
110deque_show(struct deque *d)
111{
112 printf("first: %zu -- last: %zu -- capacity: %zu\n", d->first_chunk, d->last_chunk, d->capacity);
113 for ( size_t i = 0; i != d->capacity; ++i ) {
114 printf("%zu(%p) ", i, (void *) d->map[i]);
115 }
116 puts("");
32} 117}
33 118
34int 119int
@@ -37,6 +122,23 @@ main(void)
37 struct deque c; 122 struct deque c;
38 123
39 deque_init(&c); 124 deque_init(&c);
125
126 deque_show(&c);
127 append_chunk(&c);
128 deque_show(&c);
129 append_chunk(&c);
130 deque_show(&c);
131 append_chunk(&c);
132 deque_show(&c);
133 prepend_chunk(&c);
134 deque_show(&c);
135 append_chunk(&c);
136 deque_show(&c);
137 prepend_chunk(&c);
138 deque_show(&c);
139 prepend_chunk(&c);
140 deque_show(&c);
141
40 deque_free(&c); 142 deque_free(&c);
41 143
42 return 0; 144 return 0;