Fixing and adding more tests

This commit is contained in:
Leonardo committed 2019-07-04 15:34:25 -03:00
1 parent 8c457eeb12
commit 97d50bc3d9
13 files changed
+2264 -19

No files matched your search

+8
View File
@@ -4,6 +4,10 @@
#include "unt/heap.c"
#include "unt/linkedlist.c"
#include "unt/list.c"
#include "unt/queue.c"
#include "unt/stack.c"
#include "unt/treemap.c"
#include "unt/treeset.c"
int main(void)
{
@@ -13,6 +17,10 @@ int main(void)
heap_test();
linkedlist_test();
list_test();
queue_test();
stack_test();
treemap_test();
treeset_test();
return 0;
}
+3 -3
View File
@@ -160,13 +160,13 @@ bool d_pop_back_if(deque *_deque_, bool condition)
size_t d_front(deque *_deque_)
{
if (d_empty(_deque_))
d_impl_default_value();
return d_impl_default_value();
return _deque_->buffer[_deque_->front];
}
size_t d_back(deque *_deque_)
{
if (d_empty(_deque_))
d_impl_default_value();
return d_impl_default_value();
return _deque_->buffer[(_deque_->back == 0) ? _deque_->capacity - 1 : _deque_->back - 1];
}
bool d_contains(deque *_deque_, size_t element, int (*comparator)(size_t, size_t))
@@ -249,7 +249,7 @@ bool d_iter_prev(deque_iter *iter)
size_t d_iter_value(deque_iter *iter)
{
if (d_empty(iter->target))
d_impl_default_value();
return d_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *d_iter_rvalue(deque_iter *iter)
+13 -13
View File
@@ -76,16 +76,16 @@ static hashmap_iter hm_impl_it_end(hashmap *_map_);
hashmap *hm_new(size_t capacity, double load, int (*compare)(size_t, size_t), size_t (*hash)(size_t))
{
if (capacity == 0 || load <= 0 || load >= 1)
return 0;
return NULL;
size_t real_capacity = hm_impl_calculate_size(capacity / load);
hashmap *_map_ = malloc(sizeof(hashmap));
if (!_map_)
return 0;
return NULL;
_map_->buffer = malloc(sizeof(hashmap_entry) * real_capacity);
if (!_map_->buffer)
{
free(_map_);
return 0;
return NULL;
}
memset(_map_->buffer, 0, sizeof(hashmap_entry) * real_capacity);
_map_->count = 0;
@@ -118,7 +118,7 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value)
size_t original_pos = hash % _map_->capacity;
size_t pos = original_pos;
hashmap_entry *target = &(_map_->buffer[pos]);
if (hm_impl_get_entry(_map_, key) != 0)
if (hm_impl_get_entry(_map_, key) != NULL)
return false;
if (target->state == ES_EMPTY || target->state == ES_DELETED)
{
@@ -161,7 +161,7 @@ bool hm_insert(hashmap *_map_, size_t key, size_t value)
bool hm_remove(hashmap *_map_, size_t key, size_t *value)
{
hashmap_entry *result = hm_impl_get_entry(_map_, key);
if (result == 0)
if (result == NULL)
return false;
*value = result->value;
result->key = hm_impl_default_key();
@@ -233,17 +233,17 @@ size_t hm_get(hashmap *_map_, size_t key)
{
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
if (!entry)
hm_impl_default_value();
return hm_impl_default_value();
return entry->value;
}
size_t *hm_get_ref(hashmap *_map_, size_t key)
{
hashmap_entry *entry = hm_impl_get_entry(_map_, key);
if (!entry)
return 0;
return NULL;
return &(entry->value);
}
bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != 0; }
bool hm_contains(hashmap *_map_, size_t key) { return hm_impl_get_entry(_map_, key) != NULL; }
bool hm_empty(hashmap *_map_) { return _map_->count == 0; }
size_t hm_count(hashmap *_map_) { return _map_->count; }
size_t hm_capacity(hashmap *_map_) { return _map_->capacity; }
@@ -251,7 +251,7 @@ hashmap_iter *hm_iter_new(hashmap *target)
{
hashmap_iter *iter = malloc(sizeof(hashmap_iter));
if (!iter)
return 0;
return NULL;
hm_iter_init(iter, target);
return iter;
}
@@ -345,19 +345,19 @@ bool hm_iter_prev(hashmap_iter *iter)
size_t hm_iter_key(hashmap_iter *iter)
{
if (hm_empty(iter->target))
hm_impl_default_key();
return hm_impl_default_key();
return iter->target->buffer[iter->cursor].key;
}
size_t hm_iter_value(hashmap_iter *iter)
{
if (hm_empty(iter->target))
hm_impl_default_value();
return hm_impl_default_value();
return iter->target->buffer[iter->cursor].value;
}
size_t *hm_iter_rvalue(hashmap_iter *iter)
{
if (hm_empty(iter->target))
return 0;
return NULL;
return &(iter->target->buffer[iter->cursor].value);
}
size_t hm_iter_index(hashmap_iter *iter) { return iter->index; }
@@ -398,7 +398,7 @@ static hashmap_entry *hm_impl_get_entry(hashmap *_map_, size_t key)
pos++;
target = &(_map_->buffer[pos % _map_->capacity]);
}
return 0;
return NULL;
}
static size_t hm_impl_calculate_size(size_t required)
{
+2 -2
View File
@@ -230,13 +230,13 @@ bool ll_pop_if(linkedlist *_list_, size_t index, bool condition)
size_t ll_front(linkedlist *_list_)
{
if (ll_empty(_list_))
ll_impl_default_value();
return ll_impl_default_value();
return _list_->head->data;
}
size_t ll_get(linkedlist *_list_, size_t index)
{
if (index >= _list_->count || ll_empty(_list_))
ll_impl_default_value();
return ll_impl_default_value();
linkedlist_node *scan = ll_get_node(_list_, index);
if (scan == NULL)
return ll_impl_default_value();
+248
View File
@@ -0,0 +1,248 @@
#include "cmc/queue.h"
typedef struct queue_s
{
size_t *buffer;
size_t capacity;
size_t count;
size_t front;
size_t rear;
struct queue_iter_s (*it_start)(struct queue_s *);
struct queue_iter_s (*it_end)(struct queue_s *);
} queue, *queue_ptr;
typedef struct queue_iter_s
{
struct queue_s *target;
size_t cursor;
size_t index;
bool start;
bool end;
} queue_iter, *queue_iter_ptr;
queue *q_new(size_t capacity);
void q_clear(queue *_queue_);
void q_free(queue *_queue_);
bool q_enqueue(queue *_queue_, size_t element);
bool q_dequeue(queue *_queue_);
bool q_enqueue_if(queue *_queue_, size_t element, bool condition);
bool q_dequeue_if(queue *_queue_, bool condition);
size_t q_peek(queue *_queue_);
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t));
bool q_empty(queue *_queue_);
bool q_full(queue *_queue_);
size_t q_count(queue *_queue_);
size_t q_capacity(queue *_queue_);
queue_iter *q_iter_new(queue *target);
void q_iter_free(queue_iter *iter);
void q_iter_init(queue_iter *iter, queue *target);
bool q_iter_start(queue_iter *iter);
bool q_iter_end(queue_iter *iter);
void q_iter_to_start(queue_iter *iter);
void q_iter_to_end(queue_iter *iter);
bool q_iter_next(queue_iter *iter);
bool q_iter_prev(queue_iter *iter);
size_t q_iter_value(queue_iter *iter);
size_t *q_iter_rvalue(queue_iter *iter);
size_t q_iter_index(queue_iter *iter);
static inline size_t q_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool q_impl_grow(queue *_queue_);
static queue_iter q_impl_it_start(queue *_queue_);
static queue_iter q_impl_it_end(queue *_queue_);
queue *q_new(size_t capacity)
{
if (capacity < 1)
return NULL;
queue *_queue_ = malloc(sizeof(queue));
if (!_queue_)
return NULL;
_queue_->buffer = malloc(sizeof(size_t) * capacity);
if (!_queue_->buffer)
{
free(_queue_);
return NULL;
}
memset(_queue_->buffer, 0, sizeof(size_t) * capacity);
_queue_->capacity = capacity;
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
_queue_->it_start = q_impl_it_start;
_queue_->it_end = q_impl_it_end;
return _queue_;
}
void q_clear(queue *_queue_)
{
memset(_queue_->buffer, 0, sizeof(size_t) * _queue_->capacity);
_queue_->count = 0;
_queue_->front = 0;
_queue_->rear = 0;
}
void q_free(queue *_queue_)
{
free(_queue_->buffer);
free(_queue_);
}
bool q_enqueue(queue *_queue_, size_t element)
{
if (q_full(_queue_))
{
if (!q_impl_grow(_queue_))
return false;
}
_queue_->buffer[_queue_->rear] = element;
_queue_->rear = (_queue_->rear == _queue_->capacity - 1) ? 0 : _queue_->rear + 1;
_queue_->count++;
return true;
}
bool q_dequeue(queue *_queue_)
{
if (q_empty(_queue_))
return false;
_queue_->buffer[_queue_->front] = q_impl_default_value();
_queue_->front = (_queue_->front == _queue_->capacity - 1) ? 0 : _queue_->front + 1;
_queue_->count--;
return true;
}
bool q_enqueue_if(queue *_queue_, size_t element, bool condition)
{
if (condition)
return q_enqueue(_queue_, element);
return false;
}
bool q_dequeue_if(queue *_queue_, bool condition)
{
if (condition)
return q_dequeue(_queue_);
return false;
}
size_t q_peek(queue *_queue_)
{
if (q_empty(_queue_))
return q_impl_default_value();
return _queue_->buffer[_queue_->front];
}
bool q_contains(queue *_queue_, size_t element, int (*comparator)(size_t, size_t))
{
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->count, j++)
{
if (comparator(_queue_->buffer[i], element) == 0)
return true;
}
return false;
}
bool q_empty(queue *_queue_) { return _queue_->count == 0; }
bool q_full(queue *_queue_) { return _queue_->count >= _queue_->capacity; }
size_t q_count(queue *_queue_) { return _queue_->count; }
size_t q_capacity(queue *_queue_) { return _queue_->capacity; }
queue_iter *q_iter_new(queue *target)
{
queue_iter *iter = malloc(sizeof(queue_iter));
if (!iter)
return NULL;
q_iter_init(iter, target);
return iter;
}
void q_iter_free(queue_iter *iter) { free(iter); }
void q_iter_init(queue_iter *iter, queue *target)
{
iter->target = target;
iter->cursor = target->front;
iter->index = 0;
iter->start = true;
iter->end = q_empty(target);
}
bool q_iter_start(queue_iter *iter) { return q_empty(iter->target) || iter->start; }
bool q_iter_end(queue_iter *iter) { return q_empty(iter->target) || iter->end; }
void q_iter_to_start(queue_iter *iter)
{
iter->cursor = iter->target->front;
iter->index = 0;
iter->start = true;
iter->end = q_empty(iter->target);
}
void q_iter_to_end(queue_iter *iter)
{
if (q_empty(iter->target))
iter->cursor = 0;
else
iter->cursor = (iter->target->rear == 0) ? iter->target->capacity - 1 : iter->target->rear - 1;
iter->index = iter->target->count - 1;
iter->start = q_empty(iter->target);
iter->end = true;
}
bool q_iter_next(queue_iter *iter)
{
if (iter->end)
return false;
iter->start = q_empty(iter->target);
if (iter->index == iter->target->count - 1)
iter->end = true;
else
{
iter->cursor = (iter->cursor + 1) % (iter->target->capacity);
iter->index++;
}
return true;
}
bool q_iter_prev(queue_iter *iter)
{
if (iter->start)
return false;
iter->end = q_empty(iter->target);
if (iter->index == 0)
iter->start = true;
else
{
iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1;
iter->index--;
}
return true;
}
size_t q_iter_value(queue_iter *iter)
{
if (q_empty(iter->target))
return q_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *q_iter_rvalue(queue_iter *iter)
{
if (q_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t q_iter_index(queue_iter *iter) { return iter->index; }
static bool q_impl_grow(queue *_queue_)
{
size_t new_capacity = _queue_->capacity * 2;
size_t *new_buffer = malloc(sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
for (size_t i = _queue_->front, j = 0; j < _queue_->count; i = (i + 1) % _queue_->capacity, j++)
{
new_buffer[j] = _queue_->buffer[i];
}
free(_queue_->buffer);
_queue_->buffer = new_buffer;
_queue_->capacity = new_capacity;
_queue_->front = 0;
_queue_->rear = _queue_->count;
return true;
}
static queue_iter q_impl_it_start(queue *_queue_)
{
queue_iter iter;
q_iter_init(&iter, _queue_);
q_iter_to_start(&iter);
return iter;
}
static queue_iter q_impl_it_end(queue *_queue_)
{
queue_iter iter;
q_iter_init(&iter, _queue_);
q_iter_to_end(&iter);
return iter;
}
+218
View File
@@ -0,0 +1,218 @@
#include "cmc/stack.h"
typedef struct stack_s
{
size_t *buffer;
size_t capacity;
size_t count;
struct stack_iter_s (*it_start)(struct stack_s *);
struct stack_iter_s (*it_end)(struct stack_s *);
} stack, *stack_ptr;
typedef struct stack_iter_s
{
struct stack_s *target;
size_t cursor;
bool start;
bool end;
} stack_iter, *stack_iter_ptr;
stack *s_new(size_t capacity);
void s_clear(stack *_stack_);
void s_free(stack *_stack_);
bool s_push(stack *_stack_, size_t element);
bool s_pop(stack *_stack_);
bool s_push_if(stack *_stack_, size_t element, bool condition);
bool s_pop_if(stack *_stack_, bool condition);
size_t s_top(stack *_stack_);
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t));
bool s_empty(stack *_stack_);
bool s_full(stack *_stack_);
size_t s_count(stack *_stack_);
size_t s_capacity(stack *_stack_);
stack_iter *s_iter_new(stack *target);
void s_iter_free(stack_iter *iter);
void s_iter_init(stack_iter *iter, stack *target);
bool s_iter_start(stack_iter *iter);
bool s_iter_end(stack_iter *iter);
void s_iter_to_start(stack_iter *iter);
void s_iter_to_end(stack_iter *iter);
bool s_iter_next(stack_iter *iter);
bool s_iter_prev(stack_iter *iter);
size_t s_iter_value(stack_iter *iter);
size_t *s_iter_rvalue(stack_iter *iter);
size_t s_iter_index(stack_iter *iter);
static inline size_t s_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static bool s_impl_grow(stack *_stack_);
static stack_iter s_impl_it_start(stack *_stack_);
static stack_iter s_impl_it_end(stack *_stack_);
stack *s_new(size_t capacity)
{
if (capacity < 1)
return NULL;
stack *_stack_ = malloc(sizeof(stack));
if (!_stack_)
return NULL;
_stack_->buffer = malloc(sizeof(size_t) * capacity);
if (!_stack_->buffer)
{
free(_stack_);
return NULL;
}
memset(_stack_->buffer, 0, sizeof(size_t) * capacity);
_stack_->capacity = capacity;
_stack_->count = 0;
_stack_->it_start = s_impl_it_start;
_stack_->it_end = s_impl_it_end;
return _stack_;
}
void s_clear(stack *_stack_)
{
memset(_stack_->buffer, 0, sizeof(size_t) * _stack_->capacity);
_stack_->count = 0;
}
void s_free(stack *_stack_)
{
free(_stack_->buffer);
free(_stack_);
}
bool s_push(stack *_stack_, size_t element)
{
if (s_full(_stack_))
{
if (!s_impl_grow(_stack_))
return false;
}
_stack_->buffer[_stack_->count++] = element;
return true;
}
bool s_pop(stack *_stack_)
{
if (s_empty(_stack_))
return false;
_stack_->buffer[--_stack_->count] = s_impl_default_value();
return true;
}
bool s_push_if(stack *_stack_, size_t element, bool condition)
{
if (condition)
return s_push(_stack_, element);
return false;
}
bool s_pop_if(stack *_stack_, bool condition)
{
if (condition)
return s_pop(_stack_);
return false;
}
size_t s_top(stack *_stack_)
{
if (s_empty(_stack_))
return s_impl_default_value();
return _stack_->buffer[_stack_->count - 1];
}
bool s_contains(stack *_stack_, size_t element, int (*comparator)(size_t, size_t))
{
for (size_t i = 0; i < _stack_->count; i++)
{
if (comparator(_stack_->buffer[i], element) == 0)
return true;
}
return false;
}
bool s_empty(stack *_stack_) { return _stack_->count == 0; }
bool s_full(stack *_stack_) { return _stack_->count >= _stack_->capacity; }
size_t s_count(stack *_stack_) { return _stack_->count; }
size_t s_capacity(stack *_stack_) { return _stack_->capacity; }
stack_iter *s_iter_new(stack *target)
{
stack_iter *iter = malloc(sizeof(stack_iter));
if (!iter)
return NULL;
s_iter_init(iter, target);
return iter;
}
void s_iter_free(stack_iter *iter) { free(iter); }
void s_iter_init(stack_iter *iter, stack *target)
{
iter->target = target;
iter->cursor = iter->target->count - 1;
iter->start = true;
iter->end = s_empty(target);
}
bool s_iter_start(stack_iter *iter) { return s_empty(iter->target) || iter->start; }
bool s_iter_end(stack_iter *iter) { return s_empty(iter->target) || iter->end; }
void s_iter_to_start(stack_iter *iter)
{
iter->cursor = iter->target->count - 1;
iter->start = true;
iter->end = s_empty(iter->target);
}
void s_iter_to_end(stack_iter *iter)
{
iter->cursor = 0;
iter->start = s_empty(iter->target);
iter->end = true;
}
bool s_iter_next(stack_iter *iter)
{
if (iter->end)
return false;
iter->start = s_empty(iter->target);
if (iter->cursor == 0)
iter->end = true;
else
iter->cursor--;
return true;
}
bool s_iter_prev(stack_iter *iter)
{
if (iter->start)
return false;
iter->end = s_empty(iter->target);
if (iter->cursor == iter->target->count - 1)
iter->start = true;
else
iter->cursor++;
return true;
}
size_t s_iter_value(stack_iter *iter)
{
if (s_empty(iter->target))
return s_impl_default_value();
return iter->target->buffer[iter->cursor];
}
size_t *s_iter_rvalue(stack_iter *iter)
{
if (s_empty(iter->target))
return NULL;
return &(iter->target->buffer[iter->cursor]);
}
size_t s_iter_index(stack_iter *iter) { return iter->target->count - 1 - iter->cursor; }
static bool s_impl_grow(stack *_stack_)
{
size_t new_capacity = _stack_->capacity * 2;
size_t *new_buffer = realloc(_stack_->buffer, sizeof(size_t) * new_capacity);
if (!new_buffer)
return false;
_stack_->buffer = new_buffer;
_stack_->capacity = new_capacity;
return true;
}
static stack_iter s_impl_it_start(stack *_stack_)
{
stack_iter iter;
s_iter_init(&iter, _stack_);
s_iter_to_start(&iter);
return iter;
}
static stack_iter s_impl_it_end(stack *_stack_)
{
stack_iter iter;
s_iter_init(&iter, _stack_);
s_iter_to_end(&iter);
return iter;
}
+597
View File
@@ -0,0 +1,597 @@
#include "cmc/treemap.h"
typedef struct treemap_s
{
struct treemap_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treemap_iter_s (*it_start)(struct treemap_s *);
struct treemap_iter_s (*it_end)(struct treemap_s *);
} treemap, *treemap_ptr;
typedef struct treemap_node_s
{
size_t key;
size_t value;
unsigned char height;
struct treemap_node_s *right;
struct treemap_node_s *left;
struct treemap_node_s *parent;
} treemap_node, *treemap_node_ptr;
typedef struct treemap_iter_s
{
struct treemap_s *target;
struct treemap_node_s *cursor;
struct treemap_node_s *first;
struct treemap_node_s *last;
size_t index;
bool start;
bool end;
} treemap_iter, *treemap_iter_ptr;
treemap *tm_new(int (*compare)(size_t, size_t));
void tm_clear(treemap *_map_);
void tm_free(treemap *_map_);
bool tm_insert(treemap *_map_, size_t key, size_t value);
bool tm_remove(treemap *_map_, size_t key, size_t *value);
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition);
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition);
bool tm_max(treemap *_map_, size_t *key, size_t *value);
bool tm_min(treemap *_map_, size_t *key, size_t *value);
size_t tm_get(treemap *_map_, size_t key);
size_t *tm_get_ref(treemap *_map_, size_t key);
bool tm_contains(treemap *_map_, size_t key);
bool tm_empty(treemap *_map_);
size_t tm_count(treemap *_map_);
treemap_iter *tm_iter_new(treemap *target);
void tm_iter_free(treemap_iter *iter);
void tm_iter_init(treemap_iter *iter, treemap *target);
bool tm_iter_start(treemap_iter *iter);
bool tm_iter_end(treemap_iter *iter);
void tm_iter_to_start(treemap_iter *iter);
void tm_iter_to_end(treemap_iter *iter);
bool tm_iter_next(treemap_iter *iter);
bool tm_iter_prev(treemap_iter *iter);
size_t tm_iter_key(treemap_iter *iter);
size_t tm_iter_value(treemap_iter *iter);
size_t *tm_iter_rvalue(treemap_iter *iter);
size_t tm_iter_index(treemap_iter *iter);
static inline size_t tm_impl_default_key(void)
{
size_t _empty_key_;
memset(&_empty_key_, 0, sizeof(size_t));
return _empty_key_;
}
static inline size_t tm_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static treemap_node *tm_impl_new_node(size_t key, size_t value);
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key);
static unsigned char tm_impl_h(treemap_node *node);
static unsigned char tm_impl_hupdate(treemap_node *node);
static void tm_impl_rotate_right(treemap_node **Z);
static void tm_impl_rotate_left(treemap_node **Z);
static void tm_impl_rebalance(treemap *_map_, treemap_node *node);
static treemap_iter tm_impl_it_start(treemap *_map_);
static treemap_iter tm_impl_it_end(treemap *_map_);
treemap *tm_new(int (*compare)(size_t, size_t))
{
treemap *_map_ = malloc(sizeof(treemap));
if (!_map_)
return NULL;
_map_->count = 0;
_map_->root = NULL;
_map_->cmp = compare;
_map_->it_start = tm_impl_it_start;
_map_->it_end = tm_impl_it_end;
return _map_;
}
void tm_clear(treemap *_map_)
{
treemap_node *scan = _map_->root;
treemap_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treemap_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treemap_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_map_->count = 0;
_map_->root = NULL;
}
void tm_free(treemap *_map_)
{
tm_clear(_map_);
free(_map_);
}
bool tm_insert(treemap *_map_, size_t key, size_t value)
{
if (tm_empty(_map_))
{
_map_->root = tm_impl_new_node(key, value);
if (!_map_->root)
return false;
}
else
{
treemap_node *scan = _map_->root;
treemap_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return false;
}
treemap_node *node;
if (_map_->cmp(parent->key, key) > 0)
{
parent->left = tm_impl_new_node(key, value);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = tm_impl_new_node(key, value);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
tm_impl_rebalance(_map_, node);
}
_map_->count++;
return true;
}
bool tm_remove(treemap *_map_, size_t key, size_t *value)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return false;
*value = node->value;
treemap_node *temp = NULL, *unbalanced = NULL;
bool is_root = node->parent == NULL;
if (node->left == NULL && node->right == NULL)
{
if (is_root)
_map_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_map_->root = node->right;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_map_->root = node->left;
_map_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
temp = temp->left;
size_t temp_key = temp->key;
size_t temp_val = temp->value;
unbalanced = temp->parent;
if (temp->left == NULL && temp->right == NULL)
{
if (temp->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->key = temp_key;
node->value = temp_val;
}
if (unbalanced != NULL)
tm_impl_rebalance(_map_, unbalanced);
_map_->count--;
if (_map_->count == 0)
_map_->root = NULL;
return true;
}
bool tm_insert_if(treemap *_map_, size_t key, size_t value, bool condition)
{
if (condition)
return tm_insert(_map_, key, value);
return false;
}
bool tm_remove_if(treemap *_map_, size_t key, size_t *value, bool condition)
{
if (condition)
return tm_remove(_map_, key, value);
return false;
}
bool tm_max(treemap *_map_, size_t *key, size_t *value)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->right != NULL)
scan = scan->right;
*key = scan->key;
*value = scan->value;
return true;
}
bool tm_min(treemap *_map_, size_t *key, size_t *value)
{
if (tm_empty(_map_))
return false;
treemap_node *scan = _map_->root;
while (scan->left != NULL)
scan = scan->left;
*key = scan->key;
*value = scan->value;
return true;
}
size_t tm_get(treemap *_map_, size_t key)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return tm_impl_default_value();
return node->value;
}
size_t *tm_get_ref(treemap *_map_, size_t key)
{
treemap_node *node = tm_impl_get_node(_map_, key);
if (!node)
return NULL;
return &(node->value);
}
bool tm_contains(treemap *_map_, size_t key)
{
treemap_node *scan = _map_->root;
while (scan != NULL)
{
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return true;
}
return false;
}
bool tm_empty(treemap *_map_) { return _map_->count == 0; }
size_t tm_count(treemap *_map_) { return _map_->count; }
treemap_iter *tm_iter_new(treemap *target)
{
treemap_iter *iter = malloc(sizeof(treemap_iter));
if (!iter)
return NULL;
tm_iter_init(iter, target);
return iter;
}
void tm_iter_free(treemap_iter *iter) { free(iter); }
void tm_iter_init(treemap_iter *iter, treemap *target)
{
iter->target = target;
iter->index = 0;
iter->start = true;
iter->end = tm_empty(target);
iter->cursor = target->root;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->first = iter->cursor;
iter->last = target->root;
while (iter->last->right != NULL)
iter->last = iter->last->right;
}
bool tm_iter_start(treemap_iter *iter) { return tm_empty(iter->target) || iter->start; }
bool tm_iter_end(treemap_iter *iter) { return tm_empty(iter->target) || iter->end; }
void tm_iter_to_start(treemap_iter *iter)
{
iter->index = 0;
iter->start = true;
iter->end = tm_empty(iter->target);
iter->cursor = iter->first;
}
void tm_iter_to_end(treemap_iter *iter)
{
iter->index = iter->target->count - 1;
iter->start = tm_empty(iter->target);
iter->end = true;
iter->cursor = iter->last;
}
bool tm_iter_next(treemap_iter *iter)
{
if (iter->end)
return false;
iter->start = false;
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
if (iter->cursor == iter->last)
{
iter->end = true;
return true;
}
if (iter->cursor->parent->left == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index++;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
bool tm_iter_prev(treemap_iter *iter)
{
if (iter->start)
return false;
iter->end = false;
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
if (iter->cursor == iter->first)
{
iter->start = true;
return true;
}
if (iter->cursor->parent->right == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index--;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
size_t tm_iter_key(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_key();
return iter->cursor->key;
}
size_t tm_iter_value(treemap_iter *iter)
{
if (tm_empty(iter->target))
return tm_impl_default_value();
return iter->cursor->value;
}
size_t *tm_iter_rvalue(treemap_iter *iter)
{
if (tm_empty(iter->target))
return NULL;
return &(iter->cursor->value);
}
size_t tm_iter_index(treemap_iter *iter) { return iter->index; }
static treemap_node *tm_impl_new_node(size_t key, size_t value)
{
treemap_node *node = malloc(sizeof(treemap_node));
if (!node)
return NULL;
node->key = key;
node->value = value;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treemap_node *tm_impl_get_node(treemap *_map_, size_t key)
{
if (tm_empty(_map_))
return NULL;
treemap_node *scan = _map_->root;
while (scan != NULL)
{
if (_map_->cmp(scan->key, key) > 0)
scan = scan->left;
else if (_map_->cmp(scan->key, key) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char tm_impl_h(treemap_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char tm_impl_hupdate(treemap_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = tm_impl_h(node->left);
unsigned char h_r = tm_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
static void tm_impl_rotate_right(treemap_node **Z)
{
treemap_node *root = *Z;
treemap_node *new_root = root->left;
if (root->parent != NULL)
{
if (root->parent->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
static void tm_impl_rotate_left(treemap_node **Z)
{
treemap_node *root = *Z;
treemap_node *new_root = root->right;
if (root->parent != NULL)
{
if (root->parent->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = tm_impl_hupdate(root);
new_root->height = tm_impl_hupdate(new_root);
*Z = new_root;
}
static void tm_impl_rebalance(treemap *_map_, treemap_node *node)
{
treemap_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = tm_impl_hupdate(scan);
balance = tm_impl_h(scan->right) - tm_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (tm_impl_h(child->right) < tm_impl_h(child->left))
tm_impl_rotate_right(&(scan->right));
tm_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (tm_impl_h(child->left) < tm_impl_h(child->right))
tm_impl_rotate_left(&(scan->left));
tm_impl_rotate_right(&scan);
}
if (is_root)
{
_map_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treemap_iter tm_impl_it_start(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
return iter;
}
static treemap_iter tm_impl_it_end(treemap *_map_)
{
treemap_iter iter;
tm_iter_init(&iter, _map_);
tm_iter_to_end(&iter);
return iter;
}
+688
View File
@@ -0,0 +1,688 @@
#include "cmc/treeset.h"
typedef struct treeset_s
{
struct treeset_node_s *root;
size_t count;
int (*cmp)(size_t, size_t);
struct treeset_iter_s (*it_start)(struct treeset_s *);
struct treeset_iter_s (*it_end)(struct treeset_s *);
} treeset, *treeset_ptr;
typedef struct treeset_node_s
{
size_t value;
unsigned char height;
struct treeset_node_s *right;
struct treeset_node_s *left;
struct treeset_node_s *parent;
} treeset_node, *treeset_node_ptr;
typedef struct treeset_iter_s
{
struct treeset_s *target;
struct treeset_node_s *cursor;
struct treeset_node_s *first;
struct treeset_node_s *last;
size_t index;
bool start;
bool end;
} treeset_iter, *treeset_iter_ptr;
treeset *ts_new(int (*compare)(size_t, size_t));
void ts_clear(treeset *_set_);
void ts_free(treeset *_set_);
bool ts_insert(treeset *_set_, size_t element);
bool ts_remove(treeset *_set_, size_t element);
bool ts_insert_if(treeset *_set_, size_t element, bool condition);
bool ts_remove_if(treeset *_set_, size_t element, bool condition);
bool ts_max(treeset *_set_, size_t *value);
bool ts_min(treeset *_set_, size_t *value);
bool ts_contains(treeset *_set_, size_t element);
bool ts_empty(treeset *_set_);
size_t ts_count(treeset *_set_);
treeset *ts_union(treeset *_set1_, treeset *_set2_);
treeset *ts_intersection(treeset *_set1_, treeset *_set2_);
treeset *ts_difference(treeset *_set1_, treeset *_set2_);
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_);
bool ts_is_subset(treeset *_set1_, treeset *_set2_);
bool ts_is_superset(treeset *_set1_, treeset *_set2_);
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_);
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_);
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_);
treeset_iter *ts_iter_new(treeset *target);
void ts_iter_free(treeset_iter *iter);
void ts_iter_init(treeset_iter *iter, treeset *target);
bool ts_iter_start(treeset_iter *iter);
bool ts_iter_end(treeset_iter *iter);
void ts_iter_to_start(treeset_iter *iter);
void ts_iter_to_end(treeset_iter *iter);
bool ts_iter_next(treeset_iter *iter);
bool ts_iter_prev(treeset_iter *iter);
size_t ts_iter_value(treeset_iter *iter);
size_t ts_iter_index(treeset_iter *iter);
static inline size_t ts_impl_default_value(void)
{
size_t _empty_value_;
memset(&_empty_value_, 0, sizeof(size_t));
return _empty_value_;
}
static treeset_node *ts_impl_new_node(size_t element);
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element);
static unsigned char ts_impl_h(treeset_node *node);
static unsigned char ts_impl_hupdate(treeset_node *node);
static void ts_impl_rotate_right(treeset_node **Z);
static void ts_impl_rotate_left(treeset_node **Z);
static void ts_impl_rebalance(treeset *_set_, treeset_node *node);
static treeset_iter ts_impl_it_start(treeset *_set_);
static treeset_iter ts_impl_it_end(treeset *_set_);
treeset *ts_new(int (*compare)(size_t, size_t))
{
treeset *_set_ = malloc(sizeof(treeset));
if (!_set_)
return NULL;
_set_->count = 0;
_set_->root = NULL;
_set_->cmp = compare;
_set_->it_start = ts_impl_it_start;
_set_->it_end = ts_impl_it_end;
return _set_;
}
void ts_clear(treeset *_set_)
{
treeset_node *scan = _set_->root;
treeset_node *up = NULL;
while (scan != NULL)
{
if (scan->left != NULL)
{
treeset_node *left = scan->left;
scan->left = up;
up = scan;
scan = left;
}
else if (scan->right != NULL)
{
treeset_node *right = scan->right;
scan->left = up;
scan->right = NULL;
up = scan;
scan = right;
}
else
{
if (up == NULL)
{
free(scan);
scan = NULL;
}
while (up != NULL)
{
free(scan);
if (up->right != NULL)
{
scan = up->right;
up->right = NULL;
break;
}
else
{
scan = up;
up = up->left;
}
}
}
}
_set_->count = 0;
_set_->root = NULL;
}
void ts_free(treeset *_set_)
{
ts_clear(_set_);
free(_set_);
}
bool ts_insert(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
{
_set_->root = ts_impl_new_node(element);
if (!_set_->root)
return false;
}
else
{
treeset_node *scan = _set_->root;
treeset_node *parent = scan;
while (scan != NULL)
{
parent = scan;
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return false;
}
treeset_node *node;
if (_set_->cmp(parent->value, element) > 0)
{
parent->left = ts_impl_new_node(element);
if (!parent->left)
return false;
parent->left->parent = parent;
node = parent->left;
}
else
{
parent->right = ts_impl_new_node(element);
if (!parent->right)
return false;
parent->right->parent = parent;
node = parent->right;
}
ts_impl_rebalance(_set_, node);
}
_set_->count++;
return true;
}
bool ts_remove(treeset *_set_, size_t element)
{
treeset_node *node = ts_impl_get_node(_set_, element);
if (!node)
return false;
treeset_node *temp = NULL, *unbalanced = NULL;
bool is_root = node->parent == NULL;
if (node->left == NULL && node->right == NULL)
{
if (is_root)
_set_->root = NULL;
else
{
unbalanced = node->parent;
if (node->parent->right == node)
node->parent->right = NULL;
else
node->parent->left = NULL;
}
free(node);
}
else if (node->left == NULL)
{
if (is_root)
{
_set_->root = node->right;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->right->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->right;
else
node->parent->left = node->right;
}
free(node);
}
else if (node->right == NULL)
{
if (is_root)
{
_set_->root = node->left;
_set_->root->parent = NULL;
}
else
{
unbalanced = node->parent;
node->left->parent = node->parent;
if (node->parent->right == node)
node->parent->right = node->left;
else
node->parent->left = node->left;
}
free(node);
}
else
{
temp = node->right;
while (temp->left != NULL)
temp = temp->left;
size_t temp_value = temp->value;
unbalanced = temp->parent;
if (temp->left == NULL && temp->right == NULL)
{
if (temp->parent->right == temp)
temp->parent->right = NULL;
else
temp->parent->left = NULL;
}
else if (temp->left == NULL)
{
temp->right->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->right;
else
temp->parent->left = temp->right;
}
else if (temp->right == NULL)
{
temp->left->parent = temp->parent;
if (temp->parent->right == temp)
temp->parent->right = temp->left;
else
temp->parent->left = temp->left;
}
free(temp);
node->value = temp_value;
}
if (unbalanced != NULL)
ts_impl_rebalance(_set_, unbalanced);
_set_->count--;
if (_set_->count == 0)
_set_->root = NULL;
return true;
}
bool ts_insert_if(treeset *_set_, size_t element, bool condition)
{
if (condition)
return ts_insert(_set_, element);
return false;
}
bool ts_remove_if(treeset *_set_, size_t element, bool condition)
{
if (condition)
return ts_remove(_set_, element);
return false;
}
bool ts_max(treeset *_set_, size_t *value)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->right != NULL)
scan = scan->right;
*value = scan->value;
return true;
}
bool ts_min(treeset *_set_, size_t *value)
{
if (ts_empty(_set_))
return false;
treeset_node *scan = _set_->root;
while (scan->left != NULL)
scan = scan->left;
*value = scan->value;
return true;
}
bool ts_contains(treeset *_set_, size_t element)
{
treeset_node *scan = _set_->root;
while (scan != NULL)
{
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return true;
}
return false;
}
bool ts_empty(treeset *_set_) { return _set_->count == 0; }
size_t ts_count(treeset *_set_) { return _set_->count; }
treeset *ts_union(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter1, iter2;
ts_iter_init(&iter1, _set1_);
ts_iter_init(&iter2, _set2_);
for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1))
{
ts_insert(_set_r_, ts_iter_value(&iter1));
}
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
{
ts_insert(_set_r_, ts_iter_value(&iter2));
}
return _set_r_;
}
treeset *ts_intersection(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_;
treeset *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_;
treeset_iter iter;
ts_iter_init(&iter, _set_A_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_impl_get_node(_set_B_, value) != NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_impl_get_node(_set2_, value) == NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
treeset *ts_symmetric_difference(treeset *_set1_, treeset *_set2_)
{
treeset *_set_r_ = ts_new(_set1_->cmp);
if (!_set_r_)
return false;
treeset_iter iter1, iter2;
ts_iter_init(&iter1, _set1_);
ts_iter_init(&iter2, _set2_);
for (ts_iter_to_start(&iter1); !ts_iter_end(&iter1); ts_iter_next(&iter1))
{
size_t value = ts_iter_value(&iter1);
if (ts_impl_get_node(_set2_, value) == NULL)
ts_insert(_set_r_, value);
}
for (ts_iter_to_start(&iter2); !ts_iter_end(&iter2); ts_iter_next(&iter2))
{
size_t value = ts_iter_value(&iter2);
if (ts_impl_get_node(_set1_, value) == NULL)
ts_insert(_set_r_, value);
}
return _set_r_;
}
bool ts_is_subset(treeset *_set1_, treeset *_set2_)
{
if (ts_count(_set1_) > ts_count(_set2_))
return false;
if (ts_empty(_set1_))
return true;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (!ts_contains(_set2_, value))
return false;
}
return true;
}
bool ts_is_superset(treeset *_set1_, treeset *_set2_) { return ts_is_subset(_set2_, _set1_); }
bool ts_is_proper_subset(treeset *_set1_, treeset *_set2_)
{
if (ts_count(_set1_) >= ts_count(_set2_))
return false;
if (ts_empty(_set1_))
{
if (!ts_empty(_set2_))
return true;
else
return false;
}
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (!ts_contains(_set2_, value))
return false;
}
return true;
}
bool ts_is_proper_superset(treeset *_set1_, treeset *_set2_) { return ts_is_proper_subset(_set2_, _set1_); }
bool ts_is_disjointset(treeset *_set1_, treeset *_set2_)
{
if (ts_empty(_set1_))
return true;
treeset_iter iter;
ts_iter_init(&iter, _set1_);
for (ts_iter_to_start(&iter); !ts_iter_end(&iter); ts_iter_next(&iter))
{
size_t value = ts_iter_value(&iter);
if (ts_contains(_set2_, value))
return false;
}
return true;
}
treeset_iter *ts_iter_new(treeset *target)
{
treeset_iter *iter = malloc(sizeof(treeset_iter));
if (!iter)
return NULL;
ts_iter_init(iter, target);
return iter;
}
void ts_iter_free(treeset_iter *iter) { free(iter); }
void ts_iter_init(treeset_iter *iter, treeset *target)
{
iter->target = target;
iter->index = 0;
iter->start = true;
iter->end = ts_empty(target);
iter->cursor = target->root;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->first = iter->cursor;
iter->last = target->root;
while (iter->last->right != NULL)
iter->last = iter->last->right;
}
bool ts_iter_start(treeset_iter *iter) { return ts_empty(iter->target) || iter->start; }
bool ts_iter_end(treeset_iter *iter) { return ts_empty(iter->target) || iter->end; }
void ts_iter_to_start(treeset_iter *iter)
{
iter->index = 0;
iter->start = true;
iter->end = ts_empty(iter->target);
iter->cursor = iter->first;
}
void ts_iter_to_end(treeset_iter *iter)
{
iter->index = iter->target->count - 1;
iter->start = ts_empty(iter->target);
iter->end = true;
iter->cursor = iter->last;
}
bool ts_iter_next(treeset_iter *iter)
{
if (iter->end)
return false;
iter->start = ts_empty(iter->target);
if (iter->cursor->right != NULL)
{
iter->cursor = iter->cursor->right;
while (iter->cursor->left != NULL)
iter->cursor = iter->cursor->left;
iter->index++;
return true;
}
while (true)
{
if (iter->cursor == iter->last)
{
iter->end = true;
return true;
}
if (iter->cursor->parent->left == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index++;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
bool ts_iter_prev(treeset_iter *iter)
{
if (iter->start)
return false;
iter->end = ts_empty(iter->target);
if (iter->cursor->left != NULL)
{
iter->cursor = iter->cursor->left;
while (iter->cursor->right != NULL)
iter->cursor = iter->cursor->right;
iter->index--;
return true;
}
while (true)
{
if (iter->cursor == iter->first)
{
iter->start = true;
return true;
}
if (iter->cursor->parent->right == iter->cursor)
{
iter->cursor = iter->cursor->parent;
iter->index--;
return true;
}
iter->cursor = iter->cursor->parent;
}
}
size_t ts_iter_value(treeset_iter *iter)
{
if (ts_empty(iter->target))
return ts_impl_default_value();
return iter->cursor->value;
}
size_t ts_iter_index(treeset_iter *iter) { return iter->index; }
static treeset_node *ts_impl_new_node(size_t element)
{
treeset_node *node = malloc(sizeof(treeset_node));
if (!node)
return NULL;
node->value = element;
node->right = NULL;
node->left = NULL;
node->parent = NULL;
node->height = 0;
return node;
}
static treeset_node *ts_impl_get_node(treeset *_set_, size_t element)
{
if (ts_empty(_set_))
return NULL;
treeset_node *scan = _set_->root;
while (scan != NULL)
{
if (_set_->cmp(scan->value, element) > 0)
scan = scan->left;
else if (_set_->cmp(scan->value, element) < 0)
scan = scan->right;
else
return scan;
}
return NULL;
}
static unsigned char ts_impl_h(treeset_node *node)
{
if (node == NULL)
return 0;
return node->height;
}
static unsigned char ts_impl_hupdate(treeset_node *node)
{
if (node == NULL)
return 0;
unsigned char h_l = ts_impl_h(node->left);
unsigned char h_r = ts_impl_h(node->right);
return 1 + (h_l > h_r ? h_l : h_r);
}
static void ts_impl_rotate_right(treeset_node **Z)
{
treeset_node *root = *Z;
treeset_node *new_root = root->left;
if (root->parent != NULL)
{
if (root->parent->left == root)
root->parent->left = new_root;
else
root->parent->right = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->left = new_root->right;
if (root->left)
root->left->parent = root;
new_root->right = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
static void ts_impl_rotate_left(treeset_node **Z)
{
treeset_node *root = *Z;
treeset_node *new_root = root->right;
if (root->parent != NULL)
{
if (root->parent->right == root)
root->parent->right = new_root;
else
root->parent->left = new_root;
}
new_root->parent = root->parent;
root->parent = new_root;
root->right = new_root->left;
if (root->right)
root->right->parent = root;
new_root->left = root;
root->height = ts_impl_hupdate(root);
new_root->height = ts_impl_hupdate(new_root);
*Z = new_root;
}
static void ts_impl_rebalance(treeset *_set_, treeset_node *node)
{
treeset_node *scan = node, *child = NULL;
int balance;
bool is_root = false;
while (scan != NULL)
{
if (scan->parent == NULL)
is_root = true;
scan->height = ts_impl_hupdate(scan);
balance = ts_impl_h(scan->right) - ts_impl_h(scan->left);
if (balance >= 2)
{
child = scan->right;
if (ts_impl_h(child->right) < ts_impl_h(child->left))
ts_impl_rotate_right(&(scan->right));
ts_impl_rotate_left(&scan);
}
else if (balance <= -2)
{
child = scan->left;
if (ts_impl_h(child->left) < ts_impl_h(child->right))
ts_impl_rotate_left(&(scan->left));
ts_impl_rotate_right(&scan);
}
if (is_root)
{
_set_->root = scan;
is_root = false;
}
scan = scan->parent;
}
}
static treeset_iter ts_impl_it_start(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
return iter;
}
static treeset_iter ts_impl_it_end(treeset *_set_)
{
treeset_iter iter;
ts_iter_init(&iter, _set_);
ts_iter_to_end(&iter);
return iter;
}
+2 -1
View File
@@ -64,8 +64,9 @@ CMC_CREATE_UNIT(deque_test, true, {
d_push_back(d, i);
cmc_assert_equals(size_t, 50, d_count(d));
cmc_assert_lesser_equals(size_t, d_capacity(d), d_count(d));
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 50);
CMC_TEST_PASS_ELSE_FAIL(d_count(d) == 50 && d_count(d) <= d_capacity(d));
d_free(d);
});
+73
View File
@@ -0,0 +1,73 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/queue.c"
CMC_CREATE_UNIT(queue_test, true, {
CMC_CREATE_TEST(new, {
queue *q = q_new(1000000);
cmc_assert_not_equals(ptr, NULL, q);
bool passed = q->capacity == 1000000 && q->count == 0 && q->buffer;
cmc_assert_equals(size_t, 1000000, q->capacity);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_not_equals(ptr, NULL, q->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
q_free(q);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
queue *q = q_new(0);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
queue *q = q_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, q);
CMC_TEST_PASS_ELSE_FAIL(q == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
queue *q = q_new(100);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert_equals(size_t, 50, q_count(q));
q_clear(q);
cmc_assert_equals(size_t, 0, q_count(q));
cmc_assert_equals(size_t, 100, q_capacity(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 0 && q_capacity(q) == 100);
q_free(q);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
queue *q = q_new(1);
cmc_assert_not_equals(ptr, NULL, q);
for (size_t i = 0; i < 50; i++)
q_enqueue(q, i);
cmc_assert_equals(size_t, 50, q_count(q));
CMC_TEST_PASS_ELSE_FAIL(q_count(q) == 50);
q_free(q);
});
});
+335
View File
@@ -0,0 +1,335 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/stack.c"
CMC_CREATE_UNIT(stack_test, true, {
CMC_CREATE_TEST(new, {
stack *s = s_new(1000000);
cmc_assert_not_equals(ptr, NULL, s);
bool passed = s->capacity == 1000000 && s->count == 0 && s->buffer;
cmc_assert_equals(size_t, 1000000, s->capacity);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_not_equals(ptr, NULL, s->buffer);
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(new[edge_case:capacity = 0], {
stack *s = s_new(0);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(new[edge_case:capacity = UINT64_MAX], {
stack *s = s_new(UINT64_MAX);
cmc_assert_equals(ptr, NULL, s);
CMC_TEST_PASS_ELSE_FAIL(s == NULL);
});
CMC_CREATE_TEST(clear[count capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
s_clear(s);
cmc_assert_equals(size_t, 0, s_count(s));
cmc_assert_equals(size_t, 100, s_capacity(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 0 && s_capacity(s) == 100);
s_free(s);
});
CMC_CREATE_TEST(buffer_growth[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 50; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 50, s_count(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 50 && s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(push[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_equals(size_t, 250, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 250);
s_free(s);
});
CMC_CREATE_TEST(push[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(push[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(pop[count], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 249, s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) == 249);
s_free(s);
});
CMC_CREATE_TEST(pop[capacity], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert_lesser_equals(size_t, s_capacity(s), s_count(s));
CMC_TEST_PASS_ELSE_FAIL(s_count(s) <= s_capacity(s));
s_free(s);
});
CMC_CREATE_TEST(pop[item_preservation], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = s->buffer[i] == i;
cmc_assert_equals(size_t, i, s->buffer[i]);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(push_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
s_push_if(s, i, i % 2 == 0);
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && s->buffer[i] % 2 == 0;
cmc_assert(s->buffer[i] % 2 == 0);
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(pop_if, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
{
s_push(s, i);
s_pop_if(s, s_top(s) % 2 == 0);
}
bool passed = true;
for (size_t i = 0; i < s_count(s); i++)
{
passed = passed && !(s->buffer[i] % 2 == 0);
cmc_assert(!(s->buffer[i] % 2 == 0));
}
CMC_TEST_PASS_ELSE_FAIL(passed);
s_free(s);
});
CMC_CREATE_TEST(top, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < 250; i++)
cmc_assert(s_push(s, i));
cmc_assert(s_pop(s));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, 247, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(247 == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 0], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 1));
cmc_assert(s_pop(s));
cmc_assert_equals(size_t, s_impl_default_value(), s_top(s));
CMC_TEST_PASS_ELSE_FAIL(s_impl_default_value() == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(top[edge_case:count = 1], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert_equals(size_t, 1, s_count(s));
cmc_assert_equals(size_t, 10, s_top(s));
CMC_TEST_PASS_ELSE_FAIL(10 == s_top(s));
s_free(s);
});
CMC_CREATE_TEST(empty, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(empty[after_io], {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_pop(s));
cmc_assert(s_empty(s));
CMC_TEST_PASS_ELSE_FAIL(s_empty(s));
s_free(s);
});
CMC_CREATE_TEST(full, {
stack *s = s_new(100);
cmc_assert_not_equals(ptr, NULL, s);
for (size_t i = 0; i < s_capacity(s); i++)
cmc_assert(s_push(s, i));
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
});
CMC_CREATE_TEST(full[edge_case:capacity = 1], {
stack *s = s_new(1);
cmc_assert_not_equals(ptr, NULL, s);
cmc_assert(s_push(s, 10));
cmc_assert(s_full(s));
CMC_TEST_PASS_ELSE_FAIL(s_full(s));
s_free(s);
});
});
+38
View File
@@ -0,0 +1,38 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treemap.c"
#include "utl.c"
CMC_CREATE_UNIT(treemap_test, true, {
CMC_CREATE_TEST(new, {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
CMC_TEST_PASS_ELSE_FAIL(map);
tm_free(map);
});
CMC_CREATE_TEST(clear[count], {
treemap *map = tm_new(cmp);
cmc_assert_not_equals(ptr, NULL, map);
for (size_t i = 0; i < 50; i++)
tm_insert(map, i, i);
cmc_assert_equals(size_t, 50, tm_count(map));
tm_clear(map);
cmc_assert_equals(size_t, 0, tm_count(map));
cmc_assert_equals(ptr, NULL, map->root);
CMC_TEST_PASS_ELSE_FAIL(tm_count(map) == 0);
tm_free(map);
});
});
+39
View File
@@ -0,0 +1,39 @@
#include "utl/assert.h"
#include "utl/test.h"
#include "../src/treeset.c"
#include "utl.c"
CMC_CREATE_UNIT(treeset_test, true, {
CMC_CREATE_TEST(new, {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
CMC_TEST_PASS_ELSE_FAIL(set);
ts_free(set);
});
CMC_CREATE_TEST(clear[count], {
treeset *set = ts_new(cmp);
cmc_assert_not_equals(ptr, NULL, set);
for (size_t i = 0; i < 50; i++)
ts_insert(set, i);
cmc_assert_equals(size_t, 50, ts_count(set));
ts_clear(set);
cmc_assert_equals(size_t, 0, ts_count(set));
cmc_assert_equals(ptr, NULL, set->root);
CMC_TEST_PASS_ELSE_FAIL(ts_count(set) == 0);
ts_free(set);
});
});