-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
daee4e9
commit f7062fa
Showing
4 changed files
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.DS_Store | ||
a.out* | ||
build/ | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#include "../hset/rtw_hset.h" | ||
|
||
// This is hash_fun to get hash value of given key, in first example our key is | ||
// char* so we are casting void * type to char *, at the end of function we are | ||
// taking modular 30 because our bucket size is 30. So our key should be between | ||
// 0-29. | ||
|
||
unsigned long hash_func(const void *key) { | ||
char *my_key = (char *)key; | ||
|
||
unsigned long hash = 5381; | ||
int c; | ||
|
||
while ((c = *my_key++)) | ||
hash = ((hash << 5) + hash) + c; | ||
|
||
return hash; | ||
} | ||
|
||
// This is a cmp_fun to identify if two strings are same or not. | ||
// We will use this function when we try to push - get something from our set. | ||
// If our key is char*(string) then we have to compare keys inorder to push to | ||
// set or get from set. | ||
int cmp_fun_str(const void *lhs, const void *rhs) { | ||
return strcmp((char *)lhs, (char *)rhs) == 0; | ||
} | ||
|
||
void example_set_int() { | ||
// in this example we will use our hashset like | ||
// std::set<int> so our data is integer | ||
|
||
// we have to create our hash set object with rtw_hset_init function. | ||
// It takes 3 parameter, first one is predefined hash_func, | ||
// Second one is our predefined comparasion function | ||
// third one is sizeof our object (in this case its sizeof(int)) | ||
rtw_hset set = rtw_hset_init(&hash_func, &cmp_fun_str, sizeof(int)); | ||
|
||
int data1 = 5; | ||
int data2 = 6; | ||
int data3 = 12; | ||
|
||
// To push pairs into our hash set our function is "rtw_hset_insert", it | ||
// takes 2 parameter. First one is address of our set, second one is our data | ||
rtw_hset_insert(&set, &data1); | ||
rtw_hset_insert(&set, &data2); | ||
rtw_hset_insert(&set, &data3); | ||
|
||
// Now lets try to find our data. To do that our function is | ||
// "rtw_hset_find", it takes 2 arg. First one is address of our set, second | ||
// one is our data. If thereis value | ||
// with given data it returns 1 otherwise it returns 0. | ||
|
||
if (rtw_hset_find(&set, &data1)) | ||
printf("%d exists in hashet.\n", data1); | ||
else | ||
printf("data: %d couldn't found!\n", data1); | ||
|
||
if (rtw_hset_find(&set, &data2)) | ||
printf("%d exists in hashset.\n", data2); | ||
else | ||
printf("data: %d couldn't found!\n", data2); | ||
|
||
// This is a data which we do not have in our hset. | ||
int data4 = 56; | ||
|
||
if (rtw_hset_find(&set, &data4)) | ||
printf("%d exists in hashset.\n", data4); | ||
else | ||
printf("key: '%d' couldn't found!\n", data4); | ||
|
||
// Now lets try to access our data3 and delete it from hset. | ||
if (rtw_hset_find(&set, &data3)) | ||
printf("%d exists in hashset.\n", data3); | ||
else | ||
printf("data: %d couldn't found!\n", data3); | ||
|
||
// Our data3 is in hset, so now lets try to delete it. | ||
if (rtw_hset_del(&set, &data3)) | ||
printf("data: %d deleted from hset.\n", data3); | ||
else | ||
printf("data: %d does not exist on hset.\n", data3); | ||
|
||
// We have deleted data3 already from set, lets try to delete it again. | ||
if (rtw_hset_del(&set, &data3)) | ||
printf("data: %d deleted from hset.\n", data3); | ||
else | ||
printf("data: %d does not exist on hset.\n", data3); | ||
|
||
|
||
rtw_hset_free(&set); | ||
} | ||
int main() { | ||
|
||
printf("---- example of str as key ----\n"); | ||
example_set_int(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include "rtw_hset.h" | ||
#include <string.h> | ||
|
||
rtw_hset rtw_hset_init(rtw_hset_hash_fn hash_fn, rtw_hset_eq_fn eq_fn, | ||
size_t data_len) { | ||
rtw_hset set; | ||
set.hash_fn = hash_fn; | ||
set.eq_fn = eq_fn; | ||
set.data = rtw_vec_init(data_len); | ||
|
||
memset(set.elements, 0, sizeof(set.elements)); | ||
|
||
return set; | ||
} | ||
|
||
int rtw_hset_del(rtw_hset *set, const void *data) { | ||
unsigned long index = set->hash_fn(data) % RTW_HSET_BUCKET_SIZE_; | ||
|
||
rtw_hset_elem_ *curr_node = set->elements[index]; | ||
rtw_hset_elem_ *prev_node = NULL; | ||
|
||
while (NULL != curr_node) { | ||
if (set->eq_fn(data, curr_node->data)) { | ||
char last_elem[set->data.elem_len]; | ||
rtw_vec_pop_back(&set->data, last_elem); | ||
if (1 != set->data.len) { | ||
// Overwrite the deleted element's data with the last element's | ||
// data. We don't delete the deleted key from the vector. | ||
// Because it would be expensive. We overwrite the deleted | ||
// element's data with the last element's data so that we only | ||
// make 1 memcpy and no allocation. | ||
memcpy(curr_node->data, last_elem, set->data.elem_len); | ||
} | ||
|
||
if (NULL == prev_node) { | ||
set->elements[index] = curr_node->next; | ||
} else { | ||
prev_node->next = curr_node->next; | ||
} | ||
|
||
free(curr_node); | ||
return 1; | ||
} | ||
prev_node = curr_node; | ||
curr_node = curr_node->next; | ||
} | ||
return 0; | ||
} | ||
|
||
int rtw_hset_find(const rtw_hset *self, const void *data) { | ||
unsigned long index = self->hash_fn(data) % RTW_HSET_BUCKET_SIZE_; | ||
rtw_hset_elem_ *last = self->elements[index]; | ||
while (NULL != last) { | ||
if (self->eq_fn(data, last->data)) { | ||
return 1; | ||
} | ||
last = last->next; | ||
} | ||
return 0; | ||
} | ||
|
||
inline static rtw_hset_elem_ * | ||
rtw_hset_elem_init_(rtw_hset *set, const void *data) { | ||
// Key and value needed to be packed in a single memory location. | ||
char temp[(set->data.elem_len)]; | ||
memcpy(temp, data, set->data_len); | ||
|
||
rtw_vec_push_back(&set->data, temp); | ||
|
||
rtw_hset_elem_ *item = (rtw_hset_elem_ *)malloc(sizeof(rtw_hset_elem_)); | ||
item->next = NULL; | ||
item->data = rtw_vec_last(&set->data); | ||
|
||
return item; | ||
} | ||
|
||
void rtw_hset_insert(rtw_hset *self, const void *data) { | ||
unsigned long index = self->hash_fn(data) % RTW_HSET_BUCKET_SIZE_; | ||
|
||
rtw_hset_elem_ *last = self->elements[index]; | ||
if (last == NULL) { | ||
self->elements[index] = rtw_hset_elem_init_(self, data); | ||
return; | ||
} | ||
for (;;) { | ||
if (self->eq_fn(data, last->data)) { | ||
return; | ||
} | ||
if (last->next == NULL) | ||
break; | ||
last = last->next; | ||
} | ||
|
||
last->next = rtw_hset_elem_init_(self, data); | ||
} | ||
|
||
void rtw_hset_free(rtw_hset *self) { | ||
rtw_vec_free(&self->data); | ||
|
||
for (int i = 0; i < RTW_HSET_BUCKET_SIZE_; i++) { | ||
if (self->elements[i]) { | ||
rtw_hset_elem_ *elem = self->elements[i]; | ||
while (elem != NULL) { | ||
rtw_hset_elem_ *tmp = elem; | ||
elem = elem->next; | ||
free(tmp); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#include "../vec/rtw_vec.h" | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#define RTW_HSET_BUCKET_SIZE_ 30 | ||
|
||
typedef unsigned long (*rtw_hset_hash_fn)(const void *); | ||
typedef int (*rtw_hset_eq_fn)(const void *, const void *); | ||
|
||
typedef struct rtw_hset_elem_s_ { | ||
void *data; | ||
struct rtw_hset_elem_s_ *next; | ||
} rtw_hset_elem_; | ||
|
||
typedef struct { | ||
rtw_hset_hash_fn hash_fn; | ||
rtw_hset_eq_fn eq_fn; | ||
rtw_hset_elem_ *elements[RTW_HSET_BUCKET_SIZE_]; | ||
rtw_vec data; | ||
size_t data_len; | ||
} rtw_hset; | ||
|
||
/** | ||
* Creates an empty binary set without any allocation | ||
* | ||
* @param cmp_fn Is function pointer to add our datas to hash set, comparasion | ||
* function. Help of this comp_fn we will know if incoming data exists in set or | ||
* not. It takes 2 parameters, left hand side and right hand side. It returns -1 | ||
* if right hand side is greater than left hand side It returns 1 if right hand | ||
* side is smaller than left hand side It returns 0 if two value is same. | ||
* @param hash_fn Is function pointer to hash data, hash function. | ||
* It takes only one void* parameter and get hash of that value. | ||
* It returns a hash value with int. | ||
* @param data_len Size of the data that the vector holds | ||
*/ | ||
rtw_hset rtw_hset_init(rtw_hset_hash_fn hash_fn, rtw_hset_eq_fn eq_fn, | ||
size_t data_len); | ||
|
||
/** | ||
* Deletes an element from hash set with given data. | ||
* | ||
* @param self Pointer to this set | ||
* @param data Pointer to the data | ||
* @return if deletion operation is success it returns 1, otherwise it returns 0. | ||
*/ | ||
int rtw_hset_del(rtw_hset *self, const void *data); | ||
|
||
/** | ||
* Finds the element with given data from 'self' . | ||
* | ||
* @param self Pointer to this set | ||
* @param data Pointer to the data | ||
* | ||
* @return 1 if element found, 0 otherwise. | ||
*/ | ||
int rtw_hset_find(const rtw_hset *self, const void *data); | ||
|
||
/** | ||
* Adds the data pointed by 'data' to the set. | ||
* | ||
* @param self Pointer to this set. | ||
* @param data Pointer to data that will be inserted. | ||
* | ||
*/ | ||
void rtw_hset_insert(rtw_hset *self, const void *data); | ||
|
||
/** | ||
* Frees allocated memory for this set. | ||
* | ||
* @param self Pointer to this set. | ||
* | ||
*/ | ||
void rtw_hset_free(rtw_hset *self); |