How to assign two void* C - arrays

I create in main.c an "hashmap" struct. it contains 6.000.000 "node" structs. i have to insert my elements by insert function. I didn't write it because it's not my trouble. If u need it I'll write it. Btw, the insert function is a generic function because data I need to insert every data type.In this case I insert a couple <key,value> of Integer. My trouble is : I have to make a function that return all key present in the hashmap t. In this function I have two parameters, both of them are void*. Key parameters in the hashmap are void*. The array that will contain all my keys, is void*. My aim is to put all my keys in this array and return it, but this is not possible ``` arr[j] = list->key; arr[j] = list->key;, the compiler gives me this error: incomplite type of void is not assignable*. Is there a way to resolve this thing?
library.c
struct node{
void* key;
void* val;
struct node *next;
struct node *prev;
};
struct hashmap{
int size;
struct node **list;
};
void recoverkey(struct hashmap *t, void *arr){
int j=0;
for (int i = 0; i < t->size; ++i) {
struct node *list = t->list[i];
while(list){
if(list->key!=NULL) {
arr[j] = list->key;
j++;
}
list = list->next;
}
}
}
main.c
#define SIZEFILE 6000000
int main(){
struct hashmap *t; // create hashmap
insert(); // I insert elements in the hashmap
int *arrRec;
arrRec = malloc(SIZEFILE*sizeof(int));
recoverkey(t,arrRec);

Related

How to save memory inside hashtable?

In my structure struct ListNode I am making a int type variable key but it is necessary to make that in the struct Listnode can we make that inside HashTableNode because when two or more items will be there in HashTableNode (that is when collision will be more in single table node) than we have to create more linked list node and every time inside that node key variable will consume some memory if we can define that inside HashTableNode than we can save memory.
Is it correct to mention the key in each list node so that we can access at any time whenever we need because the below hash table implementation is from very famous book of data structures.
Please tell me what i mentioned above is correct
Because i am a beginner if Not then please correct me
#define Load_factor 20
#include<stdio.h>
#include<stdlib.h>
struct Listnode{
int key;
int data;
struct Listnode* next;
};
struct HashTableNode{
int bcount; /// Number of elements in block
struct Listnode* next;
};
struct HashTable{
int tsize; /// Table size
int count;
struct HashTableNode** Table;
};
struct HashTable* createHashTable(int size){
struct HashTable* h;
h=(struct HashTable*)malloc(sizeof(struct HashTable));
h->tsize=size/Load_factor;
h->count=0;
h->Table=(struct HashTableNode**)malloc(sizeof(struct HashTableNode*)*h->tsize);
if(!h->Table){
printf("Memory Error");
return NULL;
}
for(int i=0;i<h->tsize;i++){
h->Table[i]->bcount=0;
h->Table[i]->next=NULL;
}
return h;
}
int HASH(int data,int tsize){
return(data%tsize);
}
/// Hashsearch
int HashSearch(struct HashTable* h,int data){
struct Listnode* temp;
temp=h->Table[HASH(data,h->tsize)]->next;
while(temp) ///same as temp!=NULL
{
if(temp->data==data)
return 1;
temp=temp->next;
}
return 0;
}
int HashDelete(struct HashTable* h,int data)
{
int index;
struct Listnode *temp,*prev;
index=HASH(data,h->tsize);
for(temp=h->Table[index]->next,prev=NULL;temp;prev=temp,temp=temp->next)
{
if(temp->data==data)
{
if(prev!=NULL)
prev->next=temp->next;
free(temp);
h->Table[index]->bcount--;
h->count--;
return 1;
}
}
return 0;
}
int HashInsert(struct HashTable *h ,int data){
int index;
struct Listnode* temp,*newnode;
if(HashSearch(h,data))
return 0;
index = HASH(data,h->tsize);
temp=h->Table[index]->next;
newnode=(struct Listnode*)malloc(sizeof(struct Listnode));
if(!newnode)
return -1;
newnode->key=index;
newnode->data;
newnode->next=h->Table[index]->next;
h->Table[index]->next=newnode;
h->Table[index]->bcount++;
h->count++;
return 1;
}
It is necessary to store key for every node because it is used to resolve collisions. Please note that the collision happens to the hash value and not the key, which means that every element (Listnode) in the same bucket (HashTableNode) will still have a different key so you can't optimize it away.
However, in your example the data is the key (which is usually called a HashSet as opposed to HashMap), so there is really no need for the key field in the Listnode.

how to update table size inside hash function

I was learning how to implement Hash table but i am bit confused here in because in the book below code was available and i understood well enough the code, but inside book there was no definition of HASH function ,i know we have to define it by own ,but according the below code that was given give inside book HASH is taking two arguments wherever i used the HASH like in HashInsert it is taking two arguments index=HASH(data,t->size) if we assume that return type of HASH as int
now for eg we can define HASH as
int HASH(int data,int tsize){
return(data%7);
}
but according to my program how should i update t->size(table size) inside HASH function or how should i use that
Please help me in proper implementation of the above HASH function
#define Load_factor 20
#include<stdio.h>
#include<stdlib.h>
struct Listnode{
int key;
int data;
struct Listnode* next;
};
struct HashTableNode{
int bcount; /// Number of elements in block
struct Listnode* next;
};
struct HashTable{
int tsize; /// Table size
int count;
struct HashTableNode** Table;
};
struct HashTable* createHashTable(int size){
struct HashTable* h;
h=(struct HashTable*)malloc(sizeof(struct HashTable));
h->tsize=size/Load_factor;
h->count=0;
h->Table=(struct HashTableNode**)malloc(sizeof(struct HashTableNode*)*h->tsize);
if(!h->Table){
printf("Memory Error");
return NULL;
}
for(int i=0;i<h->tsize;i++){
h->Table[i]->bcount=0;
h->Table[i]->next=NULL;
}
return h;
}
/// Hashsearch
int HashSearch(struct HashTable* h,int data){
struct Listnode* temp;
temp=h->Table[HASH(data,h->tsize)]->next;
while(temp) ///same as temp!=NULL
{
if(temp->data==data)
return 1;
temp=temp->next;
}
return 0;
}
int HashDelete(struct HashTable* h,int data)
{
int index;
struct Listnode *temp,*prev;
index=HASH(data,h->tsize);
for(temp=h->Table[index]->next,prev=NULL;temp;prev=temp,temp=temp->next)
{
if(temp->data==data)
{
if(prev!=NULL)
prev->next=temp->next;
free(temp);
h->Table[index]->bcount--;
h->count--;
return 1;
}
}
return 0;
}
int HashInsert(struct HashTable *h ,int data){
int index;
struct Listnode* temp,*newnode;
if(HashSearch(h,data))
return 0;
index = HASH(data,h->tsize);
temp=h->Table[index]->next;
newnode=(struct Listnode*)malloc(sizeof(struct Listnode));
if(!newnode)
return -1;
newnode->key=index;
newnode->data;
newnode->next=h->Table[index]->next;
h->Table[index]->next=newnode;
h->Table[index]->bcount++;
h->count++;
return 1;
}
i am just learning implementation of hashing so main is looking quiet weird
int main(){
return 0;
}
You shouldn't! I mean you shouldn't modify it.
Instead the function gets the size of the hash-table (the number of "buckets") so it can use it to create a bucket index from the hash value. This is typically done through modulo %.
So instead of a fixed magic number 7 you modulo with the size:
return(data%tsize);

C - Trying to make an array of LinkedList pointers

I'm trying to create a HashTable in C where each 'bucket' is a pointer to a LinkedList. That is, I need to create an array of LinkedList pointers.
As of now, SomeHashTable->Buckets[i] is returning a non-pointer LinkedList. I've been looking for answers everywhere and I just can't find anything. Perhaps I'm overlooking something? I've given my current code below.
HashTable.h
#include "LinkedList.h"
typedef struct HashTable
{
LinkedList* Buckets[1009];
} HashTable;
//Creates new hashtable
HashTable* HashTable_new();
//Hashes and adds a new entry
void HashTable_add(HashTable* Table, int data);
HashTable.c
#include "HashTable.h"
HashTable* HashTable_new()
{
HashTable* newTable = (HashTable*)malloc(sizeof(HashTable));
newTable->Buckets = malloc(1009 * sizeof(LinkedList*));
//Create linked lists
for (int i = 0; i < 1009; i++)
{
newTable->Buckets[i] = LinkedList_new();
}
return newTable;
}
void HashTable_add(HashTable* Table, int data)
{
int index = data % 1009;
//Get bucket to hash to
LinkedList* BucketHead = (Table->Buckets[index]);
//Hash it iiinnnn real good
LinkedList_add_at_end(BucketHead, data);
}
The linked List structs for reference:
typedef struct LinkedListNode {
int data;
struct LinkedListNode *next;
struct LinkedListNode *prev;
} LinkedListNode;
typedef struct LinkedList {
struct LinkedListNode *first;
struct LinkedListNode *last;
} LinkedList;
As H.S.'s comment mentions, there is no need to dynamically --and-- statically allocate the Buckets array.
This line:
newTable->Buckets = malloc(1009 * sizeof(LinkedList*));
is overwriting the pointer to the statically allocated array, which is probably not what you want. For scalability, I would ditch the static array and stick with malloc(). That way you could use an argument to HashTable_new() to specify the size of the buckets array, like so:
HashTable* HashTable_new(int nBuckets)
{
HashTable* newTable = (HashTable*)malloc(sizeof(HashTable));
newTable->Buckets = malloc(nBuckets * sizeof(LinkedList*));
newTable->nBuckets = nBuckets;
//Create linked lists
for (int i = 0; i < nBuckets; i++)
{
newTable->Buckets[i] = LinkedList_new();
}
return newTable;
}
Notice that newTable->Buckets is being allocated as a pointer to a pointer to LinkedList (LinkedList**). You'll need to keep track to the size of Buckets[], so add the variable to the struct as follows:
typedef struct HashTable
{
int nBuckets;
LinkedList **Buckets;
} HashTable;
You should be good as long as LinkedList_new()'s return type is LinkedList*, and don't forget to free() it all when you're done.

Initializing C struct using pointer to pointer

I'm working on creating a hash table implementation for an assignment. I've defined my hashtable as struct as follows:
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
I have to initialize the hashtable struct in a method using double pointers, e.g.:
void init(hashtable** ht) {
...
}
I've written a basic implementation below:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
void init(hashtable**);
void init(hashtable** ht) {
*ht = (hashtable *) malloc( sizeof(hashtable) );
*ht->size = 3;
}
int main(){
hashtable *t = NULL;
init(&t);
printf("t.size: %i", t->size);
}
However, I keep getting the following compile error:
ll.c:19:8: error: member reference base type 'hashtable *' (aka 'struct hashtable *') is not a
structure or union
*ht->size = 3;
~~^ ~~~~
1 error generated.
So I'm confused by the following:
1. I'm not sure how to create a new struct in the init function when being passed a pointer to pointer.
2. After allocating the struct, how do I modify the struct member attributes?
This is just a operator precedence problem.
The compiler processes -> before the *. Therefore, it tries to access the size member of struct hashtable ** which is not possible.
The code compiles if you exchange *ht->size with (*ht)->size.
You have 2 errors in your code :
int table* --> int *table - Declare pointer to integer
*ht->size --> (*ht)->size - Imp to put brackets when you are not sure of operator precedence
That's a good start, and others have addresses the primary issues in your code. However, I would suggest a minor tweak:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size;
int entries;
int table*; // pointer to table. Each entry will point to linked list
// of key-value nodes
} hashtable;
// note: freeing the hashtable is a caller responsibility!
hashtable *new_hashtable() {
hashtable *ht = malloc( sizeof(hashtable) );
ht->size = 3; // since ht is only a single pointer, no need for (*ht)->foo
return ht;
}
int main(){
hashtable *ht = new_hashtable();
printf("ht.size: %i", ht->size);
free(ht);
}
The problem is that
-> has higher precedence than * in C as you can see from here
using precedence rules *ht->size translates to *(ht->size). That should make clear the reason why you get the error. Another way to see it is
*(ht->size)=(*(*ht).size)
Fix this using parenthesis as follows: (*ht)->size
There is another issue in the definition of hashtable:
int table*; won't compile. Use int *table; instead to declare a pointer to int?
Thanks all for the quick response. For future reference, here's a quick update of the original code with solutions:
#include <stdio.h>
#include <stdlib.h>
typedef struct hashtable {
int size; // size of hash table
int entries; // number of slots allocated in table
int *table; /* pointer to table. Each entry will point to linked list
of key-value nodes */
} hashtable;
void init(hashtable**);
void init(hashtable** ht) {
*ht = (hashtable *) malloc( sizeof(hashtable) );
(*ht)->entries = 0;
(*ht)->size = 3; //replace this with better init size, ideally a prime number
(*ht)->table = malloc( (*ht)->size * sizeof(int));
}
int main(){
hashtable *t = NULL;
init(&t);
t->table[2] = 3;
printf("t.size: %i \n", t->size);
printf("t.arr:[2] %i \n", t->table[2]);
free(t);
}

access element of struct passed into a void* pointer

I'm working with a binary search tree data structure to sort a series of structs with the type definitions:
typedef struct {
char c;
int index;
} data_t;
typedef struct node node_t;
typedef node {
void *data;
node_t *left;
node_t *right;
}
The node_t typedef is from a library provided to me for this purpose, presumably with a void* pointer to ensure polymorphism. node will be passed into the function:
static void
*recursive_search_tree(node_t *root,
void *key, int cmp(void*,void*))
Within the recursive_search_tree function, I want to be able to modify the code to use the index element as a condition to find the match closest to the index of the linear pass over an array of characters, which would ultimately involve a data_t being passed into *key and key->index being accessed within the function.
The Question
Is it possible to access key->index where key is a void* pointing to a data_t struct, or would this only be possible if data_t was declared as the type for key? I have tried to do the latter, however even casting the pointer to an int doesn't seem to pass the compiler.
Sure it's possible, you'd cast key as type *data_t. (As long as that's really what key points to!)
key /* argument of type void* */
(data_t*)key /* cast as type data_t* */
((data_t*)key)->index /* dereferenced */
Here is a simple example:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
char c;
int index;
} data_t;
typedef struct node {
void *data;
struct node *left;
struct node *right;
} node_t;
static int cmp(void *lhs, void *rhs)
{
return ((data_t *)lhs)->index - ((data_t *)rhs)->index;
}
int main(void)
{
data_t d0;
data_t d1;
d0.c = 'A';
d0.index = 1;
d1.c = 'B';
d1.index = 2;
printf("d0 < d1? %s\n", (cmp((void *)&d0, (void *)&d1) < 0 ? "yes" : "no"));
printf("d1 < d0? %s\n", (cmp((void *)&d1, (void *)&d0) < 0 ? "yes" : "no"));
return EXIT_SUCCESS;
}
This is type unsafe, as is any use of void. The use of void is generally because the intermediate is holding onto something it doesn't use for someone else's convenience.
This is a C function to let you hold whatever you want in a tree.
All it does is return whatever pointer you give it.
In your search function
int cmp(void* dt1, void* dt2)
{
data_t* data1 = (data_t*)dt1;
data_t* data2 = (data_t*)dt2;
/* Do what you need with data1 and data2 here */
}
Should let you do whatever you need. The problem you have is you need to cast your values inside the function. The parameters to cmp should exactly match the API for the library you are using, which says void* for the parameters.

Resources