Getting "misaligned address" trying to solve leetcode problem: 217. Contains Duplicate - c

I am new to the concept of a hash table (just learned it today) so I am trying to implement it all by myself before using some sort of library or other programming language syntax to help me. The code below tries to solve the following problem: Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.
typedef struct node{
int n;
struct node *next;
}
node;
int hash(int i) {
return abs((i*2654435761)%1024);
}
void unloadBucket(node *at) {
if(at->next != NULL) {
unloadBucket(at->next);
}
free(at);
}
bool containsDuplicate(int* nums, int numsSize){
node *table[1024];
// Load buckets of hash table
for(int i = 0; i < 1024; i++) {
table[i] = malloc(sizeof(node));
table[i]->n = 0;
table[i]->next = NULL;
}
for(int i = 0; i < numsSize; i++) {
int key = hash(nums[i]);
node *at = table[key];
while(at->next != NULL) {
if(at->n == nums[i])
return true;
else
at = at->next;
}
at->n = nums[i];
at->next = malloc(sizeof(node));
}
// Unload buckets
for(int i = 0; i < 1024; i++) {
unloadBucket(table[i]);
}
return false;
}
And here is the error message that leetcode is returning to me:
Line 12: Char 10: runtime error: member access within misaligned address 0xbebebebebebebebe for type 'struct node', which requires 8 byte alignment [solution.c]
0xbebebebebebebebe: note: pointer points here
<memory cannot be printed>
Originally, i was getting the same error message at line 25, since I thought it was a memory leak problem I added the unloadBucket function that got the same error...

Related

Singly linked list create function C

I am currently trying to make function create() for singly linked list, where I am supposed to pass unlimited amount of parameters and it will pass the parameters as nodes' values. The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//define sllnode struct
typedef struct sllist
{
int val;
struct sllist *next;
}
sllnode;
sllnode* create(int count, ...);
int main(void)
{
//here i try to print out values of this list
sllnode* new_sllist = create(34,2,5,18);
//print out values that I have assign using create() to test
for(int i = 0; i < 4; i++)
{
printf("%i\n",new_sllist[i].val);
}
}
//create function
sllnode* create(int count, ...)
{
va_list list;
int i;
int arr[count];
va_start(list, count);
//create array arr that have all the values passed as parameters
for(i = 0; i < count; i++)
{
arr[i] = va_arg(list,int);
}
//allocate memory for new singly linked list
sllnode *sllist = malloc(count * sizeof(sllnode));
//check if memory has been successfully allocated
if(sllist == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// loop through array arr and assign values to val and *next of each sllnode in new sllist
for (int j = 0; j < count; j++)
{
sllist[j].val = arr[j];
sllist[j].next = &sllist[j+1];
if(j == count - 1)
{
sllist[j].val = arr[j];
sllist[j].next = NULL;
}
}
return sllist;
free(sllist);
}
But when I print out I only receive the last 3 values (2,5,18) and a number -23791193490 which differs each time (I suppose this has seeped into another part of memory). How do I do this correctly?
You are passing 34 for the count parameter. Correct usage would be:
sllnode* new_sllist = create(4,34,2,5,18);

how to initializing a hash table in C

I have a program in C that creates a hash table.
memset is Okay but, i want to initialize with for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HSZ 127
#define HASHING(x) ((x)%HSZ)
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
void init(void){
int i;
//memset(hash_table,0,sizeof(hash_table));
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
}
void insert_hash(int value){
int key = HASHING(value);
struct node_t *newNode = (struct node_t*)malloc(sizeof(struct node_t));
newNode->val = value;
newNode->next = NULL;
if(hash_table[key] == NULL){
hash_table[key] = newNode;
} else {
newNode->next = hash_table[key];
hash_table[key] = newNode;
}
}
int delete_hash(int value){
int key = HASHING(value);
if (hash_table[key] == NULL)
return 0;
struct node_t *delNode = NULL;
if (hash_table[key]->val == value){
delNode = hash_table[key];
hash_table[key] = hash_table[key]->next;
} else {
struct node_t *node = &hash_table[key];
struct node_t *next = hash_table[key]->next;
while (next){
if (next->val == value){
node->next = next->next;
delNode = next;
break;
}
node = next;
next = node->next;
}
}
return 1;
free(delNode);
}
void PrintAllHashData()
{
printf("###Print All Hash Data###\n");
for (int i = 0; i < HSZ; i++){
if (hash_table[i] != NULL){
printf("idx : %d ", i);
struct node_t *node = hash_table[i];
while (node->next){
printf("%d ", node->val);
node = node->next;
}
printf("%d\n", node->val);
}
}
}
int main(void){
init();
insert_hash(1);
insert_hash(3);
insert_hash(128);
PrintAllHashData();
}
look at this code.
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
The IDE I am using does not throw up a compilation error when I compile the code, but during the execution the code faults and is terminated/haulted. I tried debugging the code, it faults at this line and is stopped, I think BAD ACCESS points to Segmentation Error.
then, I changed this line to
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
but, then I got the compilation error stating 'structure type require instead of 'struct node_t *'
I think that I don't understand clearly about struct in C.
How to fix this problem?
What you are dealing with is Undefined Behavior.
See, struct node_t *hash_table[HSZ];
So, hash_table is an array of HSZ (127) pointers of the data type struct node_t.
When you do,
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
hash_table[0] to hash_table[126] pointers are not pointing to anything.
So, each of them (or all of them) should be initialized first to point to an object of the type struct node_t and then you can initialize them. For that matter, Using a memset does not cause a problem because memset is filling the contents of the pointers with all zeros. There is difference between filling the pointers with all zeros and filling all zeros to the memory pointed by pointers.
Trying this,
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
is plain wrong.
To fix the issue you are facing, you need to allocate memory dynamically using malloc. You can do the in your for loop.
for(i = 0; i < HSZ; i++)
{
//Allocate memory of the size struct_node_t
hash_table[i] = malloc(sizeof(struct node_t)); //Do not cast!
//Check if memory is allocated
if(hash_table[i] == NULL)
{
//Memory not allocated, set some error state to handle and break
break;
}
//Initialize to zero
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
when you have *hash_table[HSZ], this varible hash_table is a pointer. so whatever your action is , use hash_table-> ,syntax for pointer, mean point to somewhere.
a suggestion that when you use pointer you should always allocate memory hash_table[i] = malloc(sizeof(struct node_t));
struct node_t hash_table;
but if you initilize your varible like this, you can use hash_table.val = 0
so the way of assign value depend on how you declare your varibles
struct node_t *hash_table[HSZ];
gives you an array of pointers that are unset (i.e. not pointing to anything)
void init(void) {
int i;
// memset(hash_table,0,sizeof(hash_table));
for (i = 0; i < HSZ; i++) {
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
tries writing to your invalid pointers which gives undefined behavior.
Either make the array an array of structs (instead of pointers):
struct node_t hash_table[HSZ];
...
/* note use of . instead of -> since we have structs not pointers */
hash_table[i].val = 0;
or allocate the necessary structs so the array points to something:
for (i = 0; i < HSZ; i++) {
hash_table[i] = malloc(sizeof(struct node_t));
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}

Counting the nodes of any tree time improvement

I have to make a function which counts how many elements my tree have. My tree is not binary, is the most general kind of tree.
The node is:
typedef struct node{
char item;
int number_of_sons;
node **sons;
}
My counting function is this
void numbering(node *HT,int ok=0)
{
static int number = 0;
if (ok == 1)
{
printf("%d", number);
return;
}
if (HT == NULL)
{
return;
}
else
{
number++;
for (int i = 0;i < HT->nr_of_sons;i++)
{
numbering(HT->next[i], 0);
}
}
}
Is there a way to improve this function to make this faster?
EDIT: the way I use this function is:
int main()
{
//create tree;
numbering(tree,0);
numbering(tree,1);
}
When I call the function the second time it prints my result
You have a very strange recursive function there--you're using a static variable in the function which is never reset, so the function can only be used once per program run!
I'd rewrite it this way:
size_t nodecount(node *root)
{
size_t count = 0;
if (root)
{
count++;
for (int i = 0; i < root->nr_of_sons; i++)
{
count += nodecount(root->sons[i]);
}
}
return count;
}
If you really want to speed things up, you could augment your node structure by adding a size_t subtree_count field which you'd maintain whenever you insert or remove nodes. Another idea is to compact the pointer-to-array-of-sons into the node structure directly:
typedef struct node{
char item;
int number_of_sons;
node_t *sons[0];
} node_t;
What I've done here is made it so the sons variable is an array rather than a pointer to an array. But it has size zero (n.b. use [] or [1] if your compiler requires), because you don't know the number of sons at compile time. But you can simply allocate nodes with the right amount of space:
node_t* tree = (node_t*)malloc(sizeof(node_t) + num_sons*sizeof(node_t*));
This reduces pointer indirection by one layer, which may help performance.
Maybe this is better and more efficient:
int numbering(node *HT)
{
if (!HT)
{
return 0;
}
int num = 1;
for (int i = 0;i < HT->nr_of_sons;i++)
{
num += numbering(HT->next[i]);
}
return num;
}
I deleted your ok variable and changed the returned value from void to int.
In the case base you return 0;
For the leaf so they will return 1;
For inner nodes they will return 1 + the numbers of nodes in the
subtree.

Error in implementation of a stack with O(1) find-max/find-min?

I have implemented several functions for the Stack ADT. I am trying to find the max and min values in O(1) time and I have augmented my stack structure to serve this purpose. This is my code:
void mms_push(MMStack mms, int i) {
struct llnode *new = malloc(sizeof(struct llnode));
new->item = i;
if(mms->len!=0)
{
new->next = mms->topnode;
mms->topnode = new;
}
else
{
new->next = NULL;
mms->topnode = new;
}
if (mms->len == 0)
{
mms->topnode->minc = i;
mms->topnode->maxc = i;}
else
{
if(mms->topnode->maxc < i)
{
mms->topnode->maxc = i;
}
if(i<mms->topnode->minc)
{
mms->topnode->minc = i;
}
mms->len++;}
int mms_pop(MMStack mms) {
assert(mms);
int ret = mms->topnode->item;
struct llnode *backup = mms->topnode;
mms->topnode = mms->topnode->next;
mms->len--;
free(backup);
return ret;
}
My structures used are as below:
struct llnode
{
int item;
struct llnode *next;
int minc;
int maxc;
};
struct mmstack
{
int len ;
struct llnode *topnode;
};
typedef struct mmstack *MMStack;
I am not getting the correct value of max and min values. How do I correct the code so that I get the right value of max and min element in the stack?
Thanks in advance!
Take a look at this code:
if (mms->len == 0)
{
mms->topnode->minc = i;
mms->topnode->maxc = i;
}
else
{
if(mms->topnode->maxc < i)
{
mms->topnode->maxc = i;
}
if(i<mms->topnode->minc)
{
mms->topnode->minc = i;
}
}
Notice that in the else branch, you're reading the values of mms->topnode->minc and mms->topnode->maxc before you've initialized them. I think you meant to look at the values of mms->topnode->minc/maxc before you reassigned mms->topnode. To fix this, try doing something like this:
else
{
mms->topnode->maxc = mms->topnode->next->maxc;
mms->topnode->minc = mms->topnode->next->minc;
if(mms->topnode->maxc < i)
{
mms->topnode->maxc = i;
}
if(i<mms->topnode->minc)
{
mms->topnode->minc = i;
}
}
These extra two lines initialize the min and max values to the old max values before comparing against i, which should ensure that they get a value.
Hope this helps!
You're doing things a bit backwards — comparing i to the values in the new, uninitialised node after you have inserted it in the stack.
It's easier to first prepare the new node completely, and then link it into the stack.
Assuming that an empty stack has a NULL topnode:
void mms_push(MMStack mms, int i) {
struct llnode *new = malloc(sizeof(struct llnode));
new->item = i;
new->next = mms->topnode;
if (!mms->topnode)
{
new->minc = i;
new->maxc = i;
}
else
{
new->minc = min(mms->topnode->minc, i);
new->maxc = max(mms->topnode->maxc, i);
}
mms->topnode = new;
mms->len++;
}
I'm not sure if min and max are C99, but they're trivial to define.

C Having Trouble with Pointer Incrementing (I think)

Quite a simple error I guess but I get this error when trying to compile my C code:
error: expected identifier before '(' token
From this code where I am trying to set up structs for a hash table with linked lists for hash collisions:
typedef struct bN {
MEntry nestedEntry;
struct bN *next;
} bucketNode;
typedef struct bL {
bucketNode *first;
int bucketSize;
} bucket;
struct mlist {
bucket *currentTable;
};
And this code where I actually initialise the linked list:
MList *ml_create(void){
MList *temp;
if (ml_verbose){
fprintf(stderr, "mlist: creating mailing list\n");
}
if ((temp = (MList *)malloc(sizeof(MList))) != NULL){
temp->currentTable = (bucket *)malloc(tableSize * sizeof(bucket));
int i;
for(i = 0; i < tableSize; i++){
temp->(currentTable+i)->first = NULL; /**ERROR HERE*/
temp->(currentTable+i)->bucketSize = 0; /**ERROR HERE*/
}
}
return temp;
}
Your syntax is off. You mean:
temp->currentTable[i].first = NULL;
temp->currentTable[i].bucketSize = 0;
Change
temp->(currentTable+i)->first = NULL;
to be
(temp->currentTable+i)->first = NULL;

Resources