void insertSkipList(SkipList* list, void* I){
Node* new_node=createNode(I, randomLevel(list->max_level));
if (new_node->size > list->max_level)
Node* actual_node=list->head;
unsigned int k;
for (k = list->max_level;k>=1;k--){
if (actual_node->next[k] == NULL || list->compare(I, actual_node->next[k]->item)<0){
if (k < new_node->size) {
new_node->next[k] = actual_node->next[k];
actual_node->next[k]=new_node;
}
else{
actual_node->next = &actual_node->next[k];
k=k+1;
}
}
}
}
I'm having troubles with the command list->compare(I, actual_node->next[k]->item
as it doesn't execute at all. The problem is most likely here actual_node->next[k]->item but I can't see why.
These are the definitions of node and list
typedef struct _SkipList SkipList;
typedef struct _Node Node;
struct _SkipList {
Node *head;
unsigned int max_level;
int (*compare)(void*, void*);
};
struct _Node {
Node **next;
unsigned int size;
void *item;
};
The complete minimal reproducible example contained within the question itself is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_LENGTH 20
#define MAX_HEIGHT 5
typedef struct _SkipList SkipList;
typedef struct _Node Node;
struct _SkipList {
Node *head;
unsigned int max_level;
int (*compare)(void*, void*);
};
struct _Node {
Node **next;
unsigned int size;
void *item;
};
unsigned int randomLevel(unsigned int height);
static int compare_int(void* x_void,void* y_void){
int x=(int)x_void;
int y=(int)y_void;
return x-y;
}
static Node* createNode(void* item, unsigned int lvl) {
Node* n = (Node*) malloc(sizeof(Node));
if(n == NULL) {
printf("\nError! Node memory not allocated.");
exit(0);
}
n->item = item;
n->next = NULL;
n->size = lvl;
return n;
}
SkipList* createSkipList(unsigned int height, int (*compare)(void*, void*)){
SkipList* skiplist = (SkipList*) malloc(sizeof(SkipList));
if(skiplist == NULL) {
printf("\nError! Skiplist memory not allocated.");
exit(0);
}
skiplist->head=createNode(NULL,height);
skiplist->max_level=1;
skiplist->compare=(*compare);
return skiplist;
}
void insertSkipList(SkipList* list, void* I){
Node* new_node=createNode(I, randomLevel(list->max_level));
if (new_node->size > list->max_level)
list->max_level = new_node->size;
Node* actual_node=list->head;
unsigned int k;
printf("here it's before the loop\n");
for (k = list->max_level;k>=1;k--){
if (actual_node->next[k] == NULL || list->compare(I, actual_node->next[k]->item)<0){ //here the code stops completely
if (k < new_node->size) {
new_node->next[k] = actual_node->next[k];
actual_node->next[k]=new_node;
}
}
else{
actual_node->next = &actual_node->next[k];
k=k+1;
}
}
printf("here it's after the loop (and actually this wont get printed idk why\n");
}
unsigned int randomLevel(unsigned int height){
unsigned int lvl = 1;
time_t t;
srand((unsigned) time(&t));
while (rand() < 0.5 && lvl < height)
lvl = lvl + 1;
return lvl;
}
int main() //creates a skiplist that goes from 0 to MAX_LENGTH
{
skiplist=createSkipList(MAX_HEIGHT,(*compare_int));
int found[MAX_LENGTH];
int expected[MAX_LENGTH];
for(int i=0;i<MAX_LENGTH;i++){
insertSkipList(skiplist,(void*) i);
}
return 0;
}
so basically I wrote a program to initialize, insert, and output the whole hash table. I thought I did pretty good, but there's many issues.
First issue being, some names are displayed with an additional weird character, why??
Second issue being, I can only input a size parameter (for initialize(size) function) of <8. Anything above 7 will output "Out of Space!" but why?? I thought I managed the space pretty well from what I was taught at uni:((
Please help!
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; i++)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr[i]=NULL;
}
return H;
}
position
set(const char *key, const char *value)
{
position entry = (position) malloc(sizeof(struct list_node));
entry->value = (char*) malloc(strlen(value)+1);
entry->key = (char*) malloc(strlen(key)+1);
strncpy(entry->key,key,strlen(key));
strncpy(entry->value,value,strlen(value));
entry->next = NULL;
return entry;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
node_ptr entry = H->list_ptr_arr[slot];
node_ptr prev;
if(entry==NULL)
{
H->list_ptr_arr[slot] = set(key, value);
return;
}
while(entry!=NULL)
{
if(strcmp(entry->key, key)==0)
{
free(entry->value);
entry->value = malloc(strlen(value)+1);
strncpy(entry->value,value,strlen(value));
return;
}
prev = entry;
entry = prev->next;
}
prev->next = set(key, value);
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
if(H->list_ptr_arr[i]==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", entry->key, entry->value);
if(entry->next == NULL)
{
printf("NULL");
break;
}
entry = entry->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(7);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Then I tried to change it up a bit:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!1"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!2"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; ++i)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!3"); return 0;}
H->list_ptr_arr[i]->value="HEAD";
H->list_ptr_arr[i]->next=NULL;
}
return H;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
LIST entry = H->list_ptr_arr[slot], newNode;
newNode = (position) malloc(sizeof(struct list_node));
if(newNode==NULL){printf("Out of Space4!"); return;}
newNode->next = entry->next;
strncpy(newNode->key,key,strlen(key));
strncpy(newNode->value,value,strlen(value));
entry->next = newNode;
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
position p = entry->next;
if(p==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", p->key, p->value);
if(p->next == NULL)
{
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Thank you!
I modified the second piece of code, it runs correctly on my computer.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 256
// typedefing struct list_node multiple times is confusing, so I remove these typedefs
struct list_node {
struct list_node *next;
// strings need storage space in the memory,
// declaring key and value as array here can save some calls to malloc()
char key[MAX_SIZE];
char value[MAX_SIZE];
};
struct hash_table {
struct list_node **list_ptr_arr;
unsigned int table_size;
};
// it's better not to hide pointer type using typedef
typedef struct hash_table HASHTABLE;
unsigned long long int hash(const char *key, unsigned int hash_size) {
// hash is not initialized originally (the value is choosed randomly)
unsigned long long int hash = 5;
for (int i = 0; key[i]; i++) {
hash = (hash << 32) + key[i];
}
return (hash%hash_size);
}
unsigned int next_prime(int number) {
int j;
for (int i = number; ; i++) {
for (j = 2; j < i; j++) {
if (i%j == 0) { break; }
}
if (i == j) { return j; }
}
}
HASHTABLE *initialize(unsigned int table_size) {
HASHTABLE *H;
// you don't need to type cast malloc() result in C
H = malloc(sizeof(*H));
H->table_size = next_prime(table_size);
// I suppose list_ptr_arr is a pointer to an array of struct list_node * object
H->list_ptr_arr = malloc(sizeof(*(H->list_ptr_arr)) * H->table_size);
for (unsigned int i = 0; i < H->table_size; ++i) {
// malloc() for H->list_ptr_arr only allocated area for struct list_node * array, the struct list_node pointed to is not allocated yet, so malloc() here
H->list_ptr_arr[i] = malloc(sizeof(*(H->list_ptr_arr[i])));
strcpy(H->list_ptr_arr[i]->value, "HEAD");
H->list_ptr_arr[i]->next = NULL;
}
return H;
}
void insert(const char *key, const char *value, HASHTABLE *H) {
unsigned int slot = hash(key, H->table_size);
struct list_node *entry = H->list_ptr_arr[slot], *newNode;
newNode = malloc(sizeof(*newNode));
newNode->next = entry->next;
// strlen() doesn't count the '\0', just use strcpy here
strcpy(newNode->key, key);
strcpy(newNode->value, value);
entry->next = newNode;
}
void dump(HASHTABLE *H) {
for (unsigned int i = 0; i < H->table_size; i++) {
struct list_node *entry = H->list_ptr_arr[i];
struct list_node *p = entry->next;
if (p == NULL) { continue; }
printf("slot[%d]: ", i);
for (;;) {
printf("%s|%s -> ", p->key, p->value);
if (p->next == NULL) {
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main() {
HASHTABLE *H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
P.S. Don't forget to free the hashtable.
I have a problem with my delete_table function. So i have 2 structs
struct _entry_ {
int key;
int data;
struct _entry_* next;
struct _entry_* prev;
};
typedef struct _entry_ entry;
struct _table_ {
entry** entries;
int size;
};
typedef struct _table_ table;
I initialise my table with calloc.
void table_init(table* ht, int initial_size) {
ht->entries = (entry**)calloc(initial_size, sizeof(entry*));
if (ht->entries) {
ht->size = initial_size;
}
}
Now my free function that i wrote
void table_destroy(htable* ht) {
entry *el, *temp;
int i;
for(i = 0; i < ht->size; i++) {
el = ht->entries[i];
while(el != NULL){
temp = el;
el = el->next;
free(temp);
}
free(ht->entries[i]);
}
free(ht); // <- don't know do i need this.
}
When i test it with valgrind i got this error
==13560== Invalid free() / delete / delete[] / realloc()
==13560== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13560== by 0x400783: htable_destroy (htable.c:46)
==13560== by 0x400A24: main (main.c:25)
==13560== Address 0xffefffae0 is on thread 1's stack
==13560== in frame #2, created by main (main.c:7)
Any help would be great, thank you for your time!
void table_destroy(htable* ht) {
entry *del;
int i;
for(i = 0; i < ht->size; i++) {
while( (del = ht->entries[i]) ) {
ht->entries[i] = del->next;
free(del);
}
}
free(ht->entries);
free(ht);
}
DoubleLinkedList.h
#ifndef _DOUBLE_LINKED_LIST_H
#define _DOUBLE_LINKED_LIST_H
typedef unsigned int uint;
typedef unsigned long ulong;
typedef void* Object;
typedef struct _DNode {
Object data;
struct _DNode* prev;
struct _DNode* next;
}DNode;
typedef struct _DoubleLinkedList{
DNode* head;
DNode* tail;
uint length;
uint elementSize;
}DoubleLinkedList;
DoubleLinkedList* allocDList (uint elementSize);
#endif
DoubleLinkedList.c
#include "DoubleLinkedList.h"
DoubleLinkedList* allocDList (uint elementSize)
{
DoubleLinkedList* l;
l->head = NULL;
l->tail = NULL;
l->length = 0;
l->elementSize = elementSize;
return l;
}
main.c
#include <stdio.h>
#include "DoubleLinkedList.h"
int main ()
{
DoubleLinkedList* ab;
ab = allocDList(10);
return 0;
}
When I try to run this I get a segmentation fault with a core dump.
this is what is required in the assignment.
DoubleLinkedList* allocDList(uint elementSize): this function allocates the DoubleLinkList
You haven't initialised l, so l->HEADwon't work. You can initialise it using malloc as:
DoubleLinkedList* l = malloc(sizeof(DoubleLinkedList));
Also, in the main function, once you are done using the variable ab, remember to release the memory used by it using the free function as follows:
int main ()
{
DoubleLinkedList* ab;
ab = allocDList(10);
//Processing here
free(ab); //Release once it is no longer needed
return 0;
}
DoubleLinkedList* l;
You need to allocate some memory to l
l = (DoubleLinkedList*) malloc(sizeof(DoubleLinkedList));
Update DoubleLinkedList.c as:
DoubleLinkedList* allocDList (uint elementSize)
{
DoubleLinkedList* l;
l = malloc(sizeof(DoubleLinkedList));
l->head = NULL;
l->tail = NULL;
l->length = 0;
l->elementSize = elementSize;
return l;
}
How can i access to a duble pointer in a struct pointer??
with the code bellow, calling addBow() give me a Segmentation fault (core dumped) error
typedef struct
{
int size;
tCity **cities;
}tGraph;
//para iniciar el grafo
void initGraph(tGraph *graph, int size)
{
graph = (tGraph*)malloc(sizeof(tGraph));
graph->cities = (tCity**)malloc(sizeof(tCity*) * size);
graph->size = size;
}
//agrega un arco entre ciudades
void addBow(tGraph *graph, int id, tCity *city)
{
if ( graph->cities[id] == NULL )
{
graph->cities[id] = city;
}
else
{
tCity *cur = graph->cities[id];
while ( getNext(cur) != NULL )
{
cur = getNext(cur);
}
setNext(cur, city);
}
}
which is the correct syntax for graph->cities[id]??
Thanks
SOLUTION:
editing the initGraph solve the problem since the memory wasn't allocated
tGraph* initGraph(int size)
{
tGraph *graph = (tGraph*)malloc(sizeof(tGraph));
graph->cities = (tCity**)malloc(sizeof(tCity*) * size);
graph->size = size;
return graph;
}
You should either have initGraph() take (**graph) or return the graph. Since the malloc address of graph is local to initGraph.
Something like:
void initGraph(tGraph **graph, int size)
{
tgraph *temp;
temp = (tGraph*)malloc(sizeof(tGraph*));
temp->cities = (tCity**)malloc(sizeof(tCity*) * size);
temp->size = size;
*graph = temp;
}
graph = (tGraph*)malloc(sizeof(tGraph*));
There is one of your problems...
it should be
graph = malloc(sizeof(tGraph));
Make initGraph () return a pointer to tGraph.
tGraph* initGraph(int size) {
tGraph* graph;
graph = malloc(sizeof(tGraph));
graph->cities = malloc(sizeof(tCity*) * size);
graph->size = size;
return graph;
}
//consider this example
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct test{
int val;
}test;
typedef struct data{
char ch[10];
test **p;
}data;
int main(){
data *d=malloc(sizeof(data));
strcpy(d->ch,"hello");
d->p=(test**)malloc(sizeof(test*));
d->p[0]=(test*)malloc(sizeof(test));
d->p[0]->val=10;
printf("%s,%d",d->ch,d->p[0]->val);
}