Fixing and adding more tests
This commit is contained in:
1 parent
8c457eeb12
commit
97d50bc3d9
13 files changed
+2264
-19
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
Reference in new issue
Block a user