├── doc_en.odt ├── doc_en.pdf ├── tests.png ├── README.md ├── linkedlist.h ├── bst.h ├── Makefile ├── linkedlist.c ├── alsmap.h ├── bst.c ├── main.c ├── main.cpp ├── rbt.c └── alsmap.c /doc_en.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseAaronLopezGarcia/ALSHashMap/HEAD/doc_en.odt -------------------------------------------------------------------------------- /doc_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseAaronLopezGarcia/ALSHashMap/HEAD/doc_en.pdf -------------------------------------------------------------------------------- /tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseAaronLopezGarcia/ALSHashMap/HEAD/tests.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ALSHashMap 2 | HashTable implementation that uses a hybrid algorithm to achieve constant time and memory usage. 3 | DEPRECATED IN FAVOR OF THE MUCH FASTER AND SIMPLER FreeListHashMap: https://github.com/JoseAaronLopezGarcia/FreeListHashMap 4 | -------------------------------------------------------------------------------- /linkedlist.h: -------------------------------------------------------------------------------- 1 | #ifndef LINKEDLIST_H 2 | #define LINKEDLIST_H 3 | 4 | #ifdef __cplusplus 5 | extern "C"{ 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | typedef struct ListNode{ 12 | size_t key; 13 | void* value; 14 | struct ListNode* next; 15 | }ListNode; 16 | 17 | typedef struct LinkedList{ 18 | ListNode* start; 19 | size_t size; 20 | }LinkedList; 21 | 22 | LinkedList* LinkedList_New(); 23 | void LinkedList_Set(LinkedList*, size_t key, void* value); 24 | void* LinkedList_Get(LinkedList*, size_t key); 25 | void* LinkedList_Del(LinkedList*, size_t key); 26 | size_t LinkedList_Size(LinkedList*); 27 | void LinkedList_Destroy(LinkedList*); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /bst.h: -------------------------------------------------------------------------------- 1 | #ifndef BST_H 2 | #define BST_H 3 | 4 | #ifdef __cplusplus 5 | extern "C"{ 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | typedef struct TreeNode{ 12 | size_t key; 13 | void* value; 14 | struct TreeNode* parent; 15 | struct TreeNode* children[2]; 16 | #ifdef USE_RED_BLACK 17 | int color; 18 | #endif 19 | }TreeNode; 20 | 21 | typedef struct BinaryTree{ 22 | TreeNode* root; 23 | size_t size; 24 | }BinaryTree; 25 | 26 | BinaryTree* BinaryTree_New(); 27 | void BinaryTree_Set(BinaryTree*, size_t key, void* value); 28 | void* BinaryTree_Get(BinaryTree*, size_t key); 29 | void* BinaryTree_Del(BinaryTree*, size_t key); 30 | size_t BinaryTree_Size(BinaryTree*); 31 | void BinaryTree_Destroy(BinaryTree*); 32 | void BinaryTree_Print(BinaryTree*); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | TARGET = main 3 | SRC = main.c alsmap.c bst.c linkedlist.c 4 | FLAGS = -Wall 5 | LIBS = -lrt 6 | 7 | CPP = g++ 8 | CPP_TARGET = cppmain 9 | CPP_SRC = main.cpp 10 | CPP_FLAGS = -Wall -std=c++11 11 | CPP_LIBS = -lrt -lstdc++ 12 | 13 | all: 14 | $(CC) $(FLAGS) -o $(TARGET) $(SRC) $(LIBS) 15 | 16 | bst: 17 | $(CC) $(FLAGS) -DUSE_TREE -o $(TARGET) $(SRC) $(LIBS) 18 | 19 | rbt: 20 | $(CC) $(FLAGS) -DUSE_TREE -DUSE_RED_BLACK -o $(TARGET) $(SRC) $(LIBS) 21 | 22 | cpp: 23 | $(CPP) $(CPP_FLAGS) -o $(CPP_TARGET) $(CPP_SRC) $(CPP_LIBS) 24 | 25 | eprobe: 26 | $(CC) $(FLAGS) -DEXTENDED_PROBING -o $(TARGET) $(SRC) $(LIBS) 27 | 28 | ebst: 29 | $(CC) $(FLAGS) -DUSE_TREE -DEXTENDED_PROBING -o $(TARGET) $(SRC) $(LIBS) 30 | 31 | erbt: 32 | $(CC) $(FLAGS) -DUSE_TREE -DUSE_RED_BLACK -DEXTENDED_PROBING -o $(TARGET) $(SRC) $(LIBS) 33 | 34 | clean: 35 | rm $(TARGET) $(CPP_TARGET) 36 | 37 | -------------------------------------------------------------------------------- /linkedlist.c: -------------------------------------------------------------------------------- 1 | #include "linkedlist.h" 2 | 3 | static int findNode(LinkedList* self, size_t key, ListNode** node, ListNode** prev){ 4 | *node = *prev = NULL; 5 | if (self != NULL){ 6 | ListNode* p = NULL; 7 | ListNode* n = self->start; 8 | while (n != NULL){ 9 | if (n->key == key){ 10 | *node = n; 11 | *prev = p; 12 | return 1; 13 | } 14 | p = n; 15 | n = n->next; 16 | } 17 | } 18 | return 0; 19 | } 20 | 21 | LinkedList* LinkedList_New(){ 22 | LinkedList* self = (LinkedList*)malloc(sizeof(LinkedList)); 23 | self->start = NULL; 24 | self->size = 0; 25 | return self; 26 | } 27 | 28 | void LinkedList_Set(LinkedList* self, size_t key, void* value){ 29 | if (self != NULL && value != NULL){ 30 | ListNode *prev, *node; 31 | if (findNode(self, key, &node, &prev)){ 32 | node->value = value; 33 | } 34 | else{ 35 | ListNode* node = (ListNode*)malloc(sizeof(ListNode)); 36 | node->key = key; 37 | node->value = value; 38 | node->next = self->start; 39 | self->start = node; 40 | self->size++; 41 | } 42 | } 43 | } 44 | 45 | void* LinkedList_Get(LinkedList* self, size_t key){ 46 | ListNode *prev, *node; 47 | if (findNode(self, key, &node, &prev)) 48 | return node->value; 49 | return NULL; 50 | 51 | } 52 | 53 | void* LinkedList_Del(LinkedList* self, size_t key){ 54 | ListNode *node, *prev; 55 | void* value = NULL; 56 | if (findNode(self, key, &node, &prev)){ 57 | if (prev==NULL) self->start = node->next; 58 | else prev->next = node->next; 59 | value = node->value; 60 | free(node); 61 | self->size--; 62 | } 63 | return value; 64 | } 65 | 66 | size_t LinkedList_Size(LinkedList* self){ 67 | return self->size; 68 | } 69 | 70 | void LinkedList_Destroy(LinkedList* self){ 71 | ListNode* node = self->start; 72 | while (node != NULL){ 73 | ListNode* aux = node; 74 | node = node->next; 75 | free(aux); 76 | } 77 | free(self); 78 | } 79 | -------------------------------------------------------------------------------- /alsmap.h: -------------------------------------------------------------------------------- 1 | #ifndef ALS_HASHMAP 2 | #define ALS_HASHMAP 3 | 4 | 5 | /* CONFIG OPTIONS */ 6 | 7 | /* use binary search tree */ 8 | //#define USE_TREE 9 | 10 | /* use extended probing */ 11 | //#define EXTENDED_PROBING 12 | 13 | /* use unified auxiliary structure */ 14 | //#define UNIQUE_AUX 15 | 16 | /* use prime table sizes */ 17 | //#define USE_PRIMES 18 | 19 | #ifdef __cplusplus 20 | extern "C"{ 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef USE_TREE 28 | #include "bst.h" 29 | #else 30 | #include "linkedlist.h" 31 | #endif 32 | 33 | typedef enum{ 34 | E, // empty 35 | L, // contains item belonging here 36 | B, // contains item not belonging here 37 | A // contains data structure 38 | }ALSBucketType; 39 | 40 | typedef struct ALSNode{ 41 | ALSBucketType type; // node type 42 | union{ 43 | // pair 44 | struct{ 45 | size_t key; 46 | void* value; 47 | } pair; 48 | // auxiliary data structure 49 | #ifdef UNIQUE_AUX 50 | size_t NA; 51 | #else 52 | #ifdef USE_TREE 53 | BinaryTree* col; 54 | #else 55 | LinkedList* col; 56 | #endif 57 | #endif 58 | 59 | } bucket; 60 | }ALSNode; 61 | 62 | typedef struct ALSHashMap{ 63 | ALSNode* table; 64 | #ifdef UNIQUE_AUX 65 | #ifdef USE_TREE 66 | BinaryTree* col; 67 | #else 68 | LinkedList* col; 69 | #endif 70 | #endif 71 | size_t T; // table size 72 | size_t N; // number of elements 73 | size_t R; // probe range 74 | // stats 75 | size_t CRC; // counter of nodes that can be reallocated 76 | size_t NA; // number of auxiliary nodes 77 | size_t NE; // number of empty nodes 78 | size_t MA; // maximum number of items in auxiliary data structures 79 | }ALSHashMap; 80 | 81 | // create a new (empty) table 82 | ALSHashMap* ALSHashMap_New(); 83 | 84 | // add or update an element 85 | void ALSHashMap_Set(ALSHashMap*, size_t key, void* value); 86 | 87 | // obtain an element 88 | void* ALSHashMap_Get(ALSHashMap*, size_t key); 89 | 90 | // delete an element 91 | void* ALSHashMap_Del(ALSHashMap*, size_t key); 92 | 93 | // get number of elements 94 | size_t ALSHashMap_Size(ALSHashMap*); 95 | 96 | // destroy a table (free all memory) 97 | void ALSHashMap_Destroy(ALSHashMap*); 98 | 99 | void ALSHashMap_PrintStats(ALSHashMap*); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /bst.c: -------------------------------------------------------------------------------- 1 | #include "bst.h" 2 | 3 | #ifdef USE_RED_BLACK 4 | #include "rbt.c" 5 | #endif 6 | 7 | BinaryTree* BinaryTree_New(){ 8 | BinaryTree* self = (BinaryTree*)malloc(sizeof(BinaryTree)); 9 | self->root = NULL; 10 | self->size = 0; 11 | return self; 12 | } 13 | 14 | TreeNode* _BinaryTree_Set(BinaryTree* self, size_t key, void* value){ 15 | TreeNode* tnode = self->root; 16 | if (tnode==NULL){ 17 | self->size++; 18 | tnode = (TreeNode*)malloc(sizeof(TreeNode)); 19 | tnode->key = key; 20 | tnode->value = value; 21 | tnode->children[0] = tnode->children[1] = NULL; 22 | tnode->parent = NULL; 23 | #ifdef USE_RED_BLACK 24 | tnode->color = BLACK; 25 | #endif 26 | self->root = tnode; 27 | return tnode; 28 | } 29 | else{ 30 | for (;;){ 31 | if (tnode->key == key){ 32 | tnode->value = value; 33 | break; 34 | } 35 | else{ 36 | int c = tnode->key < key? 1:0; 37 | if (tnode->children[c] == NULL){ 38 | self->size++; 39 | TreeNode* child = (TreeNode*)malloc(sizeof(TreeNode)); 40 | tnode->children[c] = child; 41 | child->parent = tnode; 42 | child->key = key; 43 | child->value = value; 44 | child->children[0] = NULL; 45 | child->children[1] = NULL; 46 | #ifdef USE_RED_BLACK 47 | child->color = RED; 48 | #endif 49 | return child; 50 | 51 | } 52 | else tnode = tnode->children[c]; 53 | } 54 | } 55 | } 56 | return NULL; 57 | } 58 | 59 | void BinaryTree_Set(BinaryTree* self, size_t key, void* value){ 60 | TreeNode* inserted = _BinaryTree_Set(self, key, value); 61 | #ifdef USE_RED_BLACK 62 | if (inserted!=NULL) _RedBlackTree_onSetBalance(self, inserted); 63 | #endif 64 | } 65 | 66 | void* BinaryTree_Get(BinaryTree* self, size_t key){ 67 | TreeNode* tnode = self->root; 68 | while (tnode != NULL){ 69 | if (tnode->key == key){return tnode->value;} 70 | else{ 71 | int child = tnode->key < key? 1:0; 72 | tnode = tnode->children[child]; 73 | } 74 | } 75 | return NULL; 76 | } 77 | 78 | void* BinaryTree_Del(BinaryTree* self, size_t key){ 79 | TreeNode* tnode = self->root; 80 | int pchild; 81 | while (tnode != NULL){ 82 | if (tnode->key == key){ 83 | void* ret = tnode->value; 84 | TreeNode* aux = tnode; 85 | TreeNode* child = NULL; 86 | if (tnode->children[0] == NULL || tnode->children[1] == NULL){ // at most one child 87 | if ((child=tnode->children[0])==NULL) child = tnode->children[1]; 88 | if (child != NULL) child->parent = tnode->parent; 89 | if (tnode->parent != NULL){ // is not root 90 | int c = (tnode->key>tnode->parent->key)? 1:0; 91 | tnode->parent->children[c] = child; 92 | } 93 | else self->root = child; 94 | } 95 | else{ // two children 96 | aux = tnode->children[1]; 97 | while (aux->children[0] != NULL){ 98 | aux = aux->children[0]; 99 | } 100 | child = aux->children[1]; 101 | tnode->value = aux->value; 102 | tnode->key = aux->key; 103 | if (aux->parent != tnode){ 104 | aux->parent->children[0] = child; 105 | if (child!=NULL) child->parent = aux->parent; 106 | } 107 | else{ 108 | tnode->children[1] = child; 109 | if (child!=NULL) child->parent = tnode; 110 | } 111 | } 112 | self->size--; 113 | #ifdef USE_RED_BLACK 114 | if (aux->color == BLACK){ 115 | _RedBlackTree_onDelBalance(self, child); 116 | } 117 | #endif 118 | free(aux); 119 | return ret; 120 | } 121 | else{ 122 | pchild = tnode->key < key? 1:0; 123 | tnode = tnode->children[pchild]; 124 | } 125 | } 126 | return NULL; 127 | } 128 | 129 | size_t BinaryTree_Size(BinaryTree* self){ 130 | return self->size; 131 | } 132 | 133 | static void BinaryTree_DestroyNode(TreeNode* tnode){ 134 | if (tnode != NULL){ 135 | BinaryTree_DestroyNode(tnode->children[0]); 136 | BinaryTree_DestroyNode(tnode->children[1]); 137 | free(tnode); 138 | } 139 | } 140 | 141 | void BinaryTree_Destroy(BinaryTree* self){ 142 | BinaryTree_DestroyNode(self->root); 143 | free(self); 144 | } 145 | 146 | static void printTnode(TreeNode* tnode){ 147 | if (tnode == NULL) printf("(nil)"); 148 | else{ 149 | printf("("); 150 | #ifdef USE_RED_BLACK 151 | printf("%c: ", (tnode->color == RED)? 'R':'B'); 152 | #endif 153 | printf("<%zu,%p>, ", tnode->key, tnode->value); 154 | printTnode(tnode->children[0]); 155 | printf(", "); 156 | printTnode(tnode->children[1]); 157 | printf(")"); 158 | } 159 | } 160 | 161 | void BinaryTree_Print(BinaryTree* self){ 162 | printTnode(self->root); 163 | } 164 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "alsmap.h" 7 | 8 | #define MAX_ITEMS 500000 9 | 10 | typedef struct{ 11 | size_t key; 12 | void* value; 13 | }Pair; 14 | 15 | void randTest(){ 16 | srand(19); 17 | 18 | Pair items[MAX_ITEMS]; 19 | int i; 20 | ALSHashMap* map = ALSHashMap_New(); 21 | printf("Inserting\n"); 22 | for (i=0; i -> <%zu, %p>\n", 37 | items[index].key, items[index].value, items[index].key, val); 38 | } 39 | items[index].value = NULL; 40 | } 41 | printf("Searching\n"); 42 | for (i=0; i != <%zu, %p>\n", 47 | items[i].key, items[i].value, items[i].key, val); 48 | } 49 | } 50 | 51 | //ALSHashMap_PrintStats(map); 52 | ALSHashMap_Destroy(map); 53 | } 54 | 55 | void stringTest(){ 56 | static Pair tests[] = { 57 | {285909807262152150, "__add__"}, 58 | {-7432373563400207827, "__class__"}, 59 | {-3864244867600433497, "__contains__"}, 60 | {-21206928619717391, "__delattr__"}, 61 | {-8518757509529533123, "__doc__"}, 62 | {2177041475305762140, "__eq__"}, 63 | {8362317231626074027, "__format__"}, 64 | {177011475287762302, "__ge__"}, 65 | {-4016074044355204212, "__getattribute__"}, 66 | {-2585418108064572858, "__getitem__"}, 67 | {7834477386492485275, "__getnewargs__"}, 68 | {4753113843515500806, "__getslice__"}, 69 | {177028475415762519, "__gt__"}, 70 | {5317119094262461816, "__hash__"}, 71 | {243017754987892126, "__init__"}, 72 | {9177214476136763251, "__le__"}, 73 | {5277902763571881278, "__len__"}, 74 | {9177197476008762906, "__lt__"}, 75 | {7048710602605022567, "__mod__"}, 76 | {-5397995471050529035, "__mul__"}, 77 | {7177204476118763201, "__ne__"}, 78 | {3717045426703639461, "__new__"}, 79 | {8370432368919977356, "__reduce__"}, 80 | {-8813356612065597533, "__reduce_ex__"}, 81 | {7914004857907398901, "__repr__"}, 82 | {8224150437717880858, "__rmod__"}, 83 | {4670584510141430808, "__rmul__"}, 84 | {1862642071337639586, "__setattr__"}, 85 | {7819592757661739418, "__sizeof__"}, 86 | {3406273213427680266, "__str__"}, 87 | {4590790060814328915, "__subclasshook__"}, 88 | {2870999192938818550, "_formatter_field_name_split"}, 89 | {-1544660614358752326, "_formatter_parser"}, 90 | {1399668705107177948, "capitalize"}, 91 | {-1095339294798586395, "center"}, 92 | {7943899258573201248, "count"}, 93 | {2194059052396695344, "decode"}, 94 | {4408087139288664376, "encode"}, 95 | {7717545679810809234, "endswith"}, 96 | {-2162370607129298578, "expandtabs"}, 97 | {-509531383349783523, "find"}, 98 | {2880483376040711751, "format"}, 99 | {-8139544016919160671, "index"}, 100 | {-1891891588800347354, "isalnum"}, 101 | {-1891913589055347917, "isalpha"}, 102 | {-1094508681242454120, "isdigit"}, 103 | {6662203971650579192, "islower"}, 104 | {-3264133018777589699, "isspace"}, 105 | {4865563698166163645, "istitle"}, 106 | {6296712317920652027, "isupper"}, 107 | {-2338040935105240732, "join"}, 108 | {756173091232232219, "ljust"}, 109 | {-2243981909596768798, "lower"}, 110 | {5246082140489123976, "lstrip"}, 111 | {1893173574489465835, "partition"}, 112 | {-475611394924150513, "replace"}, 113 | {8566273963665974510, "rfind"}, 114 | {-295205302757070552, "rindex"}, 115 | {2119545889811422497, "rjust"}, 116 | {-7632506038852954866, "rpartition"}, 117 | {-7478859825809313188, "rsplit"}, 118 | {6967846247828238390, "rstrip"}, 119 | {-1666158750398020171, "split"}, 120 | {6545242454319875859, "splitlines"}, 121 | {-9054588884789670847, "startswith"}, 122 | {2334087250953981719, "strip"}, 123 | {-5944333514074386483, "swapcase"}, 124 | {-9092798511318848473, "title"}, 125 | {-4075548806044035269, "translate"}, 126 | {121890850537711745, "upper"}, 127 | {7057264582011549012, "zfill"}, 128 | }; 129 | int i; 130 | ALSHashMap* map = ALSHashMap_New(); 131 | printf("Inserting\n"); 132 | for (i=0; i != <%zu, %p>\n", 143 | tests[i].key, tests[i].value, tests[i].key, val); 144 | } 145 | } 146 | printf("Deleting\n"); 147 | for (i=0; i -> <%zu, %p>\n", 151 | tests[i].key, tests[i].value, tests[i].key, val); 152 | } 153 | tests[i].value = NULL; 154 | } 155 | 156 | ALSHashMap_Destroy(map); 157 | } 158 | 159 | int main(int argc, char** argv){ 160 | //stringTest(); 161 | randTest(); 162 | return 0; 163 | } 164 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_ITEMS 200000 7 | 8 | typedef struct{ 9 | size_t key; 10 | void* value; 11 | }Pair; 12 | 13 | void printStats(std::unordered_map &map){ 14 | printf("T: %zu\n", map.bucket_count()); 15 | printf("N: %zu\n", map.size()); 16 | printf("Load Factor: %f\n", map.load_factor()); 17 | } 18 | 19 | void randTest(){ 20 | srand(19); 21 | 22 | Pair items[MAX_ITEMS]; 23 | int i; 24 | std::unordered_map map; 25 | 26 | for (i=0; i != <%zu, %p>\n", 45 | items[i].key, items[i].value, items[i].key, val); 46 | } 47 | } 48 | } 49 | 50 | void stringTest(){ 51 | static Pair tests[] = { 52 | {(size_t)285909807262152150, (void*)"__add__"}, 53 | {(size_t)-7432373563400207827, (void*)"__class__"}, 54 | {(size_t)-3864244867600433497, (void*)"__contains__"}, 55 | {(size_t)-21206928619717391, (void*)"__delattr__"}, 56 | {(size_t)-8518757509529533123, (void*)"__doc__"}, 57 | {(size_t)2177041475305762140, (void*)"__eq__"}, 58 | {(size_t)8362317231626074027, (void*)"__format__"}, 59 | {(size_t)177011475287762302, (void*)"__ge__"}, 60 | {(size_t)-4016074044355204212, (void*)"__getattribute__"}, 61 | {(size_t)-2585418108064572858, (void*)"__getitem__"}, 62 | {(size_t)7834477386492485275, (void*)"__getnewargs__"}, 63 | {(size_t)4753113843515500806, (void*)"__getslice__"}, 64 | {(size_t)177028475415762519, (void*)"__gt__"}, 65 | {(size_t)5317119094262461816, (void*)"__hash__"}, 66 | {(size_t)243017754987892126, (void*)"__init__"}, 67 | {(size_t)9177214476136763251, (void*)"__le__"}, 68 | {(size_t)5277902763571881278, (void*)"__len__"}, 69 | {(size_t)9177197476008762906, (void*)"__lt__"}, 70 | {(size_t)7048710602605022567, (void*)"__mod__"}, 71 | {(size_t)-5397995471050529035, (void*)"__mul__"}, 72 | {(size_t)7177204476118763201, (void*)"__ne__"}, 73 | {(size_t)3717045426703639461, (void*)"__new__"}, 74 | {(size_t)8370432368919977356, (void*)"__reduce__"}, 75 | {(size_t)-8813356612065597533, (void*)"__reduce_ex__"}, 76 | {(size_t)7914004857907398901, (void*)"__repr__"}, 77 | {(size_t)8224150437717880858, (void*)"__rmod__"}, 78 | {(size_t)4670584510141430808, (void*)"__rmul__"}, 79 | {(size_t)1862642071337639586, (void*)"__setattr__"}, 80 | {(size_t)7819592757661739418, (void*)"__sizeof__"}, 81 | {(size_t)3406273213427680266, (void*)"__str__"}, 82 | {(size_t)4590790060814328915, (void*)"__subclasshook__"}, 83 | {(size_t)2870999192938818550, (void*)"_formatter_field_name_split"}, 84 | {(size_t)-1544660614358752326, (void*)"_formatter_parser"}, 85 | {(size_t)1399668705107177948, (void*)"capitalize"}, 86 | {(size_t)-1095339294798586395, (void*)"center"}, 87 | {(size_t)7943899258573201248, (void*)"count"}, 88 | {(size_t)2194059052396695344, (void*)"decode"}, 89 | {(size_t)4408087139288664376, (void*)"encode"}, 90 | {(size_t)7717545679810809234, (void*)"endswith"}, 91 | {(size_t)-2162370607129298578, (void*)"expandtabs"}, 92 | {(size_t)-509531383349783523, (void*)"find"}, 93 | {(size_t)2880483376040711751, (void*)"format"}, 94 | {(size_t)-8139544016919160671, (void*)"index"}, 95 | {(size_t)-1891891588800347354, (void*)"isalnum"}, 96 | {(size_t)-1891913589055347917, (void*)"isalpha"}, 97 | {(size_t)-1094508681242454120, (void*)"isdigit"}, 98 | {(size_t)6662203971650579192, (void*)"islower"}, 99 | {(size_t)-3264133018777589699, (void*)"isspace"}, 100 | {(size_t)4865563698166163645, (void*)"istitle"}, 101 | {(size_t)6296712317920652027, (void*)"isupper"}, 102 | {(size_t)-2338040935105240732, (void*)"join"}, 103 | {(size_t)756173091232232219, (void*)"ljust"}, 104 | {(size_t)-2243981909596768798, (void*)"lower"}, 105 | {(size_t)5246082140489123976, (void*)"lstrip"}, 106 | {(size_t)1893173574489465835, (void*)"partition"}, 107 | {(size_t)-475611394924150513, (void*)"replace"}, 108 | {(size_t)8566273963665974510, (void*)"rfind"}, 109 | {(size_t)-295205302757070552, (void*)"rindex"}, 110 | {(size_t)2119545889811422497, (void*)"rjust"}, 111 | {(size_t)-7632506038852954866, (void*)"rpartition"}, 112 | {(size_t)-7478859825809313188, (void*)"rsplit"}, 113 | {(size_t)6967846247828238390, (void*)"rstrip"}, 114 | {(size_t)-1666158750398020171, (void*)"split"}, 115 | {(size_t)6545242454319875859, (void*)"splitlines"}, 116 | {(size_t)-9054588884789670847, (void*)"startswith"}, 117 | {(size_t)2334087250953981719, (void*)"strip"}, 118 | {(size_t)-5944333514074386483, (void*)"swapcase"}, 119 | {(size_t)-9092798511318848473, (void*)"title"}, 120 | {(size_t)-4075548806044035269, (void*)"translate"}, 121 | {(size_t)121890850537711745, (void*)"upper"}, 122 | {(size_t)7057264582011549012, (void*)"zfill"}, 123 | }; 124 | int i; 125 | std::unordered_map map; 126 | for (i=0; i != <%zu, %p>\n", 137 | tests[i].key, tests[i].value, tests[i].key, val); 138 | } 139 | } 140 | 141 | for (i=0; iroot){ 21 | TreeNode* parent = inserted->parent; 22 | if (parent->color == RED && inserted->color == RED){ 23 | TreeNode* grandparent = parent->parent; 24 | int child = parent->key < grandparent->key? 1:0; 25 | TreeNode* uncle = grandparent->children[child]; 26 | if (uncle != NULL && uncle->color == RED){ 27 | // recolor 28 | uncle->color = BLACK; 29 | parent->color = BLACK; 30 | grandparent->color = RED; 31 | } 32 | else{ 33 | if (inserted == parent->children[child]){ // inserted node is on same side as uncle 34 | _RedBlackTree_swapParent(self, inserted); // swap parent and child 35 | inserted = inserted->children[!child]; // rotation is now done on parent 36 | } 37 | // rotate 38 | parent = inserted->parent; 39 | grandparent = parent->parent; 40 | _RedBlackTree_rotate(self, inserted->parent); 41 | // recolor 42 | parent->color = BLACK; 43 | grandparent->color = RED; 44 | } 45 | } 46 | inserted = inserted->parent; 47 | } 48 | self->root->color = BLACK; // root must always be black 49 | } 50 | 51 | void _RedBlackTree_onDelBalance(BinaryTree* self, TreeNode* child){ 52 | if (child == NULL) return; 53 | if (child!=NULL && child->color == RED){ // child is red 54 | child->color = BLACK; // recolor 55 | return; 56 | } 57 | else if (child == self->root){ // case 1: new root, nothing to do 58 | return; 59 | } 60 | else{ 61 | _RedBlackTree_delCase2(self, child); 62 | if (!_RedBlackTree_delCase3(self, child)) 63 | if (!_RedBlackTree_delCase4(self, child)) 64 | if (!_RedBlackTree_delCase5(self, child)); 65 | _RedBlackTree_delCase6(self, child); 66 | } 67 | } 68 | 69 | void _RedBlackTree_rotate(BinaryTree* self, TreeNode* node){ 70 | TreeNode* parent = node->parent; 71 | TreeNode* grandparent = parent->parent; 72 | int child = node->key > parent->key? 1:0; 73 | TreeNode* aux = node->children[!child]; 74 | parent->children[child] = aux; 75 | if (aux!=NULL) aux->parent = parent; 76 | node->children[!child] = parent; 77 | parent->parent = node; 78 | node->parent = grandparent; 79 | if (grandparent == NULL) self->root = node; 80 | else{ 81 | if (grandparent->children[0] == parent) grandparent->children[0] = node; 82 | else grandparent->children[1] = node; 83 | } 84 | } 85 | 86 | void _RedBlackTree_swapParent(BinaryTree* self, TreeNode* inserted){ 87 | TreeNode* parent = inserted->parent; 88 | TreeNode* grandparent = parent->parent; 89 | int child = inserted->key < parent->key? 1:0; 90 | TreeNode* aux = inserted->children[child]; 91 | grandparent->children[child] = inserted; 92 | parent->children[!child] = aux; 93 | inserted->children[child] = parent; 94 | parent->parent = inserted; 95 | inserted->parent = grandparent; 96 | if (aux!=NULL) aux->parent = parent; 97 | } 98 | 99 | int _RedBlackTree_delCase2(BinaryTree* self, TreeNode* child){ 100 | TreeNode* parent = child->parent; 101 | if (parent != NULL && parent->color == BLACK){ 102 | TreeNode* S = (parent->children[0]==child)? parent->children[1] : parent->children[0]; 103 | if (S->color == RED){ 104 | parent->color = RED; 105 | S->color = BLACK; 106 | _RedBlackTree_rotate(self, S); 107 | return 1; 108 | } 109 | } 110 | return 0; 111 | } 112 | 113 | int _RedBlackTree_delCase3(BinaryTree* self, TreeNode* child){ 114 | TreeNode* parent = child->parent; 115 | if (parent != NULL && parent->color == BLACK){ 116 | TreeNode* S = (parent->children[0]==child)? parent->children[1] : parent->children[0]; 117 | if (S->color == BLACK){ 118 | S->color = RED; 119 | _RedBlackTree_onDelBalance(self, parent); 120 | return 1; 121 | } 122 | } 123 | return 0; 124 | } 125 | 126 | int _RedBlackTree_delCase4(BinaryTree* self, TreeNode* child){ 127 | TreeNode* parent = child->parent; 128 | if (parent != NULL && parent->color == RED){ 129 | TreeNode* S = (parent->children[0]==child)? parent->children[1] : parent->children[0]; 130 | if (S->color == BLACK && 131 | (S->children[0] == NULL || S->children[0]->color == BLACK) && 132 | (S->children[1] == NULL || S->children[1]->color == BLACK)){ 133 | parent->color = BLACK; 134 | S->color = RED; 135 | return 1; 136 | } 137 | } 138 | return 0; 139 | } 140 | 141 | int _RedBlackTree_delCase5(BinaryTree* self, TreeNode* child){ 142 | TreeNode* parent = child->parent; 143 | if (parent != NULL && parent->color == BLACK){ 144 | int c = child->key > parent->key? 1:0; 145 | TreeNode* S = parent->children[!c]; 146 | if (S->color == BLACK && 147 | (S->children[c] == NULL || S->children[c]->color == BLACK) && 148 | (S->children[!c] != NULL && S->children[!c]->color == RED)){ 149 | S->children[!c]->color = BLACK; 150 | S->color = RED; 151 | _RedBlackTree_rotate(self, S->children[!c]); 152 | return 1; 153 | } 154 | } 155 | return 0; 156 | } 157 | 158 | int _RedBlackTree_delCase6(BinaryTree* self, TreeNode* child){ 159 | TreeNode* parent = child->parent; 160 | if (parent != NULL){ 161 | int c = child->key > parent->key? 1:0; 162 | TreeNode* S = parent->children[!c]; 163 | if (S->color == BLACK && 164 | (S->children[c] != NULL || S->children[c]->color == RED)){ 165 | S->color = parent->color; 166 | parent->color = BLACK; 167 | S->children[c]->color = BLACK; 168 | _RedBlackTree_rotate(self, S); 169 | return 1; 170 | } 171 | } 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /alsmap.c: -------------------------------------------------------------------------------- 1 | #include "alsmap.h" 2 | 3 | #ifdef USE_PRIMES 4 | #define INITIAL_SIZE 7 5 | #else 6 | #define INITIAL_SIZE 8 7 | #endif 8 | 9 | #define INITIAL_RANGE 4 10 | 11 | // Table's growth policies 12 | #define CRC_THRESHOLD 0.5f 13 | #ifdef USE_TREE 14 | #define NA_THRESHOLD 0.3f 15 | #define MA_THRESHOLD 1.5f 16 | #else 17 | #define NA_THRESHOLD 0.3f 18 | #define MA_THRESHOLD 1.5f 19 | #endif 20 | 21 | // table's shrink policies 22 | #define MIN_LF 0.7f 23 | 24 | #define min(x, y) ((xy)? x:y) 26 | 27 | #ifdef USE_PRIMES 28 | size_t primes[] = {7, 17, 31, 61, 127, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771, 65537, 131071, 262147, 524287}; 29 | #endif 30 | 31 | 32 | // Private functions 33 | static void resizeTable(ALSHashMap* self, size_t newsize); 34 | static void redistributeAux(ALSHashMap* self); 35 | static void reallocBuckets(ALSHashMap* self, int i); 36 | static ALSNode* probeBuckets(ALSHashMap* self, size_t key, int i); 37 | 38 | ALSHashMap* ALSHashMap_New(){ 39 | ALSHashMap* self = (ALSHashMap*)malloc(sizeof(ALSHashMap)); 40 | self->table = (ALSNode*)malloc(sizeof(ALSNode)*INITIAL_SIZE); 41 | self->T = INITIAL_SIZE; 42 | self->N = 0; 43 | self->R = INITIAL_RANGE; 44 | self->CRC = 0; 45 | self->NA = 0; 46 | self->NE = INITIAL_SIZE; 47 | self->MA = 0; 48 | int i=0; for (; itable[i].type = E; 50 | } 51 | #ifdef UNIQUE_AUX 52 | #ifdef USE_TREE 53 | self->col = BinaryTree_New(); 54 | #else 55 | self->col = LinkedList_New(); 56 | #endif 57 | #endif 58 | return self; 59 | } 60 | 61 | void ALSHashMap_Set(ALSHashMap* self, size_t key, void* value){ 62 | if (self != NULL && value != NULL){ 63 | int i = key%self->T; 64 | ALSNode* node = &(self->table[i]); 65 | switch (node->type){ 66 | case E: // empty bucket, insert directly 67 | node->bucket.pair.key = key; 68 | node->bucket.pair.value = value; 69 | node->type = L; 70 | self->N++; 71 | self->NE--; 72 | break; 73 | case L: // occupied by item that belongs here 74 | { 75 | ALSNode* probe; 76 | if (node->bucket.pair.key == key){ // update value 77 | node->bucket.pair.value = value; 78 | } 79 | else if ((probe = probeBuckets(self, key, i))!=NULL){ // probe bucket 80 | if (probe->type == E){ 81 | self->NE--; 82 | self->N++; 83 | probe->type = B; 84 | probe->bucket.pair.key = key; 85 | } 86 | probe->bucket.pair.value = value; 87 | } 88 | else{ // use auxiliary data structure 89 | #ifdef USE_TREE 90 | #ifdef UNIQUE_AUX 91 | BinaryTree* aux = self->col; 92 | #else 93 | BinaryTree* aux = BinaryTree_New(); 94 | #endif 95 | BinaryTree_Set(aux, key, value); 96 | BinaryTree_Set(aux, node->bucket.pair.key, node->bucket.pair.value); 97 | #else 98 | #ifdef UNIQUE_AUX 99 | LinkedList* aux = self->col; 100 | #else 101 | LinkedList* aux = LinkedList_New(); 102 | #endif 103 | LinkedList_Set(aux, key, value); 104 | LinkedList_Set(aux, node->bucket.pair.key, node->bucket.pair.value); 105 | #endif 106 | #ifndef UNIQUE_AUX 107 | node->bucket.col = aux; 108 | #endif 109 | node->type = A; 110 | self->N++; 111 | reallocBuckets(self, i); 112 | if (aux->size > self->MA) self->MA = aux->size; 113 | self->NA++; 114 | } 115 | } 116 | break; 117 | case B: // occupied by item that doesn't belong here -> do cuckoo hashing 118 | { 119 | size_t auxkey = node->bucket.pair.key; 120 | void* auxvalue = node->bucket.pair.value; 121 | node->bucket.pair.key = key; 122 | node->bucket.pair.value = value; 123 | node->type = L; 124 | ALSHashMap_Set(self, auxkey, auxvalue); 125 | } 126 | break; 127 | case A: // add to auxiliary data structure 128 | { 129 | if ((int)(key%(2*self->T))!=i) self->CRC++; 130 | #ifdef USE_TREE 131 | #ifdef UNIQUE_AUX 132 | BinaryTree* aux = self->col; 133 | #else 134 | BinaryTree* aux = node->bucket.col; 135 | #endif 136 | size_t list_size = BinaryTree_Size(aux); 137 | BinaryTree_Set(aux, key, value); 138 | size_t newsize = BinaryTree_Size(aux); 139 | #else 140 | #ifdef UNIQUE_AUX 141 | LinkedList* aux = self->col; 142 | #else 143 | LinkedList* aux = node->bucket.col; 144 | #endif 145 | size_t list_size = LinkedList_Size(aux); 146 | LinkedList_Set(aux, key, value); 147 | size_t newsize = LinkedList_Size(aux); 148 | #endif 149 | self->N += newsize-list_size; 150 | if (newsize > self->MA) self->MA = newsize; 151 | } 152 | break; 153 | } 154 | } 155 | 156 | int grow = 0; 157 | 158 | #ifdef UNIQUE_AUX 159 | grow = ((float)self->CRC/self->N >= CRC_THRESHOLD || 160 | (float)self->NA/self->T >= NA_THRESHOLD || 161 | (float)self->MA >= self->T); 162 | #else 163 | grow = ((float)self->CRC/self->N >= CRC_THRESHOLD || 164 | (float)self->NA/self->T >= NA_THRESHOLD || 165 | (float)self->MA/self->R >= MA_THRESHOLD); 166 | #endif 167 | 168 | if (grow) 169 | resizeTable(self, 2*self->T); 170 | } 171 | 172 | void* ALSHashMap_Get(ALSHashMap* self, size_t key){ 173 | if (self != NULL){ 174 | int i = key%self->T; 175 | ALSNode* node = &(self->table[i]); 176 | switch (node->type){ 177 | case E: // empty bucket, item not found 178 | return NULL; 179 | break; 180 | case L: // occupied by item that belongs here 181 | { 182 | ALSNode* probe; 183 | if (node->bucket.pair.key == key) // found right here 184 | return node->bucket.pair.value; 185 | else if ((probe = probeBuckets(self, key, i))!=NULL){ // probe bucket 186 | if (probe->type == B){ 187 | return probe->bucket.pair.value; 188 | } 189 | } 190 | // not found 191 | return NULL; 192 | } 193 | break; 194 | case B: // occupied by item that doesn't belong here -> not found 195 | { 196 | return NULL; 197 | } 198 | break; 199 | case A: // search in auxiliary data structure 200 | { 201 | #ifdef USE_TREE 202 | #ifdef UNIQUE_AUX 203 | BinaryTree* aux = self->col; 204 | #else 205 | BinaryTree* aux = node->bucket.col; 206 | #endif 207 | return BinaryTree_Get(aux, key); 208 | #else 209 | #ifdef UNIQUE_AUX 210 | LinkedList* aux = self->col; 211 | #else 212 | LinkedList* aux = node->bucket.col; 213 | #endif 214 | return LinkedList_Get(aux, key); 215 | #endif 216 | } 217 | break; 218 | } 219 | } 220 | return NULL; 221 | } 222 | 223 | void* ALSHashMap_Del(ALSHashMap* self, size_t key){ 224 | void* ret = NULL; 225 | if (self != NULL){ 226 | int i = key%self->T; 227 | ALSNode* node = &(self->table[i]); 228 | switch (node->type){ 229 | case E: // empty bucket, item not found 230 | break; 231 | case L: // occupied by item that belongs here 232 | { 233 | ALSNode* probe; 234 | if (node->bucket.pair.key == key){ // found right here 235 | node->type = E; 236 | ret = node->bucket.pair.value; 237 | reallocBuckets(self, i); 238 | self->N--; 239 | self->NE++; 240 | } 241 | else if ((probe = probeBuckets(self, key, i))!=NULL){ // probe bucket 242 | if (probe->type == B){ 243 | probe->type = E; 244 | ret = probe->bucket.pair.value; 245 | self->N--; 246 | self->NE++; 247 | } 248 | } 249 | } 250 | break; 251 | case B: // occupied by item that doesn't belong here -> not found 252 | { 253 | return NULL; 254 | } 255 | break; 256 | case A: // search in auxiliary data structure 257 | { 258 | #ifdef USE_TREE 259 | #ifdef UNIQUE_AUX 260 | BinaryTree* aux = self->col; 261 | #else 262 | BinaryTree* aux = node->bucket.col; 263 | #endif 264 | ret = BinaryTree_Del(aux, key); 265 | #ifndef UNIQUE_AUX 266 | if (BinaryTree_Size(aux)==0){ 267 | BinaryTree_Destroy(aux); 268 | self->NA--; 269 | node->type = E; 270 | self->NE++; 271 | } 272 | #endif 273 | #else 274 | #ifdef UNIQUE_AUX 275 | LinkedList* aux = self->col; 276 | #else 277 | LinkedList* aux = node->bucket.col; 278 | #endif 279 | ret = LinkedList_Del(aux, key); 280 | #ifndef UNIQUE_AUX 281 | if (LinkedList_Size(node->bucket.col)==0){ 282 | LinkedList_Destroy(node->bucket.col); 283 | self->NA--; 284 | node->type = E; 285 | self->NE++; 286 | } 287 | #endif 288 | #endif 289 | if (ret != NULL) self->N--; 290 | } 291 | break; 292 | } 293 | } 294 | if ((float)(self->T-self->NE)/self->T < MIN_LF){ 295 | redistributeAux(self); 296 | if ((float)(self->T-self->NE)/self->T < MIN_LF && self->T > INITIAL_SIZE){ 297 | resizeTable(self, self->T/2); 298 | } 299 | } 300 | return ret; 301 | } 302 | 303 | void ALSHashMap_Destroy(ALSHashMap* self){ 304 | #ifdef UNIQUE_AUX 305 | #ifdef USE_TREE 306 | BinaryTree_Destroy(self->col); 307 | #else 308 | LinkedList_Destroy(self->col); 309 | #endif 310 | #else 311 | int i=0; for (; iT; i++){ 312 | if (self->table[i].type == A){ 313 | #ifdef USE_TREE 314 | BinaryTree_Destroy(self->table[i].bucket.col); 315 | #else 316 | LinkedList_Destroy(self->table[i].bucket.col); 317 | #endif 318 | } 319 | } 320 | #endif 321 | free(self->table); 322 | free(self); 323 | } 324 | 325 | size_t ALSHashMap_Size(ALSHashMap* self){ 326 | return self->N; 327 | } 328 | 329 | void ALSHashMap_PrintStats(ALSHashMap* self){ 330 | int i; 331 | size_t SA=0, S=0, NL=0; 332 | printf("["); 333 | for (i=0; iT; i++){ 334 | switch (self->table[i].type){ 335 | case E: printf(" "); break; 336 | case L: printf("L"); NL++; break; 337 | case B: printf("B"); break; 338 | case A: 339 | #ifdef UNIQUE_AUX 340 | printf("A"); break; 341 | #else 342 | #ifdef USE_TREE 343 | S = BinaryTree_Size(self->table[i].bucket.col); 344 | #else 345 | S = LinkedList_Size(self->table[i].bucket.col); 346 | #endif 347 | printf("%zu", S); SA+=S; break; 348 | #endif 349 | } 350 | if (iT-1) printf(", "); 351 | } 352 | printf("]\n"); 353 | printf("CRC: %zu\n", self->CRC); 354 | printf("MA: %zu\n", self->MA); 355 | printf("T: %zu\n", self->T); 356 | printf("R: %zu\n", self->R); 357 | printf("NE: %zu\n", self->NE); 358 | printf("NA: %zu -> %f\n", self->NA, (double)self->NA/self->T); 359 | printf("NL: %zu -> %f\n", NL, (double)NL/self->T); 360 | #ifdef UNIQUE_AUX 361 | #ifdef USE_TREE 362 | printf("SA: %zu\n", BinaryTree_Size(self->col)); 363 | #else 364 | printf("SA: %zu\n", LinkedList_Size(self->col)); 365 | #endif 366 | #else 367 | printf("SA: %zu\n", SA); 368 | #endif 369 | printf("N: %zu\n", self->N); 370 | printf("Table Usage: %f\n", (double)(self->T-self->NE)/self->T); 371 | printf("Load Factor: %f\n", (double)self->N/self->T); 372 | #ifdef USE_TREE 373 | #ifdef USE_RED_BLACK 374 | printf("Using Red-Black Tree\n"); 375 | #else 376 | printf("Using BinaryTree\n"); 377 | #endif 378 | #else 379 | printf("Using LinkedList\n"); 380 | #endif 381 | #ifdef EXTENDED_PROBING 382 | printf("Using Extended Probing\n"); 383 | #else 384 | printf("Using Limited Probing\n"); 385 | #endif 386 | #ifdef UNIQUE_AUX 387 | printf("Using unique auxiliary structure\n"); 388 | #endif 389 | } 390 | 391 | 392 | // Private functions 393 | #ifdef USE_TREE 394 | static void redistributeTree(ALSHashMap* self, TreeNode* tnode){ 395 | if (tnode != NULL){ 396 | redistributeTree(self, tnode->children[0]); 397 | redistributeTree(self, tnode->children[1]); 398 | ALSHashMap_Set(self, tnode->key, tnode->value); 399 | free(tnode); 400 | } 401 | } 402 | #else 403 | static void redistributeList(ALSHashMap* self, ListNode* node){ 404 | while (node != NULL){ 405 | ALSHashMap_Set(self, node->key, node->value); 406 | ListNode* aux = node; 407 | node = node->next; 408 | free(aux); 409 | } 410 | } 411 | #endif 412 | 413 | 414 | // change the size of the table 415 | static void resizeTable(ALSHashMap* self, size_t newsize){ 416 | //printf("resize %zu -> %zu\n", self->T, newsize); 417 | int i; 418 | // backup table 419 | ALSNode* table = self->table; 420 | size_t T = self->T; 421 | 422 | // reset values and allocate new table 423 | if (newsize > T){ 424 | self->R++; 425 | newsize = self->T*2; 426 | } 427 | else{ 428 | self->R--; 429 | newsize = self->T/2; 430 | } 431 | 432 | #ifdef USE_PRIMES 433 | newsize = primes[self->R - INITIAL_RANGE]; 434 | #endif 435 | 436 | self->MA = 0; 437 | self->CRC = 0; 438 | self->NA = 0; 439 | self->NE = newsize; 440 | self->N = 0; 441 | self->T = newsize; 442 | self->table = (ALSNode*)malloc(sizeof(ALSNode)*newsize); 443 | for (i=0; itable[i].type = E; 445 | 446 | // iterate over old table and add to new table 447 | for (i=0; iroot); 453 | free(table[i].bucket.col); 454 | #else 455 | ListNode* node = table[i].bucket.col->start; 456 | redistributeList(self, node); 457 | free(table[i].bucket.col); 458 | #endif 459 | #endif 460 | } 461 | else{ 462 | ALSHashMap_Set(self, table[i].bucket.pair.key, table[i].bucket.pair.value); 463 | } 464 | } 465 | } 466 | #ifdef UNIQUE_AUX 467 | #ifdef USE_TREE 468 | BinaryTree* tree = self->col; 469 | self->col = BinaryTree_New(); 470 | redistributeTree(self, tree->root); 471 | free(tree); 472 | #else 473 | LinkedList* list = self->col; 474 | self->col = LinkedList_New(); 475 | redistributeList(self, list->start); 476 | free(list); 477 | #endif 478 | #endif 479 | free(table); 480 | } 481 | 482 | // attempt to redistribute auxiliary structures 483 | static void redistributeAux(ALSHashMap* self){ 484 | //printf("Redistribute aux\n"); 485 | int i; 486 | self->MA = 0; 487 | #ifdef UNIQUE_AUX 488 | #ifdef USE_TREE 489 | BinaryTree* tree = self->col; 490 | self->col = BinaryTree_New(); 491 | redistributeTree(self, tree->root); 492 | free(tree); 493 | #else 494 | LinkedList* list = self->col; 495 | self->col = LinkedList_New(); 496 | redistributeList(self, list->start); 497 | free(list); 498 | #endif 499 | #else 500 | for (i=0; iT; i++){ 501 | if (self->table[i].type == A){ 502 | self->table[i].type = E; 503 | self->NE++; 504 | self->NA--; 505 | #ifdef USE_TREE 506 | BinaryTree* tree = self->table[i].bucket.col; 507 | self->N -= BinaryTree_Size(tree); 508 | redistributeTree(self, tree->root); 509 | free(tree); 510 | #else 511 | LinkedList* list = self->table[i].bucket.col; 512 | self->N -= LinkedList_Size(list); 513 | redistributeList(self, list->start); 514 | free(list); 515 | #endif 516 | } 517 | } 518 | #endif 519 | } 520 | 521 | // move a node into its real position, returns 1 if can't allocate more 522 | static int reallocNode(ALSHashMap* self, int i, ALSNode* node, ALSNode* into){ 523 | if (node->type == B && node->bucket.pair.key%self->T == i){ 524 | if (into->type == E){ 525 | into->bucket.pair.key = node->bucket.pair.key; 526 | into->bucket.pair.value = node->bucket.pair.value; 527 | into->type = L; 528 | node->type = E; 529 | return 1; 530 | } 531 | else if (into->type == A){ 532 | #ifdef USE_TREE 533 | #ifdef UNIQUE_AUX 534 | BinaryTree* tree = self->col; 535 | #else 536 | BinaryTree* tree = into->bucket.col; 537 | #endif 538 | BinaryTree_Set(tree, node->bucket.pair.key, node->bucket.pair.value); 539 | #else 540 | #ifdef UNIQUE_AUX 541 | LinkedList* list = self->col; 542 | #else 543 | LinkedList* list = into->bucket.col; 544 | #endif 545 | LinkedList_Set(list, node->bucket.pair.key, node->bucket.pair.value); 546 | #endif 547 | node->type = E; 548 | self->NE++; 549 | } 550 | } 551 | return 0; 552 | } 553 | 554 | // do a probe and reallocate buckets to their original position 555 | static void reallocBuckets(ALSHashMap* self, int i){ 556 | int p1 = i-1; 557 | int p2 = i+1; 558 | int p1bound = max(0, (int)i - (int)(self->R)); 559 | int p2bound = min(self->T-1, i+self->R); 560 | ALSNode* into = &(self->table[i]); 561 | while (p1>=p1bound || p2<=p2bound){ 562 | if (p1>=p1bound){ 563 | ALSNode* node = &(self->table[p1]); 564 | if (reallocNode(self, i, node, into)){ 565 | return; 566 | } 567 | p1--; 568 | } 569 | if (p2<=p2bound){ 570 | ALSNode* node = &(self->table[p2]); 571 | if (reallocNode(self, i, node, into)){ 572 | return; 573 | } 574 | p2++; 575 | } 576 | } 577 | #ifdef EXTENDED_PROBING 578 | int inc = (int)self->T / (int)self->R; 579 | while (p1>=0 || p2T){ 580 | if (p1>=0){ 581 | ALSNode* node = &(self->table[p1]); 582 | if (reallocNode(self, i, node, into)){ 583 | return; 584 | } 585 | p1-=inc; 586 | } 587 | if (p2T){ 588 | ALSNode* node = &(self->table[p2]); 589 | if (reallocNode(self, i, node, into)){ 590 | return; 591 | } 592 | p2+=inc; 593 | } 594 | } 595 | #endif 596 | } 597 | 598 | // check if node is empty or contains key 599 | // if it contains key and there is empty bucket closer to its real position, reallocate it 600 | static int probeNode(ALSNode** node, ALSNode** empty, size_t key){ 601 | ALSNode* e = *empty; 602 | ALSNode* n = *node; 603 | int ret = 0; 604 | if (e == NULL && n->type == E) e = n; // found first empty node 605 | else if (n->type == B && n->bucket.pair.key == key){ // found node containing key 606 | if (e != NULL){ // move node to empty bucket closer to its real position 607 | e->type = B; 608 | e->bucket.pair.key = n->bucket.pair.key; 609 | e->bucket.pair.value = n->bucket.pair.value; 610 | n->type = E; 611 | n = e; 612 | } 613 | ret = 1; 614 | } 615 | *node = n; 616 | *empty = e; 617 | return ret; 618 | } 619 | 620 | // probe for an empty bucket or bucket containing key 621 | static ALSNode* probeBuckets(ALSHashMap* self, size_t key, int i){ 622 | int p1 = i-1; 623 | int p2 = i+1; 624 | int p1bound = max(0, (int)i - (int)(self->R)); 625 | int p2bound = min(self->T-1, i+self->R); 626 | ALSNode* empty = NULL; 627 | while (p1>=p1bound || p2<=p2bound){ 628 | if (p1>=p1bound){ 629 | ALSNode* node = &(self->table[p1]); 630 | if (probeNode(&node, &empty, key)) 631 | return node; 632 | p1--; 633 | } 634 | if (p2<=p2bound){ 635 | ALSNode* node = &(self->table[p2]); 636 | if (probeNode(&node, &empty, key)) 637 | return node; 638 | p2++; 639 | } 640 | } 641 | #ifdef EXTENDED_PROBING 642 | int inc = (int)self->T / (int)self->R; 643 | while (p1>=0 || p2T){ 644 | if (p1>=0){ 645 | ALSNode* node = &(self->table[p1]); 646 | if (probeNode(&node, &empty, key)) 647 | return node; 648 | p1-=inc; 649 | } 650 | if (p2T){ 651 | ALSNode* node = &(self->table[p2]); 652 | if (probeNode(&node, &empty, key)) 653 | return node; 654 | p2+=inc; 655 | } 656 | } 657 | #endif 658 | return empty; 659 | } 660 | --------------------------------------------------------------------------------