mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 12:34:47 +00:00
Add unordered_map
This commit is contained in:
@@ -26,7 +26,8 @@
|
||||
#include <errno.h>
|
||||
#include "deque.h"
|
||||
|
||||
const int BLOCK_SIZE = 8;
|
||||
static const int BLOCK_SIZE = 8;
|
||||
static const double RESIZE_RATIO = 1.5;
|
||||
|
||||
struct _deque {
|
||||
size_t data_size;
|
||||
@@ -167,7 +168,7 @@ int deque_push_front(deque me, void *const data)
|
||||
if (inner_index == BLOCK_SIZE - 1) {
|
||||
if (block_index == -1) {
|
||||
const int old_block_count = me->block_count;
|
||||
me->block_count = (int) ceil(1.5 * me->block_count);
|
||||
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count);
|
||||
const int added_blocks = me->block_count - old_block_count;
|
||||
void *temp = realloc(me->block,
|
||||
me->block_count * sizeof(struct node));
|
||||
@@ -214,7 +215,7 @@ int deque_push_back(deque me, void *const data)
|
||||
const int inner_index = me->end_index % BLOCK_SIZE;
|
||||
if (inner_index == 0) {
|
||||
if (block_index == me->block_count) {
|
||||
me->block_count = (int) ceil(1.5 * me->block_count);
|
||||
me->block_count = (int) ceil(RESIZE_RATIO * me->block_count);
|
||||
void *temp = realloc(me->block,
|
||||
me->block_count * sizeof(struct node));
|
||||
if (temp == NULL) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "deque.h"
|
||||
#include "queue.h"
|
||||
|
||||
const int TRIM_SIZE = 64;
|
||||
static const int TRIM_SIZE = 64;
|
||||
|
||||
struct _queue {
|
||||
int trim_count;
|
||||
|
||||
383
src/unordered_map.c
Normal file
383
src/unordered_map.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <errno.h>
|
||||
#include "unordered_map.h"
|
||||
|
||||
static const int STARTING_BUCKETS = 8;
|
||||
static const double RESIZE_AT = 0.75;
|
||||
static const double RESIZE_RATIO = 1.5;
|
||||
|
||||
struct _unordered_map {
|
||||
size_t key_size;
|
||||
size_t value_size;
|
||||
unsigned long (*hash)(const void *const key);
|
||||
int (*comparator)(const void *const one, const void *const two);
|
||||
int size;
|
||||
int capacity;
|
||||
struct node **buckets;
|
||||
};
|
||||
|
||||
struct node {
|
||||
void *key;
|
||||
void *value;
|
||||
unsigned long hash;
|
||||
struct node *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes an unordered map, which is a collection of key-value pairs,
|
||||
* hashed by keys, keys are unique
|
||||
*
|
||||
* @param data_size The size of each element in the unordered map.
|
||||
* @param hash The hash function which computes the hash from the key.
|
||||
* @param comparator The comparator function which compares two keys.
|
||||
*
|
||||
* @return The newly-initialized unordered map, or NULL if memory allocation
|
||||
* error.
|
||||
*/
|
||||
unordered_map unordered_map_init(const size_t key_size,
|
||||
const size_t value_size,
|
||||
unsigned long (*hash)(const void *const),
|
||||
int (*comparator)(const void *const,
|
||||
const void *const))
|
||||
{
|
||||
struct _unordered_map *const init = malloc(sizeof(struct _unordered_map));
|
||||
if (init == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
init->key_size = key_size;
|
||||
init->value_size = value_size;
|
||||
init->hash = hash;
|
||||
init->comparator = comparator;
|
||||
init->size = 0;
|
||||
init->capacity = STARTING_BUCKETS;
|
||||
init->buckets = calloc(STARTING_BUCKETS, sizeof(struct node *));
|
||||
if (init->buckets == NULL) {
|
||||
free(init);
|
||||
return NULL;
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the specified node to the map.
|
||||
*/
|
||||
static void unordered_map_add_item(unordered_map me, struct node *const add)
|
||||
{
|
||||
const int index = (int) (add->hash % me->capacity);
|
||||
add->next = NULL;
|
||||
if (me->buckets[index] == NULL) {
|
||||
me->buckets[index] = add;
|
||||
return;
|
||||
}
|
||||
struct node *traverse = me->buckets[index];
|
||||
while (traverse->next != NULL) {
|
||||
traverse = traverse->next;
|
||||
}
|
||||
traverse->next = add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rehashes all the keys in the unordered map. Used when storing references and
|
||||
* changing the keys. This should rarely be used.
|
||||
*
|
||||
* @param me The unordered map to rehash.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int unordered_map_rehash(unordered_map me)
|
||||
{
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
struct node *const backup = traverse->next;
|
||||
traverse->hash = me->hash(traverse->key);
|
||||
unordered_map_add_item(me, traverse);
|
||||
traverse = backup;
|
||||
}
|
||||
}
|
||||
free(old_buckets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the unordered map.
|
||||
*
|
||||
* @param me The unordered map to check.
|
||||
*
|
||||
* @return The size of the unordered map.
|
||||
*/
|
||||
int unordered_map_size(unordered_map me)
|
||||
{
|
||||
return me->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the unordered map is empty.
|
||||
*
|
||||
* @param me The unordered map to check.
|
||||
*
|
||||
* @return If the unordered map is empty.
|
||||
*/
|
||||
bool unordered_map_is_empty(unordered_map me)
|
||||
{
|
||||
return unordered_map_size(me) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increases the size of the map and redistributes the nodes.
|
||||
*/
|
||||
static int unordered_map_resize(unordered_map me)
|
||||
{
|
||||
const int old_capacity = me->capacity;
|
||||
me->capacity *= RESIZE_RATIO;
|
||||
struct node **old_buckets = me->buckets;
|
||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
||||
if (me->buckets == NULL) {
|
||||
me->buckets = old_buckets;
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
struct node *traverse = old_buckets[i];
|
||||
while (traverse != NULL) {
|
||||
struct node *const backup = traverse->next;
|
||||
unordered_map_add_item(me, traverse);
|
||||
traverse = backup;
|
||||
}
|
||||
}
|
||||
free(old_buckets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if an element is equal to the key.
|
||||
*/
|
||||
inline static bool unordered_map_is_equal(unordered_map me,
|
||||
const struct node *const item,
|
||||
const unsigned long hash,
|
||||
const void *const key)
|
||||
{
|
||||
return item->hash == hash && me->comparator(item->key, key) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates an element to add.
|
||||
*/
|
||||
static struct node *const unordered_map_create_element(unordered_map me,
|
||||
const unsigned long hash,
|
||||
const void *const key,
|
||||
const void *const value)
|
||||
{
|
||||
struct node *const init = malloc(sizeof(struct node));
|
||||
if (init == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
init->key = malloc(me->key_size);
|
||||
if (init->key == NULL) {
|
||||
free(init);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(init->key, key, me->key_size);
|
||||
init->value = malloc(me->value_size);
|
||||
if (init->value == NULL) {
|
||||
free(init->key);
|
||||
free(init);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(init->value, value, me->value_size);
|
||||
init->hash = hash;
|
||||
init->next = NULL;
|
||||
return init;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key-value pair to the unordered map if the unordered map does not
|
||||
* already contain it.
|
||||
*
|
||||
* @param me The unordered map to add to.
|
||||
* @param data The element to add.
|
||||
*
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int unordered_map_put(unordered_map me, void *const key, void *const value)
|
||||
{
|
||||
|
||||
const unsigned long hash = me->hash(key);
|
||||
const int index = (int) (hash % me->capacity);
|
||||
if (me->buckets[index] == NULL) {
|
||||
me->buckets[index] = unordered_map_create_element(me, hash, key, value);
|
||||
if (me->buckets[index] == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
struct node *traverse = me->buckets[index];
|
||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||
memcpy(traverse->value, value, me->value_size);
|
||||
return 0;
|
||||
}
|
||||
while (traverse->next != NULL) {
|
||||
traverse = traverse->next;
|
||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||
memcpy(traverse->value, value, me->value_size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
traverse->next = unordered_map_create_element(me, hash, key, value);
|
||||
if (traverse->next == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
me->size++;
|
||||
if (me->size >= RESIZE_AT * me->capacity) {
|
||||
return unordered_map_resize(me);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value associated with a key in the unordered map.
|
||||
*
|
||||
* @param value The value to copy to.
|
||||
* @param me The unordered map to get from.
|
||||
* @param key The key to search for.
|
||||
*/
|
||||
void unordered_map_get(void *const value, unordered_map me, void *const key)
|
||||
{
|
||||
const unsigned long hash = me->hash(key);
|
||||
const int index = (int) (hash % me->capacity);
|
||||
struct node *traverse = me->buckets[index];
|
||||
while (traverse != NULL) {
|
||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||
memcpy(value, traverse->value, me->value_size);
|
||||
return;
|
||||
}
|
||||
traverse = traverse->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the unordered map contains the specified element.
|
||||
*
|
||||
* @param me The unordered map to check for the element.
|
||||
* @param data The element to check.
|
||||
*
|
||||
* @return If the unordered map contained the element.
|
||||
*/
|
||||
bool unordered_map_contains(unordered_map me, void *const key)
|
||||
{
|
||||
const unsigned long hash = me->hash(key);
|
||||
const int index = (int) (hash % me->capacity);
|
||||
const struct node *traverse = me->buckets[index];
|
||||
while (traverse != NULL) {
|
||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||
return true;
|
||||
}
|
||||
traverse = traverse->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element from the unordered map if it contains it.
|
||||
*
|
||||
* @param me The unordered map to remove an element from.
|
||||
* @param data The element to remove.
|
||||
*
|
||||
* @return If the unordered map contained the element.
|
||||
*/
|
||||
bool unordered_map_remove(unordered_map me, void *const key)
|
||||
{
|
||||
const unsigned long hash = me->hash(key);
|
||||
const int index = (int) (hash % me->capacity);
|
||||
if (me->buckets[index] == NULL) {
|
||||
return false;
|
||||
}
|
||||
struct node *traverse = me->buckets[index];
|
||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||
me->buckets[index] = traverse->next;
|
||||
free(traverse->key);
|
||||
free(traverse->value);
|
||||
free(traverse);
|
||||
me->size--;
|
||||
return true;
|
||||
}
|
||||
while (traverse->next != NULL) {
|
||||
if (unordered_map_is_equal(me, traverse->next, hash, key)) {
|
||||
struct node *const backup = traverse->next;
|
||||
traverse->next = traverse->next->next;
|
||||
free(backup->key);
|
||||
free(backup->value);
|
||||
free(backup);
|
||||
me->size--;
|
||||
return true;
|
||||
}
|
||||
traverse = traverse->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the elements from the unordered map.
|
||||
*
|
||||
* @param me The unordered map to clear.
|
||||
*/
|
||||
void unordered_map_clear(unordered_map me)
|
||||
{
|
||||
for (int i = 0; i < me->capacity; i++) {
|
||||
struct node *traverse = me->buckets[i];
|
||||
while (traverse != NULL) {
|
||||
struct node *const backup = traverse;
|
||||
traverse = traverse->next;
|
||||
free(backup->key);
|
||||
free(backup->value);
|
||||
free(backup);
|
||||
}
|
||||
me->buckets[i] = NULL;
|
||||
}
|
||||
me->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the unordered map memory.
|
||||
*
|
||||
* @param me The unordered map to free from memory.
|
||||
*
|
||||
* @return NULL
|
||||
*/
|
||||
unordered_map unordered_map_destroy(unordered_map me)
|
||||
{
|
||||
unordered_map_clear(me);
|
||||
free(me->buckets);
|
||||
free(me);
|
||||
return NULL;
|
||||
}
|
||||
52
src/unordered_map.h
Normal file
52
src/unordered_map.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Bailey Thompson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONTAINERS_UNORDERED_MAP_H
|
||||
#define CONTAINERS_UNORDERED_MAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct _unordered_map *unordered_map;
|
||||
|
||||
// Starting
|
||||
unordered_map unordered_map_init(size_t key_size,
|
||||
size_t value_size,
|
||||
unsigned long (*hash)(const void *const key),
|
||||
int (*comparator)(const void *const one,
|
||||
const void *const two));
|
||||
|
||||
// Utility
|
||||
int unordered_map_rehash(unordered_map me);
|
||||
int unordered_map_size(unordered_map me);
|
||||
bool unordered_map_is_empty(unordered_map me);
|
||||
|
||||
// Accessing
|
||||
int unordered_map_put(unordered_map me, void *key, void *value);
|
||||
void unordered_map_get(void *value, unordered_map me, void *key);
|
||||
bool unordered_map_contains(unordered_map me, void *key);
|
||||
bool unordered_map_remove(unordered_map me, void *key);
|
||||
|
||||
// Ending
|
||||
void unordered_map_clear(unordered_map me);
|
||||
unordered_map unordered_map_destroy(unordered_map me);
|
||||
|
||||
#endif /* CONTAINERS_UNORDERED_MAP_H */
|
||||
@@ -25,9 +25,9 @@
|
||||
#include <errno.h>
|
||||
#include "unordered_set.h"
|
||||
|
||||
const int STARTING_BUCKETS = 8;
|
||||
const double RESIZE_AT = 0.75;
|
||||
const double RESIZE_RATIO = 1.5;
|
||||
static const int STARTING_BUCKETS = 8;
|
||||
static const double RESIZE_AT = 0.75;
|
||||
static const double RESIZE_RATIO = 1.5;
|
||||
|
||||
struct _unordered_set {
|
||||
size_t key_size;
|
||||
@@ -217,7 +217,7 @@ static struct node *const unordered_set_create_element(unordered_set me,
|
||||
* @return 0 No error.
|
||||
* -ENOMEM Out of memory.
|
||||
*/
|
||||
int unordered_set_add(unordered_set me, void *const key)
|
||||
int unordered_set_put(unordered_set me, void *const key)
|
||||
{
|
||||
|
||||
const unsigned long hash = me->hash(key);
|
||||
@@ -262,9 +262,6 @@ bool unordered_set_contains(unordered_set me, void *const key)
|
||||
{
|
||||
const unsigned long hash = me->hash(key);
|
||||
const int index = (int) (hash % me->capacity);
|
||||
if (me->buckets[index] == NULL) {
|
||||
return false;
|
||||
}
|
||||
const struct node *traverse = me->buckets[index];
|
||||
while (traverse != NULL) {
|
||||
if (unordered_set_is_equal(me, traverse, hash, key)) {
|
||||
|
||||
@@ -39,7 +39,7 @@ int unordered_set_size(unordered_set me);
|
||||
bool unordered_set_is_empty(unordered_set me);
|
||||
|
||||
// Accessing
|
||||
int unordered_set_add(unordered_set me, void *key);
|
||||
int unordered_set_put(unordered_set me, void *key);
|
||||
bool unordered_set_contains(unordered_set me, void *key);
|
||||
bool unordered_set_remove(unordered_set me, void *key);
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <errno.h>
|
||||
#include "vector.h"
|
||||
|
||||
const int START_SPACE = 8;
|
||||
static const int START_SPACE = 8;
|
||||
static const double RESIZE_RATIO = 1.5;
|
||||
|
||||
struct _vector {
|
||||
size_t data_size;
|
||||
@@ -172,7 +173,7 @@ int vector_add_at(vector me, const int index, void *const data)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (me->offset + 1 >= me->space) {
|
||||
me->space *= 1.5;
|
||||
me->space *= RESIZE_RATIO;
|
||||
void *const temp = realloc(me->storage, me->space * me->data_size);
|
||||
if (temp == NULL) {
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -11,5 +11,6 @@ int main()
|
||||
test_set();
|
||||
test_array();
|
||||
test_unordered_set();
|
||||
test_unordered_map();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,5 +14,6 @@ void test_queue(void);
|
||||
void test_set(void);
|
||||
void test_array(void);
|
||||
void test_unordered_set(void);
|
||||
void test_unordered_map(void);
|
||||
|
||||
#endif /* CONTAINERS_TEST_H */
|
||||
|
||||
135
tst/unordered_map.c
Normal file
135
tst/unordered_map.c
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "test.h"
|
||||
#include "../src/unordered_map.h"
|
||||
|
||||
static int compare_int(const void *const one, const void *const two)
|
||||
{
|
||||
const int a = *(int *) one;
|
||||
const int b = *(int *) two;
|
||||
return a - b;
|
||||
}
|
||||
|
||||
static int hash_count;
|
||||
|
||||
static unsigned long hash_int(const void *const key)
|
||||
{
|
||||
hash_count++;
|
||||
unsigned long hash = 17;
|
||||
hash = 31 * hash + *(int *) key;
|
||||
return hash;
|
||||
}
|
||||
|
||||
void test_unordered_map(void)
|
||||
{
|
||||
unordered_map a = unordered_map_init(sizeof(int),
|
||||
sizeof(int),
|
||||
hash_int,
|
||||
compare_int);
|
||||
assert(unordered_map_size(a) == 0);
|
||||
assert(unordered_map_is_empty(a));
|
||||
int b = 4;
|
||||
int c = 9;
|
||||
unordered_map_put(a, &b, &c);
|
||||
assert(unordered_map_size(a) == 1);
|
||||
c = 5;
|
||||
unordered_map_put(a, &b, &c);
|
||||
assert(unordered_map_size(a) == 1);
|
||||
assert(!unordered_map_is_empty(a));
|
||||
assert(unordered_map_contains(a, &b));
|
||||
c = 0xdeadbeef;
|
||||
unordered_map_get(&c, a, &b);
|
||||
assert(c == 5);
|
||||
b = 7;
|
||||
assert(!unordered_map_contains(a, &b));
|
||||
unordered_map_put(a, &b, &c);
|
||||
assert(unordered_map_size(a) == 2);
|
||||
assert(unordered_map_contains(a, &b));
|
||||
int d[10] = {5, 9, 4, -5, 0, 6, 1, 5, 7, 2};
|
||||
for (int i = 0; i < 10; i++) {
|
||||
unordered_map_put(a, &d[i], &c);
|
||||
assert(unordered_map_contains(a, &d[i]));
|
||||
}
|
||||
assert(unordered_map_size(a) == 9);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assert(unordered_map_contains(a, &d[i]));
|
||||
}
|
||||
for (int i = -100; i < 100; i++) {
|
||||
bool contains = false;
|
||||
for (int j = 0; j < 10; j++) {
|
||||
if (d[j] == i) {
|
||||
contains = true;
|
||||
}
|
||||
}
|
||||
assert(unordered_map_contains(a, &i) == contains);
|
||||
}
|
||||
int num = -3;
|
||||
assert(!unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 9);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 6;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 8);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 4;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 7);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 7;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 6);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 9;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 5);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = -5;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 4);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 0;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 3);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 1;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 2);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 5;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 1);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
num = 2;
|
||||
assert(unordered_map_remove(a, &num));
|
||||
assert(unordered_map_size(a) == 0);
|
||||
assert(!unordered_map_contains(a, &num));
|
||||
// Add a lot of items and remove individually.
|
||||
for (int i = 5000; i < 6000; i++) {
|
||||
unordered_map_put(a, &i, &c);
|
||||
assert(unordered_map_contains(a, &i));
|
||||
}
|
||||
assert(unordered_map_size(a) == 1000);
|
||||
for (int i = 5000; i < 6000; i++) {
|
||||
unordered_map_remove(a, &i);
|
||||
assert(!unordered_map_contains(a, &i));
|
||||
}
|
||||
assert(unordered_map_size(a) == 0);
|
||||
assert(unordered_map_is_empty(a));
|
||||
unordered_map_clear(a);
|
||||
assert(unordered_map_size(a) == 0);
|
||||
assert(unordered_map_is_empty(a));
|
||||
// Add a lot of items and clear.
|
||||
for (int i = 5000; i < 6000; i++) {
|
||||
unordered_map_put(a, &i, &c);
|
||||
assert(unordered_map_contains(a, &i));
|
||||
}
|
||||
assert(unordered_map_size(a) == 1000);
|
||||
hash_count = 0;
|
||||
unordered_map_rehash(a);
|
||||
assert(hash_count == 1000);
|
||||
unordered_map_clear(a);
|
||||
int p = 0xdeadbeef;
|
||||
assert(!unordered_map_remove(a, &p));
|
||||
assert(unordered_map_size(a) == 0);
|
||||
assert(unordered_map_is_empty(a));
|
||||
a = unordered_map_destroy(a);
|
||||
assert(a == NULL);
|
||||
}
|
||||
@@ -24,20 +24,20 @@ void test_unordered_set(void)
|
||||
assert(unordered_set_size(a) == 0);
|
||||
assert(unordered_set_is_empty(a));
|
||||
int b = 4;
|
||||
unordered_set_add(a, &b);
|
||||
unordered_set_put(a, &b);
|
||||
assert(unordered_set_size(a) == 1);
|
||||
unordered_set_add(a, &b);
|
||||
unordered_set_put(a, &b);
|
||||
assert(unordered_set_size(a) == 1);
|
||||
assert(!unordered_set_is_empty(a));
|
||||
assert(unordered_set_contains(a, &b));
|
||||
b = 7;
|
||||
assert(!unordered_set_contains(a, &b));
|
||||
unordered_set_add(a, &b);
|
||||
unordered_set_put(a, &b);
|
||||
assert(unordered_set_size(a) == 2);
|
||||
assert(unordered_set_contains(a, &b));
|
||||
int c[10] = {5, 9, 4, -5, 0, 6, 1, 5, 7, 2};
|
||||
for (int i = 0; i < 10; i++) {
|
||||
unordered_set_add(a, &c[i]);
|
||||
unordered_set_put(a, &c[i]);
|
||||
assert(unordered_set_contains(a, &c[i]));
|
||||
}
|
||||
assert(unordered_set_size(a) == 9);
|
||||
@@ -95,7 +95,7 @@ void test_unordered_set(void)
|
||||
assert(!unordered_set_contains(a, &num));
|
||||
// Add a lot of items and remove individually.
|
||||
for (int i = 5000; i < 6000; i++) {
|
||||
unordered_set_add(a, &i);
|
||||
unordered_set_put(a, &i);
|
||||
assert(unordered_set_contains(a, &i));
|
||||
}
|
||||
assert(unordered_set_size(a) == 1000);
|
||||
@@ -110,7 +110,7 @@ void test_unordered_set(void)
|
||||
assert(unordered_set_is_empty(a));
|
||||
// Add a lot of items and clear.
|
||||
for (int i = 5000; i < 6000; i++) {
|
||||
unordered_set_add(a, &i);
|
||||
unordered_set_put(a, &i);
|
||||
assert(unordered_set_contains(a, &i));
|
||||
}
|
||||
assert(unordered_set_size(a) == 1000);
|
||||
|
||||
Reference in New Issue
Block a user