diff --git a/src/hashmap.h b/src/hashmap.h new file mode 100644 index 0000000..0d28d39 --- /dev/null +++ b/src/hashmap.h @@ -0,0 +1,529 @@ +/** + * hashmap.h + * + * Creation Date: 03/04/2019 + * + * Authors: + * Leonardo Vencovsky (https://github.com/LeoVen) + * + */ + +/*****************************************************************************/ +/******************************************************************* HASHMAP */ +/*****************************************************************************/ + +#ifndef CMC_HASHMAP_H +#define CMC_HASHMAP_H + +#include +#include +#include + +#ifndef CMC_HASH_TABLE_SETUP +#define CMC_HASH_TABLE_SETUP + +typedef enum EntryState_e +{ + ES_DELETED = -1, + ES_EMPTY = 0, + ES_FILLED = 1 +} EntryState; + +static const size_t cmc_hashtable_primes[] = {53, 97, 193, 389, 769, 1543, 3079, + 6151, 12289, 24593, 49157, 98317, + 196613, 393241, 786433, 1572869, + 3145739, 6291469, 12582917, + 25165843, 50331653, 100663319, + 201326611, 402653189, 805306457, + 1610612741}; + +#endif /* CMC_HASH_TABLE_SETUP */ + +#define HASHMAP_GENERATE(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) + +/* PRIVATE *******************************************************************/ +#define HASHMAP_GENERATE_HEADER_PRIVATE(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define HASHMAP_GENERATE_SOURCE_PRIVATE(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +/* PUBLIC ********************************************************************/ +#define HASHMAP_GENERATE_HEADER_PUBLIC(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) +#define HASHMAP_GENERATE_SOURCE_PUBLIC(PFX, SNAME, FMOD, K, V) \ + HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) +/* STRUCT ********************************************************************/ +#define HASHMAP_GENERATE_STRUCT(PFX, SNAME, FMOD, K, V) \ + \ + struct SNAME##_s \ + { \ + struct SNAME##_entry_s *buffer; \ + size_t capacity; \ + size_t count; \ + double load; \ + int (*cmp)(K, K); \ + size_t (*hash)(K); \ + }; \ + \ + struct SNAME##_entry_s \ + { \ + K key; \ + V value; \ + size_t dist; \ + enum EntryState_e state; \ + }; \ + \ + struct SNAME##_iter_s \ + { \ + struct SNAME##_s *target; \ + size_t cursor; \ + size_t index; \ + size_t first; \ + size_t last; \ + bool start; \ + bool end; \ + }; \ + \ +/* HEADER ********************************************************************/ +#define HASHMAP_GENERATE_HEADER(PFX, SNAME, FMOD, K, V) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_entry_s SNAME##_entry; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)); \ + FMOD void PFX##_free(SNAME *_map_); \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value); \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value); \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition); \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value); \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value); \ + FMOD V PFX##_get(SNAME *_map_, K key); \ + FMOD bool PFX##_empty(SNAME *_map_); \ + FMOD size_t PFX##_count(SNAME *_map_); \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index); \ + \ +/* SOURCE ********************************************************************/ +#define HASHMAP_GENERATE_SOURCE(PFX, SNAME, FMOD, K, V) \ + \ + FMOD bool PFX##_grow(SNAME *_map_); \ + FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key); \ + FMOD size_t PFX##_calculate_size(size_t required); \ + \ + FMOD SNAME *PFX##_new(size_t size, double load, int (*compare)(K, K), size_t (*hash)(K)) \ + { \ + if (size == 0 || load <= 0 || load >= 1) \ + return NULL; \ + \ + size_t real_size = PFX##_calculate_size(size); \ + \ + SNAME *_map_ = malloc(sizeof(SNAME)); \ + \ + if (!_map_) \ + return NULL; \ + \ + _map_->buffer = malloc(sizeof(SNAME##_entry) * real_size); \ + \ + if (!_map_->buffer) \ + { \ + free(_map_); \ + return NULL; \ + } \ + \ + memset(_map_->buffer, 0, sizeof(SNAME##_entry) * real_size); \ + \ + _map_->count = 0; \ + _map_->capacity = real_size; \ + _map_->load = load; \ + _map_->cmp = compare; \ + _map_->hash = hash; \ + \ + return _map_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_map_) \ + { \ + free(_map_->buffer); \ + free(_map_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_map_, K key, V value) \ + { \ + if ((double)_map_->capacity * _map_->load <= (double)_map_->count) \ + { \ + if (!PFX##_grow(_map_)) \ + return false; \ + } \ + \ + size_t hash = _map_->hash(key); \ + size_t original_pos = hash % _map_->capacity; \ + size_t pos = original_pos; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos]); \ + \ + if (PFX##_get_entry(_map_, key) != NULL) \ + return false; \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = original_pos - pos; \ + target->state = ES_FILLED; \ + } \ + else \ + { \ + while (true) \ + { \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + \ + if (target->state == ES_EMPTY || target->state == ES_DELETED) \ + { \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + target->state = ES_FILLED; \ + break; \ + } \ + else if (target->dist < original_pos - pos) \ + { \ + K tmp_k = target->key; \ + V tmp_v = target->value; \ + size_t tmp_dist = target->dist; \ + \ + target->key = key; \ + target->value = value; \ + target->dist = pos - original_pos; \ + \ + key = tmp_k; \ + value = tmp_v; \ + original_pos = pos - tmp_dist; \ + } \ + } \ + } \ + \ + _map_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_map_, K key, V *value) \ + { \ + SNAME##_entry *result = PFX##_get_entry(_map_, key); \ + \ + if (result == NULL) \ + return false; \ + \ + *value = result->value; \ + \ + result->value = 0; \ + result->dist = 0; \ + result->state = ES_DELETED; \ + \ + _map_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_map_, K key, V value, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_map_, K key, V *value, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_map_, key, value); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_max(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + K result_key, max_key; \ + V result_value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &result_key, &result_value, &index); \ + \ + if (index == 0) \ + { \ + max_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, max_key) > 0) \ + { \ + max_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_min(SNAME *_map_, K *key, V *value) \ + { \ + if (PFX##_empty(_map_)) \ + return false; \ + \ + SNAME##_iter iter; \ + K result_key, min_key; \ + V result_value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &result_key, &result_value, &index); \ + \ + if (index == 0) \ + { \ + min_key = result_key; \ + *key = result_key; \ + *value = result_value; \ + } \ + else if (_map_->cmp(result_key, min_key) < 0) \ + { \ + min_key = result_key; \ + *key = min_key; \ + *value = result_value; \ + } \ + } \ + \ + return true; \ + } \ + \ + FMOD V PFX##_get(SNAME *_map_, K key) \ + { \ + SNAME##_entry *entry = PFX##_get_entry(_map_, key); \ + \ + if (!entry) \ + return 0; \ + \ + return entry->value; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_map_) \ + { \ + return _map_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_map_) \ + { \ + return _map_->count; \ + } \ + \ + FMOD bool PFX##_grow(SNAME *_map_) \ + { \ + size_t new_size = PFX##_calculate_size((size_t)((double)_map_->capacity * 1.5)); \ + \ + SNAME *_new_map_ = PFX##_new(new_size, _map_->load, _map_->cmp, _map_->hash); \ + \ + if (!_new_map_) \ + return false; \ + \ + SNAME##_iter iter; \ + K key; \ + V value; \ + size_t index; \ + \ + for (PFX##_iter_new(&iter, _map_); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &key, &value, &index); \ + PFX##_insert(_new_map_, key, value); \ + } \ + \ + if (_map_->count != _new_map_->count) \ + { \ + PFX##_free(_new_map_); \ + return false; \ + } \ + \ + SNAME##_entry *tmp = _map_->buffer; \ + _map_->buffer = _new_map_->buffer; \ + _new_map_->buffer = tmp; \ + \ + _map_->capacity = _new_map_->capacity; \ + \ + PFX##_free(_new_map_); \ + \ + return true; \ + } \ + \ + FMOD SNAME##_entry *PFX##_get_entry(SNAME *_map_, K key) \ + { \ + size_t hash = _map_->hash(key); \ + size_t pos = hash % _map_->capacity; \ + \ + SNAME##_entry *target = &(_map_->buffer[pos % _map_->capacity]); \ + \ + while (target->state == ES_FILLED || target->state == ES_DELETED) \ + { \ + if (_map_->cmp(target->key, key) == 0) \ + return target; \ + \ + pos++; \ + target = &(_map_->buffer[pos % _map_->capacity]); \ + } \ + \ + return NULL; \ + } \ + \ + FMOD size_t PFX##_calculate_size(size_t required) \ + { \ + const size_t count = sizeof(cmc_hashtable_primes) / sizeof(cmc_hashtable_primes[0]); \ + \ + if (cmc_hashtable_primes[count - 1] < required) \ + return required; \ + \ + size_t i = 0; \ + while (cmc_hashtable_primes[i] < required) \ + i++; \ + \ + return cmc_hashtable_primes[i]; \ + } \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->cursor = 0; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(target); \ + \ + if (!PFX##_empty(target)) \ + { \ + for (size_t i = 0; i < target->capacity; i++) \ + { \ + if (target->buffer[i].state == ES_FILLED) \ + { \ + iter->first = i; \ + break; \ + } \ + } \ + \ + iter->cursor = iter->first; \ + \ + for (size_t i = target->capacity; i > 0; i--) \ + { \ + if (target->buffer[i - 1].state == ES_FILLED) \ + { \ + iter->last = i - 1; \ + break; \ + } \ + } \ + } \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return iter->start && iter->cursor == iter->first; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return iter->end && iter->cursor == iter->last; \ + } \ + \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ + \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, K *key, V *value, size_t *index) \ + { \ + if (iter->end) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + *key = scan->key; \ + *value = scan->value; \ + *index = iter->index; \ + \ + if (iter->cursor == iter->last) \ + iter->end = true; \ + else \ + { \ + iter->index++; \ + while (1) \ + { \ + iter->cursor++; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, K *key, V *value, size_t *index) \ + { \ + if (iter->start) \ + return false; \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + *key = scan->key; \ + *value = scan->value; \ + *index = iter->index; \ + \ + if (iter->cursor == iter->first) \ + iter->start = true; \ + else \ + { \ + iter->index--; \ + while (1) \ + { \ + iter->cursor--; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == ES_FILLED) \ + break; \ + } \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + return true; \ + } + +#endif /* CMC_HASHMAP_H */ diff --git a/src/macro_collections.h b/src/macro_collections.h index 62c6042..0a885a9 100644 --- a/src/macro_collections.h +++ b/src/macro_collections.h @@ -41,6 +41,7 @@ #include "treeset.h" #include "treemap.h" #include "hashset.h" +#include "hashmap.h" #include "foreach.h" diff --git a/src/treeset.h b/src/treeset.h index 77b316d..05eed4c 100644 --- a/src/treeset.h +++ b/src/treeset.h @@ -66,733 +66,733 @@ }; \ \ /* HEADER ********************************************************************/ -#define TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ - \ - typedef struct SNAME##_s SNAME; \ - typedef struct SNAME##_node_s SNAME##_node; \ - typedef struct SNAME##_iter_s SNAME##_iter; \ - \ - FMOD SNAME *PFX##_new(int (*compare)(V, V)); \ - FMOD void PFX##_free(SNAME *_set_); \ - FMOD bool PFX##_insert(SNAME *_set_, V element); \ - FMOD bool PFX##_remove(SNAME *_set_, V element); \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ - FMOD V PFX##_max(SNAME *_set_); \ - FMOD V PFX##_min(SNAME *_set_); \ - FMOD bool PFX##_empty(SNAME *_set_); \ - FMOD size_t PFX##_count(SNAME *_set_); \ - \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ - \ - FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index); \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index); \ - \ +#define TREESET_GENERATE_HEADER(PFX, SNAME, FMOD, V) \ + \ + typedef struct SNAME##_s SNAME; \ + typedef struct SNAME##_node_s SNAME##_node; \ + typedef struct SNAME##_iter_s SNAME##_iter; \ + \ + FMOD SNAME *PFX##_new(int (*compare)(V, V)); \ + FMOD void PFX##_free(SNAME *_set_); \ + FMOD bool PFX##_insert(SNAME *_set_, V element); \ + FMOD bool PFX##_remove(SNAME *_set_, V element); \ + FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition); \ + FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition); \ + FMOD V PFX##_max(SNAME *_set_); \ + FMOD V PFX##_min(SNAME *_set_); \ + FMOD bool PFX##_empty(SNAME *_set_); \ + FMOD size_t PFX##_count(SNAME *_set_); \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_); \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_); \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target); \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter); \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter); \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index); \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index); \ + \ /* SOURCE ********************************************************************/ -#define TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ - \ - FMOD SNAME##_node *PFX##_new_node(V element); \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element); \ - FMOD unsigned char PFX##_h(SNAME##_node *node); \ - FMOD unsigned char PFX##_hupdate(SNAME##_node *node); \ - FMOD void PFX##_rotate_right(SNAME##_node **Z); \ - FMOD void PFX##_rotate_left(SNAME##_node **Z); \ - FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node); \ - \ - FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ - { \ - SNAME *_set_ = malloc(sizeof(SNAME)); \ - \ - if (!_set_) \ - return NULL; \ - \ - _set_->count = 0; \ - _set_->root = NULL; \ - _set_->cmp = compare; \ - \ - return _set_; \ - } \ - \ - FMOD void PFX##_free(SNAME *_set_) \ - { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *up = NULL; \ - \ - while (scan != NULL) \ - { \ - if (scan->left != NULL) \ - { \ - SNAME##_node *left = scan->left; \ - \ - scan->left = up; \ - up = scan; \ - scan = left; \ - } \ - else if (scan->right != NULL) \ - { \ - SNAME##_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; \ - } \ - } \ - } \ - } \ - \ - free(_set_); \ - } \ - \ - FMOD bool PFX##_insert(SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - { \ - _set_->root = PFX##_new_node(element); \ - if (!_set_->root) \ - return false; \ - } \ - else \ - { \ - SNAME##_node *scan = _set_->root; \ - SNAME##_node *parent = scan; \ - \ - while (scan != NULL) \ - { \ - parent = scan; \ - \ - if (_set_->cmp(scan->key, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->key, element) < 0) \ - scan = scan->right; \ - else \ - return false; \ - } \ - \ - SNAME##_node *node; \ - \ - if (_set_->cmp(parent->key, element) > 0) \ - { \ - parent->left = PFX##_new_node(element); \ - \ - if (!parent->left) \ - return false; \ - \ - parent->left->parent = parent; \ - node = parent->left; \ - } \ - else \ - { \ - parent->right = PFX##_new_node(element); \ - \ - if (!parent->right) \ - return false; \ - \ - parent->right->parent = parent; \ - node = parent->right; \ - } \ - \ - PFX##_rebalance(_set_, node); \ - } \ - \ - _set_->count++; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_remove(SNAME *_set_, V element) \ - { \ - SNAME##_node *node = PFX##_get_node(_set_, element); \ - \ - if (!node) \ - return false; \ - \ - SNAME##_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; \ - \ - V temp_key = temp->key; \ - \ - 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; \ - } \ - \ - if (unbalanced != NULL) \ - PFX##_rebalance(_set_, unbalanced); \ - \ - _set_->count--; \ - \ - return true; \ - } \ - \ - FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_insert(_set_, element); \ - \ - return false; \ - } \ - \ - FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ - { \ - if (condition) \ - return PFX##_remove(_set_, element); \ - \ - return false; \ - } \ - \ - FMOD V PFX##_max(SNAME *_set_) \ - { \ - if (PFX##_empty(_set_)) \ - return 0; \ - \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan->right != NULL) \ - scan = scan->right; \ - \ - return scan->key; \ - } \ - \ - FMOD V PFX##_min(SNAME *_set_) \ - { \ - if (PFX##_empty(_set_)) \ - return 0; \ - \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan->left != NULL) \ - scan = scan->left; \ - \ - return scan->key; \ - } \ - \ - FMOD bool PFX##_empty(SNAME *_set_) \ - { \ - return _set_->count == 0; \ - } \ - \ - FMOD size_t PFX##_count(SNAME *_set_) \ - { \ - return _set_->count; \ - } \ - \ - FMOD SNAME##_node *PFX##_new_node(V element) \ - { \ - SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ - \ - if (!node) \ - return NULL; \ - \ - node->key = element; \ - node->right = NULL; \ - node->left = NULL; \ - node->parent = NULL; \ - node->height = 0; \ - \ - return node; \ - } \ - \ - FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element) \ - { \ - if (PFX##_empty(_set_)) \ - return NULL; \ - \ - SNAME##_node *scan = _set_->root; \ - \ - while (scan != NULL) \ - { \ - if (_set_->cmp(scan->key, element) > 0) \ - scan = scan->left; \ - else if (_set_->cmp(scan->key, element) < 0) \ - scan = scan->right; \ - else \ - return scan; \ - } \ - \ - return NULL; \ - } \ - \ - FMOD unsigned char PFX##_h(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - return node->height; \ - } \ - \ - FMOD unsigned char PFX##_hupdate(SNAME##_node *node) \ - { \ - if (node == NULL) \ - return 0; \ - \ - unsigned char h_l = PFX##_h(node->left); \ - unsigned char h_r = PFX##_h(node->right); \ - \ - return 1 + (h_l > h_r ? h_l : h_r); \ - } \ - \ - FMOD void PFX##_rotate_right(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_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 = PFX##_hupdate(root); \ - new_root->height = PFX##_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - FMOD void PFX##_rotate_left(SNAME##_node **Z) \ - { \ - SNAME##_node *root = *Z; \ - SNAME##_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 = PFX##_hupdate(root); \ - new_root->height = PFX##_hupdate(new_root); \ - \ - *Z = new_root; \ - } \ - \ - FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node) \ - { \ - SNAME##_node *scan = node, *child = NULL; \ - \ - int balance; \ - bool is_root = false; \ - \ - while (scan != NULL) \ - { \ - if (scan->parent == NULL) \ - is_root = true; \ - \ - scan->height = PFX##_hupdate(scan); \ - balance = PFX##_h(scan->right) - PFX##_h(scan->left); \ - \ - if (balance >= 2) \ - { \ - child = scan->right; \ - \ - if (PFX##_h(child->right) < PFX##_h(child->left)) \ - PFX##_rotate_right(&(scan->right)); \ - \ - PFX##_rotate_left(&scan); \ - } \ - else if (balance <= -2) \ - { \ - child = scan->left; \ - \ - if (PFX##_h(child->left) < PFX##_h(child->right)) \ - PFX##_rotate_left(&(scan->left)); \ - \ - PFX##_rotate_right(&scan); \ - } \ - \ - if (is_root) \ - { \ - _set_->root = scan; \ - is_root = false; \ - } \ - \ - scan = scan->parent; \ - } \ - } \ - \ - FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter1, iter2; \ - size_t index; \ - V value; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return false; \ - \ - PFX##_iter_new(&iter1, _set1_); \ - PFX##_iter_new(&iter2, _set2_); \ - \ - for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ - { \ - PFX##_iter_next(&iter1, &value, &index); \ - PFX##_insert(_set_r_, value); \ - } \ - \ - for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ - { \ - PFX##_iter_next(&iter2, &value, &index); \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter; \ - size_t index; \ - V value; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return false; \ - \ - SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ - SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ - \ - PFX##_iter_new(&iter, _set_A_); \ - \ - for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ - { \ - PFX##_iter_next(&iter, &value, &index); \ - if (PFX##_get_node(_set_B_, value) != NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter; \ - size_t index; \ - V value; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return false; \ - \ - PFX##_iter_new(&iter, _set1_); \ - \ - for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ - { \ - PFX##_iter_next(&iter, &value, &index); \ - if (PFX##_get_node(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ - { \ - SNAME##_iter iter1, iter2; \ - size_t index; \ - V value; \ - \ - SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ - \ - if (!_set_r_) \ - return false; \ - \ - PFX##_iter_new(&iter1, _set1_); \ - PFX##_iter_new(&iter2, _set2_); \ - \ - for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ - { \ - PFX##_iter_next(&iter1, &value, &index); \ - if (PFX##_get_node(_set2_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ - { \ - PFX##_iter_next(&iter2, &value, &index); \ - if (PFX##_get_node(_set1_, value) == NULL) \ - PFX##_insert(_set_r_, value); \ - } \ - \ - return _set_r_; \ - } \ - \ - FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \ - { \ - iter->target = target; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_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; \ - } \ - \ - FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ - { \ - return iter->start && iter->cursor == iter->first; \ - } \ - \ - FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ - { \ - return iter->end && iter->cursor == iter->last; \ - } \ - \ - FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ - { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ - } \ - \ - FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ - { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ - } \ - \ - FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *result, size_t *index) \ - { \ - if (iter->end) \ - return false; \ - \ - *result = iter->cursor->key; \ - *index = iter->index; \ - 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; \ - } \ - } \ - \ - FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *result, size_t *index) \ - { \ - if (iter->start) \ - return false; \ - \ - *result = iter->cursor->key; \ - *index = iter->index; \ - 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; \ - } \ +#define TREESET_GENERATE_SOURCE(PFX, SNAME, FMOD, V) \ + \ + FMOD SNAME##_node *PFX##_new_node(V element); \ + FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element); \ + FMOD unsigned char PFX##_h(SNAME##_node *node); \ + FMOD unsigned char PFX##_hupdate(SNAME##_node *node); \ + FMOD void PFX##_rotate_right(SNAME##_node **Z); \ + FMOD void PFX##_rotate_left(SNAME##_node **Z); \ + FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node); \ + \ + FMOD SNAME *PFX##_new(int (*compare)(V, V)) \ + { \ + SNAME *_set_ = malloc(sizeof(SNAME)); \ + \ + if (!_set_) \ + return NULL; \ + \ + _set_->count = 0; \ + _set_->root = NULL; \ + _set_->cmp = compare; \ + \ + return _set_; \ + } \ + \ + FMOD void PFX##_free(SNAME *_set_) \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *up = NULL; \ + \ + while (scan != NULL) \ + { \ + if (scan->left != NULL) \ + { \ + SNAME##_node *left = scan->left; \ + \ + scan->left = up; \ + up = scan; \ + scan = left; \ + } \ + else if (scan->right != NULL) \ + { \ + SNAME##_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; \ + } \ + } \ + } \ + } \ + \ + free(_set_); \ + } \ + \ + FMOD bool PFX##_insert(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + { \ + _set_->root = PFX##_new_node(element); \ + if (!_set_->root) \ + return false; \ + } \ + else \ + { \ + SNAME##_node *scan = _set_->root; \ + SNAME##_node *parent = scan; \ + \ + while (scan != NULL) \ + { \ + parent = scan; \ + \ + if (_set_->cmp(scan->key, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->key, element) < 0) \ + scan = scan->right; \ + else \ + return false; \ + } \ + \ + SNAME##_node *node; \ + \ + if (_set_->cmp(parent->key, element) > 0) \ + { \ + parent->left = PFX##_new_node(element); \ + \ + if (!parent->left) \ + return false; \ + \ + parent->left->parent = parent; \ + node = parent->left; \ + } \ + else \ + { \ + parent->right = PFX##_new_node(element); \ + \ + if (!parent->right) \ + return false; \ + \ + parent->right->parent = parent; \ + node = parent->right; \ + } \ + \ + PFX##_rebalance(_set_, node); \ + } \ + \ + _set_->count++; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_remove(SNAME *_set_, V element) \ + { \ + SNAME##_node *node = PFX##_get_node(_set_, element); \ + \ + if (!node) \ + return false; \ + \ + SNAME##_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; \ + \ + V temp_key = temp->key; \ + \ + 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; \ + } \ + \ + if (unbalanced != NULL) \ + PFX##_rebalance(_set_, unbalanced); \ + \ + _set_->count--; \ + \ + return true; \ + } \ + \ + FMOD bool PFX##_insert_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_insert(_set_, element); \ + \ + return false; \ + } \ + \ + FMOD bool PFX##_remove_if(SNAME *_set_, V element, bool condition) \ + { \ + if (condition) \ + return PFX##_remove(_set_, element); \ + \ + return false; \ + } \ + \ + FMOD V PFX##_max(SNAME *_set_) \ + { \ + if (PFX##_empty(_set_)) \ + return 0; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan->right != NULL) \ + scan = scan->right; \ + \ + return scan->key; \ + } \ + \ + FMOD V PFX##_min(SNAME *_set_) \ + { \ + if (PFX##_empty(_set_)) \ + return 0; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan->left != NULL) \ + scan = scan->left; \ + \ + return scan->key; \ + } \ + \ + FMOD bool PFX##_empty(SNAME *_set_) \ + { \ + return _set_->count == 0; \ + } \ + \ + FMOD size_t PFX##_count(SNAME *_set_) \ + { \ + return _set_->count; \ + } \ + \ + FMOD SNAME##_node *PFX##_new_node(V element) \ + { \ + SNAME##_node *node = malloc(sizeof(SNAME##_node)); \ + \ + if (!node) \ + return NULL; \ + \ + node->key = element; \ + node->right = NULL; \ + node->left = NULL; \ + node->parent = NULL; \ + node->height = 0; \ + \ + return node; \ + } \ + \ + FMOD SNAME##_node *PFX##_get_node(SNAME *_set_, V element) \ + { \ + if (PFX##_empty(_set_)) \ + return NULL; \ + \ + SNAME##_node *scan = _set_->root; \ + \ + while (scan != NULL) \ + { \ + if (_set_->cmp(scan->key, element) > 0) \ + scan = scan->left; \ + else if (_set_->cmp(scan->key, element) < 0) \ + scan = scan->right; \ + else \ + return scan; \ + } \ + \ + return NULL; \ + } \ + \ + FMOD unsigned char PFX##_h(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + return node->height; \ + } \ + \ + FMOD unsigned char PFX##_hupdate(SNAME##_node *node) \ + { \ + if (node == NULL) \ + return 0; \ + \ + unsigned char h_l = PFX##_h(node->left); \ + unsigned char h_r = PFX##_h(node->right); \ + \ + return 1 + (h_l > h_r ? h_l : h_r); \ + } \ + \ + FMOD void PFX##_rotate_right(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_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 = PFX##_hupdate(root); \ + new_root->height = PFX##_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + FMOD void PFX##_rotate_left(SNAME##_node **Z) \ + { \ + SNAME##_node *root = *Z; \ + SNAME##_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 = PFX##_hupdate(root); \ + new_root->height = PFX##_hupdate(new_root); \ + \ + *Z = new_root; \ + } \ + \ + FMOD void PFX##_rebalance(SNAME *_set_, SNAME##_node *node) \ + { \ + SNAME##_node *scan = node, *child = NULL; \ + \ + int balance; \ + bool is_root = false; \ + \ + while (scan != NULL) \ + { \ + if (scan->parent == NULL) \ + is_root = true; \ + \ + scan->height = PFX##_hupdate(scan); \ + balance = PFX##_h(scan->right) - PFX##_h(scan->left); \ + \ + if (balance >= 2) \ + { \ + child = scan->right; \ + \ + if (PFX##_h(child->right) < PFX##_h(child->left)) \ + PFX##_rotate_right(&(scan->right)); \ + \ + PFX##_rotate_left(&scan); \ + } \ + else if (balance <= -2) \ + { \ + child = scan->left; \ + \ + if (PFX##_h(child->left) < PFX##_h(child->right)) \ + PFX##_rotate_left(&(scan->left)); \ + \ + PFX##_rotate_right(&scan); \ + } \ + \ + if (is_root) \ + { \ + _set_->root = scan; \ + is_root = false; \ + } \ + \ + scan = scan->parent; \ + } \ + } \ + \ + FMOD SNAME *PFX##_union(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + size_t index; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter1, _set1_); \ + PFX##_iter_new(&iter2, _set2_); \ + \ + for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + { \ + PFX##_iter_next(&iter1, &value, &index); \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + { \ + PFX##_iter_next(&iter2, &value, &index); \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_intersection(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter; \ + size_t index; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + SNAME *_set_A_ = _set1_->count < _set2_->count ? _set1_ : _set2_; \ + SNAME *_set_B_ = _set_A_ == _set1_ ? _set2_ : _set1_; \ + \ + PFX##_iter_new(&iter, _set_A_); \ + \ + for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &value, &index); \ + if (PFX##_get_node(_set_B_, value) != NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter; \ + size_t index; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter, _set1_); \ + \ + for (PFX##_iter_tostart(&iter); !PFX##_iter_end(&iter);) \ + { \ + PFX##_iter_next(&iter, &value, &index); \ + if (PFX##_get_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD SNAME *PFX##_symmetric_difference(SNAME *_set1_, SNAME *_set2_) \ + { \ + SNAME##_iter iter1, iter2; \ + size_t index; \ + V value; \ + \ + SNAME *_set_r_ = PFX##_new(_set1_->cmp); \ + \ + if (!_set_r_) \ + return false; \ + \ + PFX##_iter_new(&iter1, _set1_); \ + PFX##_iter_new(&iter2, _set2_); \ + \ + for (PFX##_iter_tostart(&iter1); !PFX##_iter_end(&iter1);) \ + { \ + PFX##_iter_next(&iter1, &value, &index); \ + if (PFX##_get_node(_set2_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + for (PFX##_iter_tostart(&iter2); !PFX##_iter_end(&iter2);) \ + { \ + PFX##_iter_next(&iter2, &value, &index); \ + if (PFX##_get_node(_set1_, value) == NULL) \ + PFX##_insert(_set_r_, value); \ + } \ + \ + return _set_r_; \ + } \ + \ + FMOD void PFX##_iter_new(SNAME##_iter *iter, SNAME *target) \ + { \ + iter->target = target; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_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; \ + } \ + \ + FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ + { \ + return iter->start && iter->cursor == iter->first; \ + } \ + \ + FMOD bool PFX##_iter_end(SNAME##_iter *iter) \ + { \ + return iter->end && iter->cursor == iter->last; \ + } \ + \ + FMOD void PFX##_iter_tostart(SNAME##_iter *iter) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor = iter->first; \ + } \ + \ + FMOD void PFX##_iter_toend(SNAME##_iter *iter) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + \ + iter->cursor = iter->last; \ + } \ + \ + FMOD bool PFX##_iter_next(SNAME##_iter *iter, V *value, size_t *index) \ + { \ + if (iter->end) \ + return false; \ + \ + *value = iter->cursor->key; \ + *index = iter->index; \ + 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; \ + } \ + } \ + \ + FMOD bool PFX##_iter_prev(SNAME##_iter *iter, V *value, size_t *index) \ + { \ + if (iter->start) \ + return false; \ + \ + *value = iter->cursor->key; \ + *index = iter->index; \ + 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; \ + } \ } #endif /* CMC_TREESET_H */ diff --git a/tests/foreach.c b/tests/foreach.c index 428cd22..8e53cb4 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -2,7 +2,7 @@ #include #include "../src/macro_collections.h" -int cmp(int a, int b) +int intcmp(int a, int b) { return a - b; } @@ -28,6 +28,7 @@ COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /**/, /**/, int) COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /**/, /**/, int) COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /**/, int, int) COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /**/, /**/, int) +COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) int main(int argc, char const *argv[]) { @@ -36,10 +37,11 @@ int main(int argc, char const *argv[]) queue *q = q_new(1000); deque *d = d_new(1000); linked *ll = ll_new(); - heap *h = h_new(1000, MaxHeap, cmp); - tset *ts = ts_new(cmp); - tmap *tm = tm_new(cmp); - hset *hs = hs_new(1000, 0.9, cmp, inthash); + heap *h = h_new(1000, MaxHeap, intcmp); + tset *ts = ts_new(intcmp); + tmap *tm = tm_new(intcmp); + hset *hs = hs_new(1000, 0.9, intcmp, inthash); + hmap *hm = hm_new(1000, 0.9, intcmp, inthash); for (int i = 1; i < 10001; i++) { @@ -62,9 +64,11 @@ int main(int argc, char const *argv[]) ts_insert(ts, i); tm_insert(tm, i, i); hs_insert(hs, i); + hm_insert(hm, i, i); } - int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, sum7 = 0, sum8 = 0, sum9 = 0; + int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, + sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0; FOR_EACH(l, list, int, l, { sum0 += value; @@ -103,6 +107,11 @@ int main(int argc, char const *argv[]) sum9 += value; }) + FOR_EACH_MAP(hm, hmap, int, int, hm, { + sum10 += key; + sum11 += value; + }) + if (sum0 == 50005000) printf("%10s PASSED\n", "LIST"); if (sum1 == 50005000) @@ -121,10 +130,13 @@ int main(int argc, char const *argv[]) printf("%10s PASSED\n", "TREEMAP"); if (sum9 == 50005000) printf("%10s PASSED\n", "HASHSET"); + if (sum10 == 50005000 && sum11 == 50005000) + printf("%10s PASSED\n", "HASHMAP"); printf("\n\n"); - sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, sum7 = 0, sum8 = 0, sum9 = 0; + sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0, + sum7 = 0, sum8 = 0, sum9 = 0, sum10 = 0, sum11 = 0; FOR_EACH_REV(l, list, int, l, { sum0 += value; @@ -163,6 +175,11 @@ int main(int argc, char const *argv[]) sum9 += value; }) + FOR_EACH_MAP_REV(tm, tmap, int, int, tm, { + sum10 += key; + sum11 += value; + }) + if (sum0 == 50005000) printf("%10s PASSED\n", "LIST"); if (sum1 == 50005000) @@ -181,6 +198,8 @@ int main(int argc, char const *argv[]) printf("%10s PASSED\n", "TREEMAP"); if (sum9 == 50005000) printf("%10s PASSED\n", "HASHSET"); + if (sum10 == 50005000 && sum11 == 50005000) + printf("%10s PASSED\n", "HASHMAP"); l_free(l); ll_free(ll); diff --git a/tests/iterators/hashmap.c b/tests/iterators/hashmap.c new file mode 100644 index 0000000..2e187a2 --- /dev/null +++ b/tests/iterators/hashmap.c @@ -0,0 +1,71 @@ +// Checks if the hashmap iterator can go back and forward in the hashmap without +// hitting invalid states or a null pointer. Check is done visually. +#include +#include +#include +#include +#include "../../src/hashmap.h" + +HASHMAP_GENERATE(hm, hmap, static, int, double) + +size_t inthash(int t) +{ + size_t a = t; + a += ~(a << 15); + a ^= (a >> 10); + a += (a << 3); + a ^= (a >> 6); + a += ~(a << 11); + a ^= (a >> 16); + return a; +} + +int intcmp(int a, int b) +{ + return a - b; +} + +int main(int argc, char const *argv[]) +{ + size_t i; + int k; + double v, varr[10] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; + + // Initialize hashmap and add some element + hmap *hm = hm_new(50, 0.9, intcmp, inthash); + for (int i = 0; i < 10; i++) + hm_insert(hm, i, varr[i]); + + // Initialize iterator + hmap_iter iter; + hm_iter_new(&iter, hm); + + // Make the iterator go back and forward + for (int j = 0; j < 4; j++) + { + while (hm_iter_next(&iter, &k, &v, &i)) + printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v); + printf("\n"); + while (hm_iter_prev(&iter, &k, &v, &i)) + printf("S[%2d] = { %2d : %2.2lf }\n", i, k, v); + printf("\n\n"); + } + + for (hm_iter_tostart(&iter); !hm_iter_end(&iter); /**/) + { + hm_iter_next(&iter, &k, &v, &i); + printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v); + } + + printf("\n"); + + for (hm_iter_toend(&iter); !hm_iter_start(&iter); /**/) + { + hm_iter_prev(&iter, &k, &v, &i); + printf("M[%2d] = { %2d : %2.2lf }\n", i, k, v); + } + + hm_free(hm); + + return 0; +}